From b1a076d967e2d843c786921dbbbb6cb081df8363 Mon Sep 17 00:00:00 2001 From: Ernie Pasveer Date: Sun, 28 Aug 2022 14:03:10 -0500 Subject: [PATCH] VarObj: Handle link lists. --- src/CMakeLists.txt | 2 + src/QEditDelegate.cpp | 31 ++++++ src/QEditDelegate.h | 27 ++++++ src/SeerGdbWidget.cpp | 10 ++ src/SeerGdbWidget.h | 1 + src/SeerRegisterValuesBrowserWidget.cpp | 13 ++- src/SeerRegisterValuesBrowserWidget.h | 34 ------- src/SeerVarVisualizerWidget.cpp | 107 ++++++++++++++++----- src/SeerVarVisualizerWidget.h | 6 +- src/SeerVarVisualizerWidget.ui | 13 ++- tests/hellolinklist/DEBUG | 81 ++++++++++++++++ tests/hellolinklist/hellolinklist.cpp | 119 ++++++++++++++++++------ 12 files changed, 350 insertions(+), 94 deletions(-) create mode 100644 src/QEditDelegate.cpp create mode 100644 src/QEditDelegate.h create mode 100644 tests/hellolinklist/DEBUG diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e08cf92..eec78e0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -98,6 +98,7 @@ set(HEADER_FILES QIndexTreeWidget.h QStringPair.h QHistoryLineEdit.h + QEditDelegate.h ) set(SOURCE_FILES @@ -178,6 +179,7 @@ set(SOURCE_FILES QClearLineEdit.cpp QIndexTreeWidget.cpp QHistoryLineEdit.cpp + QEditDelegate.cpp ) qt5_add_resources(SOURCE_FILES resource.qrc) diff --git a/src/QEditDelegate.cpp b/src/QEditDelegate.cpp new file mode 100644 index 0000000..cec2e82 --- /dev/null +++ b/src/QEditDelegate.cpp @@ -0,0 +1,31 @@ +#include "QEditDelegate.h" + +// +// QAllowEditDelegate enables a custom editor for a QTreeView column. +// +QAllowEditDelegate::QAllowEditDelegate(QObject* parent) : QStyledItemDelegate(parent) { +} + +void QAllowEditDelegate::setModelData (QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const { + + QStyledItemDelegate::setModelData(editor, model, index); + + emit editingFinished(index); +} + +// +// QNoEditDelegate disables editing in a QTreeView for a column. +// It does this by returning a 'null' editor when QTreeView calls QStyledItemDelegate::createEditor() for the cell. +// +QNoEditDelegate::QNoEditDelegate(QObject* parent) : QStyledItemDelegate(parent) { +} + +QWidget* QNoEditDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const { + + Q_UNUSED(parent); + Q_UNUSED(option); + Q_UNUSED(index); + + return 0; +} + diff --git a/src/QEditDelegate.h b/src/QEditDelegate.h new file mode 100644 index 0000000..e91678d --- /dev/null +++ b/src/QEditDelegate.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include + +class QAllowEditDelegate : public QStyledItemDelegate { + + Q_OBJECT + + public: + QAllowEditDelegate(QObject* parent = nullptr); + + virtual void setModelData (QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const; + + signals: + void editingFinished (const QModelIndex& ) const; +}; + +class QNoEditDelegate : public QStyledItemDelegate { + + public: + QNoEditDelegate(QObject* parent = nullptr); + + virtual QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const; +}; + diff --git a/src/SeerGdbWidget.cpp b/src/SeerGdbWidget.cpp index b6625ae..1e9a0c0 100644 --- a/src/SeerGdbWidget.cpp +++ b/src/SeerGdbWidget.cpp @@ -1545,6 +1545,15 @@ void SeerGdbWidget::handleGdbVarObjUpdate (int expressionid, QString objname) { handleGdbCommand(QString("%1-var-update --all-values \"%2\"").arg(expressionid).arg(objname)); } +void SeerGdbWidget::handleGdbVarObjAssign (int expressionid, QString objname, QString value) { + + if (executableLaunchMode() == "") { + return; + } + + handleGdbCommand(QString("%1-var-assign \"%2\" %3").arg(expressionid).arg(objname).arg(value)); +} + void SeerGdbWidget::handleGdbVarObjDelete (int expressionid, QString objname) { if (executableLaunchMode() == "") { @@ -1758,6 +1767,7 @@ void SeerGdbWidget::handleGdbVarAddExpression (QString expression) { QObject::connect(w, &SeerVarVisualizerWidget::varObjCreate, this, &SeerGdbWidget::handleGdbVarObjCreate); QObject::connect(w, &SeerVarVisualizerWidget::varObjListChildren, this, &SeerGdbWidget::handleGdbVarObjListChildren); QObject::connect(w, &SeerVarVisualizerWidget::varObjUpdate, this, &SeerGdbWidget::handleGdbVarObjUpdate); + QObject::connect(w, &SeerVarVisualizerWidget::varObjAssign, this, &SeerGdbWidget::handleGdbVarObjAssign); QObject::connect(w, &SeerVarVisualizerWidget::varObjDelete, this, &SeerGdbWidget::handleGdbVarObjDelete); QObject::connect(w, &SeerVarVisualizerWidget::addMemoryVisualize, this, &SeerGdbWidget::handleGdbMemoryAddExpression); QObject::connect(w, &SeerVarVisualizerWidget::addArrayVisualize, this, &SeerGdbWidget::handleGdbArrayAddExpression); diff --git a/src/SeerGdbWidget.h b/src/SeerGdbWidget.h index 3ee7ba7..c9a2bff 100644 --- a/src/SeerGdbWidget.h +++ b/src/SeerGdbWidget.h @@ -209,6 +209,7 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm { void handleGdbVarObjCreate (int expressionid, QString expression); void handleGdbVarObjListChildren (int expressionid, QString objname); void handleGdbVarObjUpdate (int expressionid, QString objname); + void handleGdbVarObjAssign (int expressionid, QString objname, QString value); void handleGdbVarObjDelete (int expressionid, QString objname); void handleGdbDataListValues (); void handleGdbDataListExpressions (); diff --git a/src/SeerRegisterValuesBrowserWidget.cpp b/src/SeerRegisterValuesBrowserWidget.cpp index 580521e..1a95178 100644 --- a/src/SeerRegisterValuesBrowserWidget.cpp +++ b/src/SeerRegisterValuesBrowserWidget.cpp @@ -1,6 +1,7 @@ #include "SeerRegisterValuesBrowserWidget.h" #include "SeerRegisterEditValueDialog.h" #include "SeerUtl.h" +#include "QEditDelegate.h" #include #include #include @@ -31,17 +32,17 @@ SeerRegisterValuesBrowserWidget::SeerRegisterValuesBrowserWidget (QWidget* paren registerFormatComboBox->addItem("Raw", QVariant("r")); // Create edit delegate. - MyEditingDelegate* editDelegate = new MyEditingDelegate(this); + QAllowEditDelegate* editDelegate = new QAllowEditDelegate(this); - registersTreeWidget->setItemDelegateForColumn(0, new MyNoEditDelegate(this)); - registersTreeWidget->setItemDelegateForColumn(1, new MyNoEditDelegate(this)); + registersTreeWidget->setItemDelegateForColumn(0, new QNoEditDelegate(this)); + registersTreeWidget->setItemDelegateForColumn(1, new QNoEditDelegate(this)); registersTreeWidget->setItemDelegateForColumn(2, editDelegate); - registersTreeWidget->setItemDelegateForColumn(3, new MyNoEditDelegate(this)); + registersTreeWidget->setItemDelegateForColumn(3, new QNoEditDelegate(this)); // Connect things. QObject::connect(registersTreeWidget, &QTreeWidget::itemEntered, this, &SeerRegisterValuesBrowserWidget::handleItemEntered); QObject::connect(registersTreeWidget, &QTreeWidget::customContextMenuRequested, this, &SeerRegisterValuesBrowserWidget::handleContextMenu); - QObject::connect(editDelegate, &MyEditingDelegate::editingFinished, this, &SeerRegisterValuesBrowserWidget::handleIndexEditingFinished); + QObject::connect(editDelegate, &QAllowEditDelegate::editingFinished, this, &SeerRegisterValuesBrowserWidget::handleIndexEditingFinished); QObject::connect(registerFormatComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &SeerRegisterValuesBrowserWidget::handleFormatChanged); } @@ -208,8 +209,6 @@ void SeerRegisterValuesBrowserWidget::handleItemEntered (QTreeWidgetItem* item, Q_UNUSED(column); - //qDebug() << item->text(0) << column; - item->setToolTip(0, item->text(1) + " : " + item->text(2)); for (int i=1; icolumnCount(); i++) { // Copy tooltip to other columns. diff --git a/src/SeerRegisterValuesBrowserWidget.h b/src/SeerRegisterValuesBrowserWidget.h index 3382391..5ae35bf 100644 --- a/src/SeerRegisterValuesBrowserWidget.h +++ b/src/SeerRegisterValuesBrowserWidget.h @@ -2,43 +2,9 @@ #include "ui_SeerRegisterValuesBrowserWidget.h" #include -#include -#include #include #include -class MyEditingDelegate : public QStyledItemDelegate { - - Q_OBJECT - - public: - MyEditingDelegate(QObject* parent = nullptr) : QStyledItemDelegate(parent) {} - - virtual void setModelData (QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const { - - QStyledItemDelegate::setModelData(editor, model, index); - - emit editingFinished(index); - } - - signals: - void editingFinished(const QModelIndex& ) const; -}; - -class MyNoEditDelegate: public QStyledItemDelegate { - public: - MyNoEditDelegate(QObject* parent = nullptr): QStyledItemDelegate(parent) {} - - virtual QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const { - - Q_UNUSED(parent); - Q_UNUSED(option); - Q_UNUSED(index); - - return 0; - } -}; - class SeerRegisterValuesBrowserWidget : public QWidget, protected Ui::SeerRegisterValuesBrowserWidgetForm { Q_OBJECT diff --git a/src/SeerVarVisualizerWidget.cpp b/src/SeerVarVisualizerWidget.cpp index d72250e..aa46d0a 100644 --- a/src/SeerVarVisualizerWidget.cpp +++ b/src/SeerVarVisualizerWidget.cpp @@ -1,5 +1,6 @@ #include "SeerVarVisualizerWidget.h" #include "SeerUtl.h" +#include "QEditDelegate.h" #include #include #include @@ -24,10 +25,9 @@ SeerVarVisualizerWidget::SeerVarVisualizerWidget (QWidget* parent) : QWidget(par setAttribute(Qt::WA_DeleteOnClose); variableNameLineEdit->setFocus(); - variableTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu); variableTreeWidget->setMouseTracking(true); variableTreeWidget->setSortingEnabled(false); - variableTreeWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); + variableTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu); variableTreeWidget->setRootIsDecorated(true); variableTreeWidget->setItemsExpandable(true); variableTreeWidget->resizeColumnToContents(0); // variable @@ -40,21 +40,38 @@ SeerVarVisualizerWidget::SeerVarVisualizerWidget (QWidget* parent) : QWidget(par variableTreeWidget->resizeColumnToContents(7); // has_more variableTreeWidget->clear(); - detailedCheckBox->setChecked(false); + debugCheckBox->setChecked(false); + + // Create edit delegate. + // The value column will allow editing of the cell. However, some cells can then + // individually disable it again. ie: If the cell is for a node, not a value. + // See 'new QTreeWidgetItem' + QAllowEditDelegate* editDelegate = new QAllowEditDelegate(this); + + variableTreeWidget->setItemDelegateForColumn(0, new QNoEditDelegate(this)); + variableTreeWidget->setItemDelegateForColumn(1, editDelegate); + variableTreeWidget->setItemDelegateForColumn(2, new QNoEditDelegate(this)); + variableTreeWidget->setItemDelegateForColumn(3, new QNoEditDelegate(this)); + variableTreeWidget->setItemDelegateForColumn(4, new QNoEditDelegate(this)); + variableTreeWidget->setItemDelegateForColumn(5, new QNoEditDelegate(this)); + variableTreeWidget->setItemDelegateForColumn(6, new QNoEditDelegate(this)); + variableTreeWidget->setItemDelegateForColumn(6, new QNoEditDelegate(this)); + // Connect things. QObject::connect(expandAllToolButton, &QToolButton::clicked, this, &SeerVarVisualizerWidget::handleExpandAllButton); QObject::connect(collapseAllToolButton, &QToolButton::clicked, this, &SeerVarVisualizerWidget::handleCollapseAllButton); QObject::connect(refreshToolButton, &QToolButton::clicked, this, &SeerVarVisualizerWidget::handleRefreshButton); - QObject::connect(detailedCheckBox, &QCheckBox::clicked, this, &SeerVarVisualizerWidget::handleDetailedCheckBox); + QObject::connect(debugCheckBox, &QCheckBox::clicked, this, &SeerVarVisualizerWidget::handleDebugCheckBox); QObject::connect(variableNameLineEdit, &QLineEdit::returnPressed, this, &SeerVarVisualizerWidget::handleVariableNameLineEdit); QObject::connect(variableTreeWidget, &QTreeWidget::customContextMenuRequested, this, &SeerVarVisualizerWidget::handleContextMenu); QObject::connect(variableTreeWidget, &QTreeWidget::itemEntered, this, &SeerVarVisualizerWidget::handleItemEntered); QObject::connect(variableTreeWidget, &QTreeWidget::itemExpanded, this, &SeerVarVisualizerWidget::handleItemExpanded); QObject::connect(variableTreeWidget, &QTreeWidget::itemCollapsed, this, &SeerVarVisualizerWidget::handleItemExpanded); + QObject::connect(editDelegate, &QAllowEditDelegate::editingFinished, this, &SeerVarVisualizerWidget::handleIndexEditingFinished); // Show/hide columns. - handleDetailedCheckBox(); + handleDebugCheckBox(); // Restore window settings. readSettings(); @@ -87,6 +104,7 @@ void SeerVarVisualizerWidget::setVariableName (const QString& name) { if (variableNameLineEdit->text() != "") { QTreeWidgetItem* item = new QTreeWidgetItem; + item->setText(0, name); item->setText(1, ""); item->setText(2, ""); @@ -119,12 +137,12 @@ void SeerVarVisualizerWidget::handleText (const QString& text) { // "4^done,name=\"seer4\",numchild=\"1\",value=\"{...}\",type=\"Person\",thread-id=\"1\",has_more=\"0\"" - // qDebug() << text; - QString id_text = text.section('^', 0,0); if (id_text.toInt() == _variableId) { + //qDebug() << text; + QString name_text = Seer::parseFirst(text, "name=", '"', '"', false); QString exp_text = Seer::parseFirst(text, "exp=", '"', '"', false); QString numchild_text = Seer::parseFirst(text, "numchild=", '"', '"', false); @@ -150,12 +168,26 @@ void SeerVarVisualizerWidget::handleText (const QString& text) { topItem->setText(0, exp_text); } + // Allow editing if the item has no children and has a value. + if (numchild_text == "0" && value_text != "") { + topItem->setFlags(topItem->flags() | Qt::ItemIsEditable); + } + // For now, always expand everything. variableTreeWidget->expandAll(); // If there are children, get them. + //if (numchild_text != "0") { + // emit varObjListChildren(_variableId, name_text); + //} + if (numchild_text != "0") { - emit varObjListChildren(_variableId, name_text); + if (type_text.endsWith('*') && Seer::filterEscapes(value_text) == "0x0") { + // If it is a pointer that is not null, get the children. + // How universal is this for other languages? + }else{ + emit varObjListChildren(_variableId, name_text); + } } // Save the VarObj name. @@ -170,12 +202,12 @@ void SeerVarVisualizerWidget::handleText (const QString& text) { // ], // has_more="0" - // qDebug() << text; - QString id_text = text.section('^', 0,0); if (id_text.toInt() == _variableId) { + //qDebug() << text; + QString children_text = Seer::parseFirst(text, "children=", '[', ']', false); QStringList child_list = Seer::parse(children_text, "child=", '{', '}', false); QString hasmore_text = Seer::parseFirst(text, "has_more=", '"', '"', false); @@ -192,7 +224,6 @@ void SeerVarVisualizerWidget::handleText (const QString& text) { // Do we have an existing item to add to? QList matches = variableTreeWidget->findItems(Seer::varObjParent(name_text), Qt::MatchExactly|Qt::MatchRecursive, 3); - // No, just add to the top level. if (matches.size() == 0) { @@ -219,14 +250,27 @@ void SeerVarVisualizerWidget::handleText (const QString& text) { item->setText(0, exp_text); } + // Allow editing if the item has no children and has a value. + if (numchild_text == "0" && value_text != "") { + item->setFlags(item->flags() | Qt::ItemIsEditable); + } + topItem->addChild(item); } // If there are children, get them. if (numchild_text != "0") { - emit varObjListChildren(_variableId, name_text); + if (type_text.endsWith('*') && Seer::filterEscapes(value_text) == "0x0") { + // If it is a pointer that is not null, get the children. + // How universal is this for other languages? + }else{ + emit varObjListChildren(_variableId, name_text); + } } } + + // For now, always expand everything. + variableTreeWidget->expandAll(); } @@ -241,12 +285,12 @@ void SeerVarVisualizerWidget::handleText (const QString& text) { // {name=\"seer4.public.location.public.zip\", value=\"77063\", in_scope=\"true\", type_changed=\"false\", has_more=\"0\"} // ]" - // qDebug() << text; - QString id_text = text.section('^', 0,0); if (id_text.toInt() == _variableId) { + //qDebug() << text; + QString changelist_text = Seer::parseFirst(text, "changelist=", '[', ']', false); QStringList child_list = Seer::parse(changelist_text, "", '{', '}', false); @@ -260,9 +304,9 @@ void SeerVarVisualizerWidget::handleText (const QString& text) { QString dynamic_text = Seer::parseFirst(child_text, "dynamic=", '"', '"', false); QString hasmore_text = Seer::parseFirst(child_text, "has_more=", '"', '"', false); - // Do we have an existing item to add to? - QList matches = variableTreeWidget->findItems(name_text, Qt::MatchExactly|Qt::MatchRecursive, 0); + // Do we have an existing item to add to? + QList matches = variableTreeWidget->findItems(name_text, Qt::MatchExactly|Qt::MatchRecursive, 3); // No, just add to the top level. if (matches.size() == 0) { @@ -276,6 +320,10 @@ void SeerVarVisualizerWidget::handleText (const QString& text) { item->setText(1, Seer::filterEscapes(value_text)); item->setText(7, hasmore_text); + + if (typechanged_text == "true") { + handleRefreshButton(); + } } } } @@ -283,7 +331,7 @@ void SeerVarVisualizerWidget::handleText (const QString& text) { }else if (text.contains(QRegExp("^([0-9]+)\\^error,msg="))) { - qDebug() << text; + //qDebug() << text; QString id_text = text.section('^', 0,0); QString msg_text = Seer::parseFirst(text, "msg=", '"', '"', false); @@ -299,8 +347,8 @@ void SeerVarVisualizerWidget::handleText (const QString& text) { foreach (auto item, topItem->takeChildren()) delete item; // Set the error text. - topItem->setText(3, ""); - topItem->setText(4, Seer::filterEscapes(msg_text)); + topItem->setText(1, ""); + topItem->setText(2, Seer::filterEscapes(msg_text)); } @@ -582,7 +630,7 @@ void SeerVarVisualizerWidget::handleResizeColumns () { variableTreeWidget->resizeColumnToContents(7); } -void SeerVarVisualizerWidget::handleHideDetailedColumns (bool flag) { +void SeerVarVisualizerWidget::handleHideDebugColumns (bool flag) { variableTreeWidget->setColumnHidden(0, false); variableTreeWidget->setColumnHidden(1, false); @@ -620,9 +668,9 @@ void SeerVarVisualizerWidget::handleRefreshButton () { } } -void SeerVarVisualizerWidget::handleDetailedCheckBox () { +void SeerVarVisualizerWidget::handleDebugCheckBox () { - handleHideDetailedColumns(!detailedCheckBox->isChecked()); + handleHideDebugColumns(!debugCheckBox->isChecked()); } void SeerVarVisualizerWidget::handleVariableNameLineEdit () { @@ -634,6 +682,21 @@ void SeerVarVisualizerWidget::handleVariableNameLineEdit () { setVariableName (variableNameLineEdit->text()); } +void SeerVarVisualizerWidget::handleIndexEditingFinished (const QModelIndex& index) { + + QTreeWidgetItem* item = variableTreeWidget->getItemFromIndex(index); + + if (item == 0) { + return; + } + + // Get the new value; + QString value = item->text(1); + + // Emit the signal to change the varobj to the new value. + emit varObjAssign(_variableId, item->text(3), value); +} + void SeerVarVisualizerWidget::writeSettings () { QSettings settings; diff --git a/src/SeerVarVisualizerWidget.h b/src/SeerVarVisualizerWidget.h index ddf2d6d..08a52e6 100644 --- a/src/SeerVarVisualizerWidget.h +++ b/src/SeerVarVisualizerWidget.h @@ -19,6 +19,7 @@ class SeerVarVisualizerWidget : public QWidget, protected Ui::SeerVarVisualizerW void varObjListChildren (int expressionid, QString objname); void varObjUpdate (int expressionid, QString objname); void varObjDelete (int expressionid, QString objname); + void varObjAssign (int expressionid, QString objname, QString value); void addMemoryVisualize (QString expression); void addArrayVisualize (QString expression); void addStructVisualize (QString expression); @@ -30,13 +31,14 @@ class SeerVarVisualizerWidget : public QWidget, protected Ui::SeerVarVisualizerW void handleExpandAllButton (); void handleCollapseAllButton (); void handleRefreshButton (); - void handleDetailedCheckBox (); + void handleDebugCheckBox (); void handleVariableNameLineEdit (); + void handleIndexEditingFinished (const QModelIndex& index); void handleContextMenu (const QPoint& pos); void handleItemEntered (QTreeWidgetItem* item, int column); void handleItemExpanded (QTreeWidgetItem* item); void handleResizeColumns (); - void handleHideDetailedColumns (bool flag); + void handleHideDebugColumns (bool flag); protected: void writeSettings (); diff --git a/src/SeerVarVisualizerWidget.ui b/src/SeerVarVisualizerWidget.ui index 393a5eb..c77bb21 100644 --- a/src/SeerVarVisualizerWidget.ui +++ b/src/SeerVarVisualizerWidget.ui @@ -38,17 +38,17 @@ - + Show more variable details. - Detailed + Debug - + Variable @@ -151,12 +151,19 @@ QLineEdit
QHistoryLineEdit.h
+ + QIndexTreeWidget + QTreeWidget +
QIndexTreeWidget.h
+
variableNameLineEdit expandAllToolButton collapseAllToolButton refreshToolButton + autoRefreshCheckBox + debugCheckBox variableTreeWidget diff --git a/tests/hellolinklist/DEBUG b/tests/hellolinklist/DEBUG new file mode 100644 index 0000000..64ee014 --- /dev/null +++ b/tests/hellolinklist/DEBUG @@ -0,0 +1,81 @@ +"4^done,name="seer4", + numchild="1", + value="{...}", + type="Node", + thread-id="1", + has_more="0"" + + +"4^done,numchild="1", + children=[ + child={name="seer4.public",exp="public",numchild="2",value="",thread-id="1"} + ], + has_more="0"" +"4^done,numchild="2", + children=[ + child={name="seer4.public.data",exp="data",numchild="0",value="1",type="int",thread-id="1"}, + child={name="seer4.public.next",exp="next",numchild="1",value="0x613c40",type="Node *",thread-id="1"} + ], + has_more="0"" +"4^done,numchild="1", + children=[ + child={name="seer4.public.next.public",exp="public",numchild="2",value="",thread-id="1"} + ], + has_more="0"" +"4^done,numchild="2", + children=[ + child={name="seer4.public.next.public.data",exp="data",numchild="0",value="2",type="int",thread-id="1"}, + child={name="seer4.public.next.public.next",exp="next",numchild="1",value="0x613c60",type="Node *",thread-id="1"} + ], + has_more="0"" +"4^done,numchild="1", + children=[ + child={name="seer4.public.next.public.next.public",exp="public",numchild="2",value="",thread-id="1"} + ], + has_more="0"" +"4^done,numchild="2", + children=[ + child={name="seer4.public.next.public.next.public.data",exp="data",numchild="0",value="3",type="int",thread-id="1"}, + child={name="seer4.public.next.public.next.public.next",exp="next",numchild="1",value="0x0",type="Node *",thread-id="1"} + ], + has_more="0"" +"4^done,numchild="1", + children=[ + child={name="seer4.public.next.public.next.public.next.public",exp="public",numchild="2",value="",thread-id="1"} + ], + has_more="0"" +"4^done,numchild="2", + children=[ + child={name="seer4.public.next.public.next.public.next.public.data",exp="data",numchild="0",value="",type="int",thread-id="1"}, + child={name="seer4.public.next.public.next.public.next.public.next",exp="next",numchild="1",value="",type="Node *",thread-id="1"} + ], + has_more="0"" +"4^done,numchild="1", + children=[ + child={name="seer4.public.next.public.next.public.next.public.next.public",exp="public",numchild="2",value="",thread-id="1"} + ], + has_more="0"" +"4^done,numchild="2", + children=[ + child={name="seer4.public.next.public.next.public.next.public.next.public.data",exp="data",numchild="0",value="",type="int",thread-id="1"}, + child={name="seer4.public.next.public.next.public.next.public.next.public.next",exp="next",numchild="1",value="",type="Node *",thread-id="1"} + ], + has_more="0"" +"4^done,numchild="1", + children=[ + child={name="seer4.public.next.public.next.public.next.public.next.public.next.public",exp="public",numchild="2",value="",thread-id="1"} + ], + has_more="0"" +"4^done,numchild="2", + children=[ + child={name="seer4.public.next.public.next.public.next.public.next.public.next.public.data",exp="data",numchild="0",value="",type="int",thread-id="1"}, + child={name="seer4.public.next.public.next.public.next.public.next.public.next.public.next",exp="next",numchild="1",value="",type="Node *",thread-id="1"} + ], + has_more="0"" +"4^done,numchild="1", + children=[ + child={name="seer4.public.next.public.next.public.next.public.next.public.next.public.next.public",exp="public",numchild="2",value="",thread-id="1"} + ], + has_more="0"" + + diff --git a/tests/hellolinklist/hellolinklist.cpp b/tests/hellolinklist/hellolinklist.cpp index 059f952..5312006 100644 --- a/tests/hellolinklist/hellolinklist.cpp +++ b/tests/hellolinklist/hellolinklist.cpp @@ -2,38 +2,105 @@ #include #include #include +#include +#include +// https://www.geeksforgeeks.org/linked-list-set-1-introduction/ +// +// C program to implement a linked list +// -struct Location { - std::string city; - std::string state; - int zip; +struct Node { + int data; + struct Node* next; }; -struct Person { - std::string name; - int age; - float salary; - struct Location* location; -}; +// Driver's code +int main() { + + struct Node* head = NULL; + struct Node* second = NULL; + struct Node* third = NULL; + + // allocate 3 nodes in the heap + head = (struct Node*)malloc(sizeof(struct Node)); + second = (struct Node*)malloc(sizeof(struct Node)); + third = (struct Node*)malloc(sizeof(struct Node)); + + /* Three blocks have been allocated dynamically. + We have pointers to these three blocks as head, + second and third + head second third + | | | + | | | + +---+-----+ +----+----+ +----+----+ + | # | # | | # | # | | # | # | + +---+-----+ +----+----+ +----+----+ + + # represents any random value. + Data is random because we haven’t assigned + anything yet + */ + + head->data = 1; // assign data in first node + head->next = second; // Link first node with + + // the second node + + /* data has been assigned to the data part of the first + block (block pointed by the head). And next + pointer of first block points to second. + So they both are linked. + + head second third + | | | + | | | + +---+---+ +----+----+ +-----+----+ + | 1 | o----->| # | # | | # | # | + +---+---+ +----+----+ +-----+----+ + */ + + // assign data to second node + second->data = 2; + + // Link second node with the third node + second->next = third; + + /* data has been assigned to the data part of the second + block (block pointed by second). And next + pointer of the second block points to the third + block. So all three blocks are linked. + + head second third + | | | + | | | + +---+---+ +---+---+ +----+----+ + | 1 | o----->| 2 | o-----> | # | # | + +---+---+ +---+---+ +----+----+ + */ + + third->data = 3; // assign data to third node + third->next = NULL; + + /* data has been assigned to data part of third + block (block pointed by third). And next pointer + of the third block is made NULL to indicate + that the linked list is terminated here. + + We have the linked list ready. + + head + | + | + +---+---+ +---+---+ +----+------+ + | 1 | o----->| 2 | o-----> | 3 | NULL | + +---+---+ +---+---+ +----+------+ -int main (int argc, char** argv) { - - Person me; - - me.name = "Pasveer, Ernie"; - me.age = 60; - me.salary = 0.25; - - //me.location = (struct Location*)malloc(sizeof(struct Location)); - me.location = new Location; - - me.location->city = "Houston"; - me.location->state = "Texas"; - me.location->zip = 77063; - - std::cout << "'" << me.name << "', from '" << me.location->city << "', is " << me.age << " years old and makes " << me.salary << " per year." << std::endl; + Note that only head is sufficient to represent + the whole list. We can traverse the complete + list by following next pointers. + */ return 0; }