commit 5f5599009c564b0385776c2cc966e78ab42990af Author: mynameisdeleted Date: Thu Jul 9 08:05:08 2026 -0400 Add Rust and C++ linked list implementations with build/debug configs Rust version in src/main.rs (Cargo project) and a C++ port in cpp/main.cpp using raw pointers, both with VS Code build tasks and gdb-based debug configs. Vendors vscode-debug-visualizer and visualization as submodules for reference while building a custom node-table graph visualizer. Co-Authored-By: Claude Sonnet 5 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..326b1f7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +/cpp/list_example_cpp diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..bf610b1 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "external/vscode-debug-visualizer"] + path = external/vscode-debug-visualizer + url = https://github.com/hediet/vscode-debug-visualizer.git +[submodule "external/visualization"] + path = external/visualization + url = https://github.com/hediet/visualization.git diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..f714eed --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,57 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug list_example (Rust)", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/target/debug/list_example", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "miDebuggerPath": "/usr/bin/rust-gdb", + "preLaunchTask": "cargo build", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + }, + { + "name": "Debug list_example (C++)", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/cpp/list_example_cpp", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}/cpp", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "miDebuggerPath": "/usr/bin/gdb", + "preLaunchTask": "g++ build cpp/main.cpp", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "description": "Don't truncate long arrays (needed for Debug Visualizer JSON)", + "text": "-gdb-set print elements 0", + "ignoreFailures": true + }, + { + "description": "Don't truncate long strings (needed for Debug Visualizer JSON)", + "text": "-gdb-set print characters 0", + "ignoreFailures": true + } + ] + } + ] +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..436335d --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,35 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "cargo build", + "type": "shell", + "command": "cargo", + "args": ["build"], + "group": { + "kind": "build", + "isDefault": true + }, + "problemMatcher": ["$rustc"] + }, + { + "label": "g++ build cpp/main.cpp", + "type": "cppbuild", + "command": "/usr/bin/g++", + "args": [ + "-std=c++17", + "-g", + "-Wall", + "-Wextra", + "${workspaceFolder}/cpp/main.cpp", + "-o", + "${workspaceFolder}/cpp/list_example_cpp" + ], + "options": { + "cwd": "${workspaceFolder}/cpp" + }, + "group": "build", + "problemMatcher": ["$gcc"] + } + ] +} diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..fa88d3f --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "list_example" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..21e11bf --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "list_example" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/cpp/main.cpp b/cpp/main.cpp new file mode 100644 index 0000000..d88b680 --- /dev/null +++ b/cpp/main.cpp @@ -0,0 +1,100 @@ +#include +#include +#include + +// A single node containing data and a raw pointer to the next node +template +struct Node { + T data; + Node* next; +}; + +// The main wrapper for the linked list tracking the head node +template +class LinkedList { +public: + LinkedList() : head_(nullptr) {} + + ~LinkedList() { + Node* current = head_; + while (current) { + Node* 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{std::move(data), head_}; + } + + // Remove and return the front element of the list + std::optional pop_front() { + if (!head_) { + return std::nullopt; + } + Node* 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 as a graph, for the VS Code + // "Debug Visualizer" extension: watch `list.toDebugGraph()` while paused. + // Schema: https://hediet.github.io/visualization/docs/visualization-data-schema.json + std::string toDebugGraph() const { + std::ostringstream json; + json << "{\"kind\":{\"graph\":true},\"nodes\":["; + for (Node* n = head_; n; n = n->next) { + if (n != head_) json << ","; + json << "{\"id\":\"" << n << "\",\"label\":\"" << n->data << "\"}"; + } + json << "],\"edges\":["; + for (Node* n = head_; n && n->next; n = n->next) { + if (n != head_) json << ","; + json << "{\"from\":\"" << n << "\",\"to\":\"" << n->next << "\"}"; + } + json << "]}"; + return json.str(); + } + +private: + Node* 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 main() { + LinkedList 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; +} diff --git a/external/visualization b/external/visualization new file mode 160000 index 0000000..9e6dc9a --- /dev/null +++ b/external/visualization @@ -0,0 +1 @@ +Subproject commit 9e6dc9a5add14fe6468ac761ceea0aede2bb1de6 diff --git a/external/vscode-debug-visualizer b/external/vscode-debug-visualizer new file mode 160000 index 0000000..96c26e5 --- /dev/null +++ b/external/vscode-debug-visualizer @@ -0,0 +1 @@ +Subproject commit 96c26e5388eda9ed81a488f1d95a26a9af166214 diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..751ef86 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,57 @@ +// A single node containing data and an optional pointer to the next node +struct Node { + data: T, + next: Option>>, +} + +// The main wrapper for the linked list tracking the head node +pub struct LinkedList { + head: Option>>, +} + +impl LinkedList { + // Create an empty linked list + pub fn new() -> Self { + LinkedList { head: None } + } + + // Add a new element to the front of the list + pub fn push_front(&mut self, data: T) { + let new_node = Box::new(Node { + data, + // .take() temporarily leaves None in self.head and extracts the value + next: self.head.take(), + }); + self.head = Some(new_node); + } + + // Remove and return the front element of the list + pub fn pop_front(&mut self) -> Option { + self.head.take().map(|node| { + self.head = node.next; + node.data + }) + } + + // Read the front element without removing it + pub fn peek_front(&self) -> Option<&T> { + self.head.as_ref().map(|node| &node.data) + } +} + +fn main() { + let mut list = LinkedList::new(); + + // Demonstrate pushing items + list.push_front(10); + list.push_front(20); + list.push_front(30); + + // Demonstrate peaking at the top item + println!("Top element: {:?}", list.peek_front()); // Output: Some(30) + + // Demonstrate popping items + while let Some(value) = list.pop_front() { + println!("Popped: {}", value); + } +} \ No newline at end of file