TypeSynthetic.h revision 81a96aa6242f7b559770f5dc62316253cb8cb0d4
1//===-- TypeSynthetic.h -------------------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef lldb_TypeSynthetic_h_
11#define lldb_TypeSynthetic_h_
12
13// C Includes
14#include <stdint.h>
15#include <unistd.h>
16
17// C++ Includes
18#include <string>
19#include <vector>
20
21// Other libraries and framework includes
22
23// Project includes
24#include "lldb/lldb-public.h"
25#include "lldb/lldb-enumerations.h"
26
27#include "lldb/Core/ValueObject.h"
28#include "lldb/Interpreter/ScriptInterpreterPython.h"
29#include "lldb/Symbol/Type.h"
30
31namespace lldb_private {
32    class SyntheticChildrenFrontEnd
33    {
34    protected:
35        ValueObject &m_backend;
36    public:
37
38        SyntheticChildrenFrontEnd (ValueObject &backend) :
39        m_backend(backend)
40        {}
41
42        virtual
43        ~SyntheticChildrenFrontEnd ()
44        {
45        }
46
47        virtual size_t
48        CalculateNumChildren () = 0;
49
50        virtual lldb::ValueObjectSP
51        GetChildAtIndex (size_t idx) = 0;
52
53        virtual size_t
54        GetIndexOfChildWithName (const ConstString &name) = 0;
55
56        // this function is assumed to always succeed and it if fails, the front-end should know to deal
57        // with it in the correct way (most probably, by refusing to return any children)
58        // the return value of Update() should actually be interpreted as "ValueObjectSyntheticFilter cache is good/bad"
59        // if =true, ValueObjectSyntheticFilter is allowed to use the children it fetched previously and cached
60        // if =false, ValueObjectSyntheticFilter must throw away its cache, and query again for children
61        virtual bool
62        Update () = 0;
63
64        // if this function returns false, then CalculateNumChildren() MUST return 0 since UI frontends
65        // might validly decide not to inquire for children given a false return value from this call
66        // if it returns true, then CalculateNumChildren() can return any number >= 0 (0 being valid)
67        // it should if at all possible be more efficient than CalculateNumChildren()
68        virtual bool
69        MightHaveChildren () = 0;
70
71        typedef STD_SHARED_PTR(SyntheticChildrenFrontEnd) SharedPointer;
72        typedef STD_UNIQUE_PTR(SyntheticChildrenFrontEnd) AutoPointer;
73
74    private:
75        DISALLOW_COPY_AND_ASSIGN(SyntheticChildrenFrontEnd);
76    };
77
78    class SyntheticChildren
79    {
80    public:
81
82        class Flags
83        {
84        public:
85
86            Flags () :
87            m_flags (lldb::eTypeOptionCascade)
88            {}
89
90            Flags (const Flags& other) :
91            m_flags (other.m_flags)
92            {}
93
94            Flags (uint32_t value) :
95            m_flags (value)
96            {}
97
98            Flags&
99            operator = (const Flags& rhs)
100            {
101                if (&rhs != this)
102                    m_flags = rhs.m_flags;
103
104                return *this;
105            }
106
107            Flags&
108            operator = (const uint32_t& rhs)
109            {
110                m_flags = rhs;
111                return *this;
112            }
113
114            Flags&
115            Clear()
116            {
117                m_flags = 0;
118                return *this;
119            }
120
121            bool
122            GetCascades () const
123            {
124                return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade;
125            }
126
127            Flags&
128            SetCascades (bool value = true)
129            {
130                if (value)
131                    m_flags |= lldb::eTypeOptionCascade;
132                else
133                    m_flags &= ~lldb::eTypeOptionCascade;
134                return *this;
135            }
136
137            bool
138            GetSkipPointers () const
139            {
140                return (m_flags & lldb::eTypeOptionSkipPointers) == lldb::eTypeOptionSkipPointers;
141            }
142
143            Flags&
144            SetSkipPointers (bool value = true)
145            {
146                if (value)
147                    m_flags |= lldb::eTypeOptionSkipPointers;
148                else
149                    m_flags &= ~lldb::eTypeOptionSkipPointers;
150                return *this;
151            }
152
153            bool
154            GetSkipReferences () const
155            {
156                return (m_flags & lldb::eTypeOptionSkipReferences) == lldb::eTypeOptionSkipReferences;
157            }
158
159            Flags&
160            SetSkipReferences (bool value = true)
161            {
162                if (value)
163                    m_flags |= lldb::eTypeOptionSkipReferences;
164                else
165                    m_flags &= ~lldb::eTypeOptionSkipReferences;
166                return *this;
167            }
168
169            uint32_t
170            GetValue ()
171            {
172                return m_flags;
173            }
174
175            void
176            SetValue (uint32_t value)
177            {
178                m_flags = value;
179            }
180
181        private:
182            uint32_t m_flags;
183        };
184
185        SyntheticChildren (const Flags& flags) :
186        m_flags(flags)
187        {
188        }
189
190        virtual
191        ~SyntheticChildren ()
192        {
193        }
194
195        bool
196        Cascades () const
197        {
198            return m_flags.GetCascades();
199        }
200        bool
201        SkipsPointers () const
202        {
203            return m_flags.GetSkipPointers();
204        }
205        bool
206        SkipsReferences () const
207        {
208            return m_flags.GetSkipReferences();
209        }
210
211        void
212        SetCascades (bool value)
213        {
214            m_flags.SetCascades(value);
215        }
216
217        void
218        SetSkipsPointers (bool value)
219        {
220            m_flags.SetSkipPointers(value);
221        }
222
223        void
224        SetSkipsReferences (bool value)
225        {
226            m_flags.SetSkipReferences(value);
227        }
228
229        uint32_t
230        GetOptions ()
231        {
232            return m_flags.GetValue();
233        }
234
235        void
236        SetOptions (uint32_t value)
237        {
238            m_flags.SetValue(value);
239        }
240
241        virtual bool
242        IsScripted () = 0;
243
244        virtual std::string
245        GetDescription () = 0;
246
247        virtual SyntheticChildrenFrontEnd::AutoPointer
248        GetFrontEnd (ValueObject &backend) = 0;
249
250        typedef STD_SHARED_PTR(SyntheticChildren) SharedPointer;
251        typedef bool(*SyntheticChildrenCallback)(void*, ConstString, const SyntheticChildren::SharedPointer&);
252
253        uint32_t&
254        GetRevision ()
255        {
256            return m_my_revision;
257        }
258
259    protected:
260        uint32_t m_my_revision;
261        Flags m_flags;
262
263    private:
264        DISALLOW_COPY_AND_ASSIGN(SyntheticChildren);
265    };
266
267    class TypeFilterImpl : public SyntheticChildren
268    {
269        std::vector<std::string> m_expression_paths;
270    public:
271        TypeFilterImpl(const SyntheticChildren::Flags& flags) :
272        SyntheticChildren(flags),
273        m_expression_paths()
274        {
275        }
276
277        TypeFilterImpl(const SyntheticChildren::Flags& flags,
278                       const std::initializer_list<const char*> items) :
279        SyntheticChildren(flags),
280        m_expression_paths()
281        {
282            for (auto path : items)
283                AddExpressionPath (path);
284        }
285
286        void
287        AddExpressionPath (const char* path)
288        {
289            AddExpressionPath(std::string(path));
290        }
291
292        void
293        Clear()
294        {
295            m_expression_paths.clear();
296        }
297
298        int
299        GetCount() const
300        {
301            return m_expression_paths.size();
302        }
303
304        const char*
305        GetExpressionPathAtIndex(int i) const
306        {
307            return m_expression_paths[i].c_str();
308        }
309
310        bool
311        SetExpressionPathAtIndex (int i, const char* path)
312        {
313            return SetExpressionPathAtIndex(i, std::string(path));
314        }
315
316        void
317        AddExpressionPath (const std::string& path)
318        {
319            bool need_add_dot = true;
320            if (path[0] == '.' ||
321                (path[0] == '-' && path[1] == '>') ||
322                path[0] == '[')
323                need_add_dot = false;
324            // add a '.' symbol to help forgetful users
325            if(!need_add_dot)
326                m_expression_paths.push_back(path);
327            else
328                m_expression_paths.push_back(std::string(".") + path);
329        }
330
331        bool
332        SetExpressionPathAtIndex (int i, const std::string& path)
333        {
334            if (i >= GetCount())
335                return false;
336            bool need_add_dot = true;
337            if (path[0] == '.' ||
338                (path[0] == '-' && path[1] == '>') ||
339                path[0] == '[')
340                need_add_dot = false;
341            // add a '.' symbol to help forgetful users
342            if(!need_add_dot)
343                m_expression_paths[i] = path;
344            else
345                m_expression_paths[i] = std::string(".") + path;
346            return true;
347        }
348
349        bool
350        IsScripted ()
351        {
352            return false;
353        }
354
355        std::string
356        GetDescription ();
357
358        class FrontEnd : public SyntheticChildrenFrontEnd
359        {
360        private:
361            TypeFilterImpl* filter;
362        public:
363
364            FrontEnd(TypeFilterImpl* flt,
365                     ValueObject &backend) :
366            SyntheticChildrenFrontEnd(backend),
367            filter(flt)
368            {}
369
370            virtual
371            ~FrontEnd ()
372            {
373            }
374
375            virtual size_t
376            CalculateNumChildren ()
377            {
378                return filter->GetCount();
379            }
380
381            virtual lldb::ValueObjectSP
382            GetChildAtIndex (size_t idx)
383            {
384                if (idx >= filter->GetCount())
385                    return lldb::ValueObjectSP();
386                return m_backend.GetSyntheticExpressionPathChild(filter->GetExpressionPathAtIndex(idx), true);
387            }
388
389            virtual bool
390            Update() { return false; }
391
392            virtual bool
393            MightHaveChildren ()
394            {
395                return filter->GetCount() > 0;
396            }
397
398            virtual size_t
399            GetIndexOfChildWithName (const ConstString &name)
400            {
401                const char* name_cstr = name.GetCString();
402                for (int i = 0; i < filter->GetCount(); i++)
403                {
404                    const char* expr_cstr = filter->GetExpressionPathAtIndex(i);
405                    if (expr_cstr)
406                    {
407                        if (*expr_cstr == '.')
408                            expr_cstr++;
409                        else if (*expr_cstr == '-' && *(expr_cstr+1) == '>')
410                            expr_cstr += 2;
411                    }
412                    if (!::strcmp(name_cstr, expr_cstr))
413                        return i;
414                }
415                return UINT32_MAX;
416            }
417
418            typedef STD_SHARED_PTR(SyntheticChildrenFrontEnd) SharedPointer;
419
420        private:
421            DISALLOW_COPY_AND_ASSIGN(FrontEnd);
422        };
423
424        virtual SyntheticChildrenFrontEnd::AutoPointer
425        GetFrontEnd(ValueObject &backend)
426        {
427            return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(this, backend));
428        }
429
430    private:
431        DISALLOW_COPY_AND_ASSIGN(TypeFilterImpl);
432    };
433
434    class CXXSyntheticChildren : public SyntheticChildren
435    {
436    public:
437        typedef SyntheticChildrenFrontEnd* (*CreateFrontEndCallback) (CXXSyntheticChildren*, lldb::ValueObjectSP);
438    protected:
439        CreateFrontEndCallback m_create_callback;
440        std::string m_description;
441    public:
442        CXXSyntheticChildren (const SyntheticChildren::Flags& flags,
443                              const char* description,
444                              CreateFrontEndCallback callback) :
445        SyntheticChildren(flags),
446        m_create_callback(callback),
447        m_description(description ? description : "")
448        {
449        }
450
451        bool
452        IsScripted ()
453        {
454            return false;
455        }
456
457        std::string
458        GetDescription ();
459
460        virtual SyntheticChildrenFrontEnd::AutoPointer
461        GetFrontEnd (ValueObject &backend)
462        {
463            return SyntheticChildrenFrontEnd::AutoPointer(m_create_callback(this, backend.GetSP()));
464        }
465
466    private:
467        DISALLOW_COPY_AND_ASSIGN(CXXSyntheticChildren);
468    };
469
470#ifndef LLDB_DISABLE_PYTHON
471
472    class ScriptedSyntheticChildren : public SyntheticChildren
473    {
474        std::string m_python_class;
475        std::string m_python_code;
476    public:
477
478        ScriptedSyntheticChildren (const SyntheticChildren::Flags& flags,
479                                   const char* pclass,
480                                   const char* pcode = NULL) :
481        SyntheticChildren(flags),
482        m_python_class(),
483        m_python_code()
484        {
485            if (pclass)
486                m_python_class = pclass;
487            if (pcode)
488                m_python_code = pcode;
489        }
490
491        const char*
492        GetPythonClassName ()
493        {
494            return m_python_class.c_str();
495        }
496
497        const char*
498        GetPythonCode ()
499        {
500            return m_python_code.c_str();
501        }
502
503        void
504        SetPythonClassName (const char* fname)
505        {
506            m_python_class.assign(fname);
507            m_python_code.clear();
508        }
509
510        void
511        SetPythonCode (const char* script)
512        {
513            m_python_code.assign(script);
514        }
515
516        std::string
517        GetDescription ();
518
519        bool
520        IsScripted ()
521        {
522            return true;
523        }
524
525        class FrontEnd : public SyntheticChildrenFrontEnd
526        {
527        private:
528            std::string m_python_class;
529            lldb::ScriptInterpreterObjectSP m_wrapper_sp;
530            ScriptInterpreter *m_interpreter;
531        public:
532
533            FrontEnd (std::string pclass,
534                      ValueObject &backend);
535
536            virtual
537            ~FrontEnd ();
538
539            virtual size_t
540            CalculateNumChildren ()
541            {
542                if (!m_wrapper_sp || m_interpreter == NULL)
543                    return 0;
544                return m_interpreter->CalculateNumChildren(m_wrapper_sp);
545            }
546
547            virtual lldb::ValueObjectSP
548            GetChildAtIndex (size_t idx);
549
550            virtual bool
551            Update ()
552            {
553                if (!m_wrapper_sp || m_interpreter == NULL)
554                    return false;
555
556                return m_interpreter->UpdateSynthProviderInstance(m_wrapper_sp);
557            }
558
559            virtual bool
560            MightHaveChildren ()
561            {
562                if (!m_wrapper_sp || m_interpreter == NULL)
563                    return false;
564
565                return m_interpreter->MightHaveChildrenSynthProviderInstance(m_wrapper_sp);
566            }
567
568            virtual size_t
569            GetIndexOfChildWithName (const ConstString &name)
570            {
571                if (!m_wrapper_sp || m_interpreter == NULL)
572                    return UINT32_MAX;
573                return m_interpreter->GetIndexOfChildWithName(m_wrapper_sp, name.GetCString());
574            }
575
576            typedef STD_SHARED_PTR(SyntheticChildrenFrontEnd) SharedPointer;
577
578        private:
579            DISALLOW_COPY_AND_ASSIGN(FrontEnd);
580        };
581
582        virtual SyntheticChildrenFrontEnd::AutoPointer
583        GetFrontEnd(ValueObject &backend)
584        {
585            return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(m_python_class, backend));
586        }
587
588    private:
589        DISALLOW_COPY_AND_ASSIGN(ScriptedSyntheticChildren);
590    };
591#endif
592} // namespace lldb_private
593
594#endif	// lldb_TypeSynthetic_h_
595