From 94c613c9fe801da696df62ad3db56a08ee07003f Mon Sep 17 00:00:00 2001
From: hjk <qtc-committer@nokia.com>
Date: Wed, 10 Dec 2008 14:37:15 +0100
Subject: [PATCH] add custom dumpers for std::list

---
 bin/gdbmacros/gdbmacros.cpp             |  73 +++++++++++++++
 src/plugins/debugger/gdbengine.cpp      |   2 +
 src/plugins/debugger/watchhandler.cpp   |  22 ++++-
 tests/manual/gdbdebugger/simple/app.cpp | 119 ++++++++++++++++--------
 4 files changed, 170 insertions(+), 46 deletions(-)

diff --git a/bin/gdbmacros/gdbmacros.cpp b/bin/gdbmacros/gdbmacros.cpp
index 199b783f45d..e074ddd2a5d 100644
--- a/bin/gdbmacros/gdbmacros.cpp
+++ b/bin/gdbmacros/gdbmacros.cpp
@@ -122,6 +122,7 @@ int qtGhVersion = QT_VERSION;
 #   include <QImage>
 #endif
 
+#include <list>
 #include <string>
 #include <vector>
 
@@ -2101,6 +2102,76 @@ static void qDumpQVector(QDumper &d)
     d.disarm();
 }
 
+static void qDumpStdList(QDumper &d)
+{
+    const std::list<int> &list = *reinterpret_cast<const std::list<int> *>(d.data);
+    const void *p = d.data;
+    qCheckAccess(p);
+    p = deref(p);
+    qCheckAccess(p);
+    p = deref(p);
+    qCheckAccess(p);
+    p = deref(p);
+    qCheckAccess(p);
+    p = deref(addOffset(d.data, sizeof(void*)));
+    qCheckAccess(p);
+    p = deref(addOffset(p, sizeof(void*)));
+    qCheckAccess(p);
+    p = deref(addOffset(p, sizeof(void*)));
+    qCheckAccess(p);
+    p = deref(addOffset(p, sizeof(void*)));
+    qCheckAccess(p);
+
+    int nn = 0;
+    std::list<int>::const_iterator it = list.begin();
+    for (int i = 0; i < 101 && it != list.end(); ++i, ++it) {
+        qCheckAccess(it.operator->());
+        ++nn;
+    }
+
+    if (nn > 100)
+        P(d, "value", "<more than 100 items>");
+    else
+        P(d, "value", "<" << nn << " items>");
+    P(d, "numchild", nn);
+
+    P(d, "valuedisabled", "true");
+    if (d.dumpChildren) {
+        unsigned innersize = d.extraInt[0];
+        bool innerTypeIsPointer = isPointerType(d.innertype);
+        QByteArray strippedInnerType = stripPointerType(d.innertype);
+        d << ",children=[";
+        std::list<int>::const_iterator it = list.begin();
+        for (int i = 0; i < 1000 && it != list.end(); ++i, ++it) {
+            d.beginHash();
+            P(d, "name", "[" << i << "]");
+            P(d, "type", d.innertype);
+            const void *p = it.operator->();
+            if (innerTypeIsPointer) {
+                if (deref(p)) {
+                    qDumpInnerValue(d, strippedInnerType.data(), deref(p));
+                } else {
+                    P(d, "type", d.innertype);
+                    P(d, "value", "<null>");
+                    P(d, "numchild", "0");
+                }
+            } else {
+                qDumpInnerValue(d, d.innertype, p);
+            }
+            d.endHash();
+        }
+        if (it != list.end()) {
+            d.beginHash();
+            P(d, "name", "[...]");
+            P(d, "value", "<incomplete>");
+            P(d, "type", d.innertype);
+            d.endHash();
+        }
+        d << "]";
+    }
+    d.disarm();
+}
+
 static void qDumpStdString(QDumper &d)
 {
     const std::string &str = *reinterpret_cast<const std::string *>(d.data);
@@ -2325,6 +2396,8 @@ static void handleProtocolVersion2and3(QDumper & d)
                 qDumpStdVector(d);
             else if (isEqual(type, "std::vector::bool"))
                 qDumpStdVectorBool(d);
+            else if (isEqual(type, "std::list"))
+                qDumpStdList(d);
             else if (isEqual(type, "string"))
                 qDumpStdString(d);
             else if (isEqual(type, "std::string"))
diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp
index d7ac5b1aaa1..83473674782 100644
--- a/src/plugins/debugger/gdbengine.cpp
+++ b/src/plugins/debugger/gdbengine.cpp
@@ -2939,6 +2939,8 @@ bool GdbEngine::isCustomValueDumperAvailable(const QString &type) const
             if (tmplate == "QSet")
                 return true;
         }
+        if (tmplate == "std::list")
+            return true;
         if (tmplate == "std::vector" && inner != "bool")
             return true;
         if (tmplate == "std::basic_string") {
diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp
index 053fcadcd19..47f1593db36 100644
--- a/src/plugins/debugger/watchhandler.cpp
+++ b/src/plugins/debugger/watchhandler.cpp
@@ -402,18 +402,30 @@ bool WatchHandler::setData(const QModelIndex &idx,
 static QString niceType(QString type)
 {
     if (type.contains("std::")) {
-        static QRegExp re("std::vector<(.*)\\s*,std::allocator<(.*)>\\s*>");
-        re.setMinimal(true);
-
+        // std::string
         type.replace("std::basic_string<char, std::char_traits<char>, "
                      "std::allocator<char> >", "std::string");
+
+        // std::wstring
         type.replace("std::basic_string<wchar_t, std::char_traits<wchar_t>, "
                      "std::allocator<wchar_t> >", "std::wstring");
 
+        // std::vector
+        static QRegExp re1("std::vector<(.*)\\s*,std::allocator<(.*)>\\s*>");
+        re1.setMinimal(true);
+        for (int i = 0; i != 10; ++i) {
+            if (re1.indexIn(type) == -1 || re1.cap(1) != re1.cap(2)) 
+                break;
+            type.replace(re1.cap(0), "std::vector<" + re1.cap(1) + ">");
+        }
+
+        // std::list
+        static QRegExp re2("std::list<(.*)\\s*,std::allocator<(.*)>\\s*>");
+        re2.setMinimal(true);
         for (int i = 0; i != 10; ++i) {
-            if (re.indexIn(type) == -1 || re.cap(1) != re.cap(2)) 
+            if (re2.indexIn(type) == -1 || re2.cap(1) != re2.cap(2)) 
                 break;
-            type.replace(re.cap(0), "std::vector<" + re.cap(1) + ">");
+            type.replace(re2.cap(0), "std::list<" + re2.cap(1) + ">");
         }
 
         type.replace(" >", ">");
diff --git a/tests/manual/gdbdebugger/simple/app.cpp b/tests/manual/gdbdebugger/simple/app.cpp
index 958c8985b05..4dc01961958 100644
--- a/tests/manual/gdbdebugger/simple/app.cpp
+++ b/tests/manual/gdbdebugger/simple/app.cpp
@@ -53,6 +53,8 @@
 #include <QtNetwork/QHostAddress>
 
 #include <iostream>
+#include <list>
+#include <stack>
 #include <string>
 #include <vector>
 
@@ -373,65 +375,63 @@ void stringRefTest(const QString &refstring)
     Q_UNUSED(refstring);
 }
 
-
-int F(int a, int b)
-{
-   return a + b;
-}
-
-int add(int i) { return i + 2; }
-
-int mul(int i) { return i * 2; }
-
-
-void testStdVector()
+void testStdList()
 {
-    int x = F(add(1), mul(2));
-    Q_UNUSED(x);
-    std::vector<int *> plist1;
+    std::list<int *> plist1;
     plist1.push_back(new int(1));
     plist1.push_back(0);
     plist1.push_back(new int(2));
 
-    std::vector<int> flist2;
+    std::list<int> flist2;
     flist2.push_back(1);
     flist2.push_back(2);
     flist2.push_back(3);
     flist2.push_back(4);
 
-    int a = 1;
-    int b = 0;
-
-    while (0) {
-        a += 1;
-        if (b)
-            break;
-    }
-
     flist2.push_back(1);
     flist2.push_back(2);
     flist2.push_back(3);
     flist2.push_back(4);
 
-    std::vector<Foo *> plist;
+    std::list<Foo *> plist;
     plist.push_back(new Foo(1));
     plist.push_back(0);
     plist.push_back(new Foo(2));
 
-    std::vector<Foo> flist;
+    std::list<Foo> flist;
     flist.push_back(1);
-
     flist.push_back(2);
     flist.push_back(3);
     flist.push_back(4);
-    //flist.takeFirst();
-    //flist.takeFirst();
 
-    std::vector<bool> vec;
+    std::list<bool> vec;
     vec.push_back(true);
     vec.push_back(false);
 }
 
+void testStdStack()
+{
+    std::stack<int *> plist1;
+    plist1.push(new int(1));
+    plist1.push(0);
+    plist1.push(new int(2));
+    plist1.pop();
+    plist1.pop();
+    plist1.pop();
+
+    std::stack<int> flist2;
+    flist2.push(1);
+    flist2.push(2);
+
+    std::stack<Foo *> plist;
+    plist.push(new Foo(1));
+    plist.push(new Foo(2));
+
+    std::stack<Foo> flist;
+    flist.push(1);
+    flist.push(2);
+}
+
 void testStdString()
 {
     QString foo;
@@ -470,6 +470,42 @@ void testStdString()
     v.push_back(str);
 }
 
+void testStdVector()
+{
+    std::vector<int *> plist1;
+    plist1.push_back(new int(1));
+    plist1.push_back(0);
+    plist1.push_back(new int(2));
+
+    std::vector<int> flist2;
+    flist2.push_back(1);
+    flist2.push_back(2);
+    flist2.push_back(3);
+    flist2.push_back(4);
+
+    flist2.push_back(1);
+    flist2.push_back(2);
+    flist2.push_back(3);
+    flist2.push_back(4);
+
+    std::vector<Foo *> plist;
+    plist.push_back(new Foo(1));
+    plist.push_back(0);
+    plist.push_back(new Foo(2));
+
+    std::vector<Foo> flist;
+    flist.push_back(1);
+    flist.push_back(2);
+    flist.push_back(3);
+    flist.push_back(4);
+    //flist.takeFirst();
+    //flist.takeFirst();
+
+    std::vector<bool> vec;
+    vec.push_back(true);
+    vec.push_back(false);
+}
+
 void testString()
 {
     QString str = "Hello ";
@@ -729,16 +765,9 @@ void testNamespace()
     bar.doit(1);
 }
 
-int main(int argc, char *argv[])
-{
-    testIO();
-    //QString s;
-    //s = "hallo";
-    //QList<QVector<int> *> vi;
-    //QList<QVector<double> *> vd;
-    //int n = A::barz();
-
 
+void testHidden()
+{
     int  n = 1;
     n = 2;
     n = 3;
@@ -762,10 +791,18 @@ int main(int argc, char *argv[])
     }
     ++n;
     ++n;
+}
 
+int main(int argc, char *argv[])
+{
+    //testIO();
+    testHidden();
     testArray();
-    testStdVector();
+
+    testStdList();
+    testStdStack();
     testStdString();
+    testStdVector();
 
     testPlugin();
     testList();
-- 
GitLab