OSDN Git Service

Update license.
[qt-creator-jp/qt-creator-jp.git] / src / libs / qtcreatorcdbext / symbolgroupnode.h
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
8 **
9 **
10 ** GNU Lesser General Public License Usage
11 **
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 **
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 **
23 ** Other Usage
24 **
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **************************************************************************/
32
33 #ifndef SYMBOLGROUPNODE_H
34 #define SYMBOLGROUPNODE_H
35
36 #include "common.h"
37
38 #include <vector>
39 #include <string>
40 #include <map>
41 #include <iosfwd>
42
43 enum { symbolGroupDebug = 0 };
44
45 std::ostream &operator<<(std::ostream &, const DEBUG_SYMBOL_PARAMETERS&p);
46
47 class SymbolGroupNodeVisitor;
48 class SymbolGroup;
49 struct SymbolGroupValueContext;
50 class SymbolGroupNode;
51
52 struct DumpParameters
53 {
54     typedef std::map<std::string, int> FormatMap; // type or iname to format
55     enum DumpFlags
56     {
57         DumpHumanReadable = 0x1,
58         DumpComplexDumpers = 0x2
59     };
60
61     DumpParameters();
62     bool humanReadable() const {  return dumpFlags & DumpHumanReadable; }
63     // Helper to decode format option arguments.
64     static FormatMap decodeFormatArgument(const std::string &f);
65
66     bool recode(const std::string &type, const std::string &iname,
67                 const SymbolGroupValueContext &ctx,
68                 std::wstring *value, int *encoding) const;
69     int format(const std::string &type, const std::string &iname) const;
70
71     unsigned dumpFlags;
72     FormatMap typeFormats;
73     FormatMap individualFormats;
74 };
75
76 std::ostream &operator<<(std::ostream &os, const DumpParameters &);
77
78 class AbstractSymbolGroupNode
79 {
80     AbstractSymbolGroupNode(const AbstractSymbolGroupNode&);
81     AbstractSymbolGroupNode& operator=(const AbstractSymbolGroupNode&);
82
83 public:
84     typedef std::vector<AbstractSymbolGroupNode *> AbstractSymbolGroupNodePtrVector;
85     typedef AbstractSymbolGroupNodePtrVector::iterator AbstractSymbolGroupNodePtrVectorIterator;
86     typedef AbstractSymbolGroupNodePtrVector::const_iterator AbstractSymbolGroupNodePtrVectorConstIterator;
87
88     virtual ~AbstractSymbolGroupNode();
89
90     // Name to appear in watchwindow
91     const std::string &name() const { return m_name; }
92     // 'iname' used as an internal id.
93     const std::string &iName() const { return m_iname; }
94     // Full iname 'local.x.foo': WARNING: this returns the absolute path not
95     // taking reference nodes into account by recursing up the parents.
96     std::string absoluteFullIName() const;
97
98     virtual const AbstractSymbolGroupNodePtrVector &children() const = 0;
99     AbstractSymbolGroupNode *childAt(unsigned) const;
100
101     unsigned indexByIName(const char *) const; // (unsigned(-1) on failure
102     AbstractSymbolGroupNode *childByIName(const char *) const;
103     unsigned indexOf(const AbstractSymbolGroupNode *) const;
104
105     const AbstractSymbolGroupNode *parent() const { return m_parent; }
106     AbstractSymbolGroupNode *parent() { return m_parent; }
107
108     unsigned flags() const           { return m_flags; }
109     bool testFlags(unsigned f) const { return (m_flags & f) != 0; }
110     void addFlags(unsigned f)        { m_flags |= f; }
111     void clearFlags(unsigned f)      { m_flags &= ~f; }
112
113     virtual SymbolGroupNode *asSymbolGroupNode() { return 0; }
114     virtual const SymbolGroupNode *asSymbolGroupNode() const { return 0; }
115     virtual const AbstractSymbolGroupNode *resolveReference() const { return this; }
116     virtual AbstractSymbolGroupNode *resolveReference() { return this; }
117
118     bool accept(SymbolGroupNodeVisitor &visitor,
119                 const std::string &visitingParentIname,
120                 unsigned child, unsigned depth);
121
122     // I/O: GDBMI dump for Visitors, return child count
123     virtual int dump(std::ostream &str, const std::string &visitingFullIname,
124                      const DumpParameters &p, const SymbolGroupValueContext &ctx) = 0;
125     // I/O: debug output for Visitors
126     virtual void debug(std::ostream &os, const std::string &visitingFullIname,
127                        unsigned verbosity, unsigned depth) const;
128
129     // For BaseSymbolGroupNode only.
130     void setParent(AbstractSymbolGroupNode *n);
131
132 protected:
133     explicit AbstractSymbolGroupNode(const std::string &name, const std::string &iname);
134
135     // Basic GDBMI dumping
136     static inline void dumpBasicData(std::ostream &str, const std::string &aName,
137                                   const std::string &aFullIname,
138                                   const std::string &type = std::string(),
139                                   const std::string &expression = std::string());
140
141 private:
142     const std::string m_name;
143     const std::string m_iname;
144     AbstractSymbolGroupNode *m_parent;
145     unsigned m_flags;
146 };
147
148 class BaseSymbolGroupNode : public AbstractSymbolGroupNode
149 {
150 public:
151     virtual const AbstractSymbolGroupNodePtrVector &children() const { return m_children; }
152     void addChild(AbstractSymbolGroupNode *c); // for watches
153     void removeChildAt(unsigned);
154
155 protected:
156     explicit BaseSymbolGroupNode(const std::string &name, const std::string &iname);
157     virtual ~BaseSymbolGroupNode();
158
159     void reserveChildren(AbstractSymbolGroupNodePtrVector::size_type s) { m_children.reserve(s); }
160
161 private:
162     AbstractSymbolGroupNodePtrVector m_children;
163     void removeChildren();
164 };
165
166 // Dummy fake node to satisfy the watch model for failed additions. Reports error.
167 class ErrorSymbolGroupNode : public BaseSymbolGroupNode
168 {
169 public:
170     explicit ErrorSymbolGroupNode(const std::string &name, const std::string &iname);
171
172     virtual int dump(std::ostream &str, const std::string &fullIname,
173                      const DumpParameters &p, const SymbolGroupValueContext &ctx);
174     virtual void debug(std::ostream &os, const std::string &visitingFullIname,
175                        unsigned verbosity, unsigned depth) const;
176 };
177
178 class SymbolGroupNode : public BaseSymbolGroupNode
179 {
180     explicit SymbolGroupNode(SymbolGroup *symbolGroup,
181                              ULONG index,
182                              const std::string &module,
183                              const std::string &name,
184                              const std::string &iname);
185
186 public:
187     enum Flags
188     {
189         Uninitialized = 0x1,
190         SimpleDumperNotApplicable = 0x2, // No dumper available for type
191         SimpleDumperOk = 0x4,     // Internal dumper ran, value set
192         SimpleDumperFailed = 0x8, // Internal dumper failed
193         SimpleDumperMask = SimpleDumperNotApplicable|SimpleDumperOk|SimpleDumperFailed,
194         ExpandedByDumper = 0x10,
195         AdditionalSymbol = 0x20, // Introduced by addSymbol, should not be visible
196         Obscured = 0x40,    // Symbol is obscured by (for example) fake container children
197         ComplexDumperOk = 0x80,
198         WatchNode = 0x100
199     };
200
201     typedef std::vector<DEBUG_SYMBOL_PARAMETERS> SymbolParameterVector;
202
203     void parseParameters(SymbolParameterVector::size_type index,
204                          SymbolParameterVector::size_type parameterOffset,
205                          const SymbolParameterVector &vec);
206
207     static SymbolGroupNode *create(SymbolGroup *sg, const std::string &module, const std::string &name, const SymbolParameterVector &vec);
208     // For root nodes, only: Add a new symbol by name
209     SymbolGroupNode *addSymbolByName(const std::string &module,
210                                      const std::string &name,  // Expression like 'myarray[1]'
211                                      const std::string &displayName,  // Name to be displayed, defaults to name
212                                      const std::string &iname, // Desired iname, defaults to name
213                                      std::string *errorMessage);
214
215     SymbolGroup *symbolGroup() const { return m_symbolGroup; }
216
217     // I/O: Gdbmi dump for Visitors
218     virtual int dump(std::ostream &str, const std::string &fullIname,
219                       const DumpParameters &p, const SymbolGroupValueContext &ctx);
220     // Dumper functionality for reference nodes, returns child count guess
221     int dumpNode(std::ostream &str, const std::string &aName, const std::string &aFullIName,
222                   const DumpParameters &p, const SymbolGroupValueContext &ctx);
223
224     // I/O: debug for Visitors
225     virtual void debug(std::ostream &os, const std::string &visitingFullIname,
226                        unsigned verbosity, unsigned depth) const;
227
228     std::wstring symbolGroupRawValue() const;
229     std::wstring symbolGroupFixedValue() const;
230     // A quick check if symbol is valid by checking for inaccessible value
231     bool isMemoryAccessible() const;
232
233     std::string type() const;
234     int dumperType() const { return m_dumperType; } // Valid after dumper run
235     int dumperContainerSize() { return m_dumperContainerSize; } // Valid after dumper run
236     unsigned size() const; // Size of value
237     ULONG64 address() const;
238     std::string module() const { return m_module; }
239
240     bool expand(std::string *errorMessage);
241     bool expandRunComplexDumpers(const SymbolGroupValueContext &ctx, std::string *errorMessage);
242     bool isExpanded() const { return !children().empty(); }
243     bool canExpand() const { return m_parameters.SubElements > 0; }
244     void runComplexDumpers(const SymbolGroupValueContext &ctx);
245     // Cast to a different type. Works only on unexpanded nodes
246     bool typeCast(const std::string &desiredType, std::string *errorMessage);
247
248     ULONG subElements() const { return m_parameters.SubElements; }
249     ULONG index() const { return m_index; }
250
251     virtual SymbolGroupNode *asSymbolGroupNode() { return this; }
252     virtual const SymbolGroupNode *asSymbolGroupNode() const { return this; }
253
254     // Remove self off parent and return the indexes to be shifted or unsigned(-1).
255     bool removeSelf(SymbolGroupNode *root, std::string *errorMessage);
256
257 private:
258     const SymbolGroupNode *symbolGroupNodeParent() const;
259     SymbolGroupNode *symbolGroupNodeParent();
260     bool isArrayElement() const;
261     // Notify about expansion/collapsing of a node, shift indexes
262     bool notifyIndexesMoved(ULONG index, bool inserted, ULONG offset);
263     bool runSimpleDumpers(const SymbolGroupValueContext &ctx);
264     std::wstring simpleDumpValue(const SymbolGroupValueContext &ctx);
265     ULONG nextSymbolIndex() const;
266
267     SymbolGroup *const m_symbolGroup;
268     const std::string m_module;
269     ULONG m_index;
270     DEBUG_SYMBOL_PARAMETERS m_parameters; // Careful when using ParentSymbol. It might not be correct.
271     std::wstring m_dumperValue;
272     int m_dumperType;
273     int m_dumperContainerSize;
274     void *m_dumperSpecialInfo; // Opaque information passed from simple to complex dumpers
275 };
276
277 class ReferenceSymbolGroupNode : public AbstractSymbolGroupNode
278 {
279 public:
280     explicit ReferenceSymbolGroupNode(const std::string &name,
281                                       const std::string &iname,
282                                       SymbolGroupNode *referencedNode);
283     // Convenience to create a node name name='[1]', iname='1' for arrays
284     static ReferenceSymbolGroupNode *createArrayNode(int index,
285                                                      SymbolGroupNode *referencedNode);
286
287     virtual int dump(std::ostream &str, const std::string &visitingFullIname,
288                       const DumpParameters &p, const SymbolGroupValueContext &ctx);
289     virtual void debug(std::ostream &os, const std::string &visitingFullIname,
290                        unsigned verbosity, unsigned depth) const;
291
292     virtual const AbstractSymbolGroupNodePtrVector &children() const { return m_referencedNode->children(); }
293
294     virtual const AbstractSymbolGroupNode *resolveReference() const { return m_referencedNode; }
295     virtual AbstractSymbolGroupNode *resolveReference() { return m_referencedNode; }
296
297 private:
298     SymbolGroupNode * const m_referencedNode;
299 };
300
301 class MapNodeSymbolGroupNode : public BaseSymbolGroupNode
302 {
303 private:
304     explicit MapNodeSymbolGroupNode(const std::string &name,
305                                     const std::string &iname,
306                                     ULONG64 address /* = 0 */,
307                                     const std::string &type,
308                                     AbstractSymbolGroupNode *key,
309                                     AbstractSymbolGroupNode *value);
310
311 public:
312     static MapNodeSymbolGroupNode *
313         create(int i, ULONG64 address /* = 0 */, const std::string &type,
314                SymbolGroupNode *key, SymbolGroupNode *value);
315
316     virtual int dump(std::ostream &str, const std::string &visitingFullIname,
317                       const DumpParameters &p, const SymbolGroupValueContext &ctx);
318     virtual void debug(std::ostream &os, const std::string &visitingFullIname,
319                        unsigned verbosity, unsigned depth) const;
320
321 private:
322     const ULONG64 m_address;
323     const std::string m_type;
324 };
325
326 class SymbolGroupNodeVisitor {
327     SymbolGroupNodeVisitor(const SymbolGroupNodeVisitor&);
328     SymbolGroupNodeVisitor& operator=(const SymbolGroupNodeVisitor&);
329
330     friend class AbstractSymbolGroupNode;
331 protected:
332     SymbolGroupNodeVisitor() {}
333 public:
334     virtual ~SymbolGroupNodeVisitor() {}
335
336     // "local.vi" -> "local"
337     static std::string parentIname(const std::string &iname);
338     static const char iNamePathSeparator = '.';
339
340 protected:
341     enum VisitResult
342     {
343         VisitContinue,
344         VisitSkipChildren,
345         VisitStop
346     };
347
348 protected:
349     virtual VisitResult visit(AbstractSymbolGroupNode *node,
350                               const std::string &fullIname,
351                               unsigned child, unsigned depth) = 0;
352     // Helper for formatting output.
353     virtual void childrenVisited(const AbstractSymbolGroupNode * /* node */, unsigned /* depth */) {}
354 };
355
356 class DebugSymbolGroupNodeVisitor : public SymbolGroupNodeVisitor {
357 public:
358     explicit DebugSymbolGroupNodeVisitor(std::ostream &os, unsigned verbosity = 0);
359
360 protected:
361     virtual VisitResult visit(AbstractSymbolGroupNode *node,
362                               const std::string &fullIname,
363                               unsigned child, unsigned depth);
364
365 private:
366     std::ostream &m_os;
367     const unsigned m_verbosity;
368 };
369
370 class DebugFilterSymbolGroupNodeVisitor : public DebugSymbolGroupNodeVisitor {
371 public:
372     explicit DebugFilterSymbolGroupNodeVisitor(std::ostream &os,
373                                                const std::string &filter,
374                                                const unsigned verbosity = 0);
375
376 protected:
377     virtual VisitResult visit(AbstractSymbolGroupNode *node,
378                               const std::string &fullIname,
379                               unsigned child, unsigned depth);
380
381 private:
382     const std::string m_filter;
383 };
384
385 class DumpSymbolGroupNodeVisitor : public SymbolGroupNodeVisitor {
386 public:
387     explicit DumpSymbolGroupNodeVisitor(std::ostream &os,
388                                         const SymbolGroupValueContext &context,
389                                         const DumpParameters &parameters = DumpParameters());
390
391 protected:
392     virtual VisitResult visit(AbstractSymbolGroupNode *node,
393                               const std::string &fullIname,
394                               unsigned child, unsigned depth);
395     virtual void childrenVisited(const AbstractSymbolGroupNode *  node, unsigned depth);
396
397 private:
398     std::ostream &m_os;
399     const SymbolGroupValueContext &m_context;
400     const DumpParameters &m_parameters;
401     unsigned m_lastDepth;
402 };
403
404 #endif // SYMBOLGROUPNODE_H