Files
visual_debugger/cpp/main.cpp

106 lines
3.1 KiB
C++

#include <iostream>
#include <optional>
#include <sstream>
// A single node containing data and a raw pointer to the next node
template <typename T>
struct Node {
T data;
Node<T>* next;
};
// The main wrapper for the linked list tracking the head node
template <typename T>
class LinkedList {
public:
LinkedList() : head_(nullptr) {}
~LinkedList() {
Node<T>* current = head_;
while (current) {
Node<T>* next = current->next;
delete current;
current = next;
}
}
// Raw-pointer ownership can't be safely duplicated by a shallow copy
LinkedList(const LinkedList&) = delete;
LinkedList& operator=(const LinkedList&) = delete;
// Add a new element to the front of the list
void push_front(T data) {
head_ = new Node<T>{std::move(data), head_};
}
// Remove and return the front element of the list
std::optional<T> pop_front() {
if (!head_) {
return std::nullopt;
}
Node<T>* old_head = head_;
T data = std::move(old_head->data);
head_ = old_head->next;
delete old_head;
return data;
}
// Read the front element without removing it
const T* peek_front() const {
return head_ ? &head_->data : nullptr;
}
// Build a JSON string describing the list for the VS Code "Debug
// Visualizer" extension's custom "node table" view (see
// vis-plugins/node-table-visualizer.js): watch `list.toDebugGraph()`
// while paused. Each node is rendered as its own address-labeled box
// with a field table -- data as a plain value, next as a hex pointer.
std::string toDebugGraph() const {
std::ostringstream json;
json << "{\"kind\":{\"nodeTable\":true},\"nodes\":[";
for (Node<T>* n = head_; n; n = n->next) {
if (n != head_) json << ",";
json << "{\"id\":\"" << n << "\",\"fields\":["
<< "{\"name\":\"data\",\"value\":\"" << n->data << "\"},"
<< "{\"name\":\"next\",\"value\":\"" << n->next << "\",\"isPointer\":true}"
<< "]}";
}
json << "],\"edges\":[";
for (Node<T>* n = head_; n && n->next; n = n->next) {
if (n != head_) json << ",";
json << "{\"from\":\"" << n << "\",\"to\":\"" << n->next << "\",\"label\":\"next\"}";
}
json << "]}";
return json.str();
}
private:
Node<T>* head_;
};
// Force instantiation of every member, including toDebugGraph(), which
// nothing in this file calls directly -- without this, gdb has no symbol
// to invoke from the debugger's watch expression.
template class LinkedList<int>;
int main() {
LinkedList<int> list;
// Demonstrate pushing items
list.push_front(10);
list.push_front(20);
list.push_front(30);
// Demonstrate peeking at the top item
if (const int* top = list.peek_front()) {
std::cout << "Top element: " << *top << "\n"; // Output: 30
}
// Demonstrate popping items
while (auto value = list.pop_front()) {
std::cout << "Popped: " << *value << "\n";
}
return 0;
}