Home | History | Annotate | Download | only in DataFormatters
      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 
     31 namespace 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         size_t
    299         GetCount() const
    300         {
    301             return m_expression_paths.size();
    302         }
    303 
    304         const char*
    305         GetExpressionPathAtIndex(size_t i) const
    306         {
    307             return m_expression_paths[i].c_str();
    308         }
    309 
    310         bool
    311         SetExpressionPathAtIndex (size_t 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 (size_t 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 (size_t 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