File: | tools/lldb/include/lldb/Utility/StructuredData.h |
Warning: | line 469, column 42 Potential memory leak |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- BreakpointResolverScripted.cpp ---------------------------*- 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 | #include "lldb/Breakpoint/BreakpointResolverScripted.h" | |||
11 | ||||
12 | // C Includes | |||
13 | // C++ Includes | |||
14 | // Other libraries and framework includes | |||
15 | // Project includes | |||
16 | ||||
17 | #include "lldb/Breakpoint/BreakpointLocation.h" | |||
18 | #include "lldb/Core/Debugger.h" | |||
19 | #include "lldb/Core/Module.h" | |||
20 | #include "lldb/Core/Section.h" | |||
21 | #include "lldb/Core/StructuredDataImpl.h" | |||
22 | #include "lldb/Interpreter/CommandInterpreter.h" | |||
23 | #include "lldb/Interpreter/ScriptInterpreter.h" | |||
24 | #include "lldb/Target/Process.h" | |||
25 | #include "lldb/Target/Target.h" | |||
26 | #include "lldb/Utility/Log.h" | |||
27 | #include "lldb/Utility/StreamString.h" | |||
28 | ||||
29 | using namespace lldb; | |||
30 | using namespace lldb_private; | |||
31 | ||||
32 | //---------------------------------------------------------------------- | |||
33 | // BreakpointResolverScripted: | |||
34 | //---------------------------------------------------------------------- | |||
35 | BreakpointResolverScripted::BreakpointResolverScripted( | |||
36 | Breakpoint *bkpt, | |||
37 | const llvm::StringRef class_name, | |||
38 | lldb::SearchDepth depth, | |||
39 | StructuredDataImpl *args_data, | |||
40 | ScriptInterpreter &script_interp) | |||
41 | : BreakpointResolver(bkpt, BreakpointResolver::PythonResolver), | |||
42 | m_class_name(class_name), m_depth(depth), m_args_ptr(args_data) { | |||
43 | CreateImplementationIfNeeded(); | |||
44 | } | |||
45 | ||||
46 | void BreakpointResolverScripted::CreateImplementationIfNeeded() { | |||
47 | if (m_implementation_sp) | |||
48 | return; | |||
49 | ||||
50 | if (m_class_name.empty()) | |||
51 | return; | |||
52 | ||||
53 | if (m_breakpoint) { | |||
54 | TargetSP target_sp = m_breakpoint->GetTargetSP(); | |||
55 | ScriptInterpreter *script_interp = target_sp->GetDebugger() | |||
56 | .GetCommandInterpreter() | |||
57 | .GetScriptInterpreter(); | |||
58 | if (!script_interp) | |||
59 | return; | |||
60 | lldb::BreakpointSP bkpt_sp(m_breakpoint->shared_from_this()); | |||
61 | m_implementation_sp = script_interp->CreateScriptedBreakpointResolver( | |||
62 | m_class_name.c_str(), m_args_ptr, bkpt_sp); | |||
63 | } | |||
64 | } | |||
65 | ||||
66 | void BreakpointResolverScripted::NotifyBreakpointSet() { | |||
67 | CreateImplementationIfNeeded(); | |||
68 | } | |||
69 | ||||
70 | BreakpointResolverScripted::~BreakpointResolverScripted() {} | |||
71 | ||||
72 | BreakpointResolver * | |||
73 | BreakpointResolverScripted::CreateFromStructuredData( | |||
74 | Breakpoint *bkpt, const StructuredData::Dictionary &options_dict, | |||
75 | Status &error) { | |||
76 | llvm::StringRef class_name; | |||
77 | bool success; | |||
78 | ||||
79 | if (!bkpt) | |||
| ||||
80 | return nullptr; | |||
81 | ||||
82 | success = options_dict.GetValueForKeyAsString( | |||
83 | GetKey(OptionNames::PythonClassName), class_name); | |||
84 | if (!success) { | |||
85 | error.SetErrorString("BRFL::CFSD: Couldn't find class name entry."); | |||
86 | return nullptr; | |||
87 | } | |||
88 | lldb::SearchDepth depth; | |||
89 | int depth_as_int; | |||
90 | success = options_dict.GetValueForKeyAsInteger( | |||
91 | GetKey(OptionNames::SearchDepth), depth_as_int); | |||
92 | if (!success) { | |||
93 | error.SetErrorString("BRFL::CFSD: Couldn't find class name entry."); | |||
94 | return nullptr; | |||
95 | } | |||
96 | if (depth_as_int >= (int) OptionNames::LastOptionName) { | |||
97 | error.SetErrorString("BRFL::CFSD: Invalid value for search depth."); | |||
98 | return nullptr; | |||
99 | } | |||
100 | depth = (lldb::SearchDepth) depth_as_int; | |||
101 | ||||
102 | StructuredDataImpl *args_data_impl = new StructuredDataImpl(); | |||
103 | StructuredData::Dictionary *args_dict = new StructuredData::Dictionary(); | |||
104 | success = options_dict.GetValueForKeyAsDictionary( | |||
105 | GetKey(OptionNames::ScriptArgs), args_dict); | |||
106 | if (success) { | |||
107 | // FIXME: The resolver needs a copy of the ARGS dict that it can own, | |||
108 | // so I need to make a copy constructor for the Dictionary so I can pass | |||
109 | // that to it here. For now the args are empty. | |||
110 | //StructuredData::Dictionary *dict_copy = new StructuredData::Dictionary(args_dict); | |||
111 | ||||
112 | } | |||
113 | ScriptInterpreter *script_interp = bkpt->GetTarget() | |||
114 | .GetDebugger() | |||
115 | .GetCommandInterpreter() | |||
116 | .GetScriptInterpreter(); | |||
117 | return new BreakpointResolverScripted(bkpt, class_name, depth, args_data_impl, | |||
118 | *script_interp); | |||
119 | } | |||
120 | ||||
121 | StructuredData::ObjectSP | |||
122 | BreakpointResolverScripted::SerializeToStructuredData() { | |||
123 | StructuredData::DictionarySP options_dict_sp( | |||
124 | new StructuredData::Dictionary()); | |||
125 | ||||
126 | options_dict_sp->AddStringItem(GetKey(OptionNames::PythonClassName), | |||
127 | m_class_name); | |||
128 | return WrapOptionsDict(options_dict_sp); | |||
129 | } | |||
130 | ||||
131 | ScriptInterpreter *BreakpointResolverScripted::GetScriptInterpreter() { | |||
132 | return m_breakpoint->GetTarget().GetDebugger().GetCommandInterpreter() | |||
133 | .GetScriptInterpreter(); | |||
134 | } | |||
135 | ||||
136 | Searcher::CallbackReturn | |||
137 | BreakpointResolverScripted::SearchCallback(SearchFilter &filter, | |||
138 | SymbolContext &context, Address *addr, | |||
139 | bool containing) { | |||
140 | assert(m_breakpoint != NULL)((m_breakpoint != __null) ? static_cast<void> (0) : __assert_fail ("m_breakpoint != NULL", "/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Breakpoint/BreakpointResolverScripted.cpp" , 140, __PRETTY_FUNCTION__)); | |||
141 | bool should_continue = true; | |||
142 | if (!m_implementation_sp) | |||
143 | return Searcher::eCallbackReturnStop; | |||
144 | ||||
145 | ScriptInterpreter *interp = GetScriptInterpreter(); | |||
146 | should_continue = interp->ScriptedBreakpointResolverSearchCallback( | |||
147 | m_implementation_sp, | |||
148 | &context); | |||
149 | if (should_continue) | |||
150 | return Searcher::eCallbackReturnContinue; | |||
151 | else | |||
152 | return Searcher::eCallbackReturnStop; | |||
153 | } | |||
154 | ||||
155 | lldb::SearchDepth | |||
156 | BreakpointResolverScripted::GetDepth() { | |||
157 | assert(m_breakpoint != NULL)((m_breakpoint != __null) ? static_cast<void> (0) : __assert_fail ("m_breakpoint != NULL", "/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Breakpoint/BreakpointResolverScripted.cpp" , 157, __PRETTY_FUNCTION__)); | |||
158 | lldb::SearchDepth depth = lldb::eSearchDepthModule; | |||
159 | if (m_implementation_sp) { | |||
160 | ScriptInterpreter *interp = GetScriptInterpreter(); | |||
161 | depth = interp->ScriptedBreakpointResolverSearchDepth( | |||
162 | m_implementation_sp); | |||
163 | } | |||
164 | return depth; | |||
165 | } | |||
166 | ||||
167 | void BreakpointResolverScripted::GetDescription(Stream *s) { | |||
168 | StructuredData::GenericSP generic_sp; | |||
169 | std::string short_help; | |||
170 | ||||
171 | if (m_implementation_sp) { | |||
172 | ScriptInterpreter *interp = GetScriptInterpreter(); | |||
173 | interp->GetShortHelpForCommandObject(m_implementation_sp, | |||
174 | short_help); | |||
175 | } | |||
176 | if (!short_help.empty()) | |||
177 | s->PutCString(short_help.c_str()); | |||
178 | else | |||
179 | s->Printf("python class = %s", m_class_name.c_str()); | |||
180 | } | |||
181 | ||||
182 | void BreakpointResolverScripted::Dump(Stream *s) const {} | |||
183 | ||||
184 | lldb::BreakpointResolverSP | |||
185 | BreakpointResolverScripted::CopyForBreakpoint(Breakpoint &breakpoint) { | |||
186 | ScriptInterpreter *script_interp = GetScriptInterpreter(); | |||
187 | // FIXME: Have to make a copy of the arguments from the m_args_ptr and then | |||
188 | // pass that to the new resolver. | |||
189 | lldb::BreakpointResolverSP ret_sp( | |||
190 | new BreakpointResolverScripted(&breakpoint, m_class_name, | |||
191 | m_depth, nullptr, *script_interp)); | |||
192 | return ret_sp; | |||
193 | } |
1 | //===-- StructuredData.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 liblldb_StructuredData_h_ | |||
11 | #define liblldb_StructuredData_h_ | |||
12 | ||||
13 | #include "llvm/ADT/StringRef.h" | |||
14 | ||||
15 | #include "lldb/Utility/ConstString.h" | |||
16 | #include "lldb/Utility/FileSpec.h" // for FileSpec | |||
17 | #include "lldb/lldb-enumerations.h" // for StructuredDataType | |||
18 | ||||
19 | #include <cassert> // for assert | |||
20 | #include <cstddef> // for size_t | |||
21 | #include <cstdint> // for uint64_t | |||
22 | #include <functional> | |||
23 | #include <map> | |||
24 | #include <memory> | |||
25 | #include <string> | |||
26 | #include <type_traits> // for move | |||
27 | #include <utility> | |||
28 | #include <vector> | |||
29 | ||||
30 | namespace lldb_private { | |||
31 | class Status; | |||
32 | } | |||
33 | namespace lldb_private { | |||
34 | class Stream; | |||
35 | } | |||
36 | ||||
37 | namespace lldb_private { | |||
38 | ||||
39 | //---------------------------------------------------------------------- | |||
40 | /// @class StructuredData StructuredData.h "lldb/Utility/StructuredData.h" | |||
41 | /// A class which can hold structured data | |||
42 | /// | |||
43 | /// The StructuredData class is designed to hold the data from a JSON or plist | |||
44 | /// style file -- a serialized data structure with dictionaries (maps, | |||
45 | /// hashes), arrays, and concrete values like integers, floating point | |||
46 | /// numbers, strings, booleans. | |||
47 | /// | |||
48 | /// StructuredData does not presuppose any knowledge of the schema for the | |||
49 | /// data it is holding; it can parse JSON data, for instance, and other parts | |||
50 | /// of lldb can iterate through the parsed data set to find keys and values | |||
51 | /// that may be present. | |||
52 | //---------------------------------------------------------------------- | |||
53 | ||||
54 | class StructuredData { | |||
55 | public: | |||
56 | class Object; | |||
57 | class Array; | |||
58 | class Integer; | |||
59 | class Float; | |||
60 | class Boolean; | |||
61 | class String; | |||
62 | class Dictionary; | |||
63 | class Generic; | |||
64 | ||||
65 | typedef std::shared_ptr<Object> ObjectSP; | |||
66 | typedef std::shared_ptr<Array> ArraySP; | |||
67 | typedef std::shared_ptr<Integer> IntegerSP; | |||
68 | typedef std::shared_ptr<Float> FloatSP; | |||
69 | typedef std::shared_ptr<Boolean> BooleanSP; | |||
70 | typedef std::shared_ptr<String> StringSP; | |||
71 | typedef std::shared_ptr<Dictionary> DictionarySP; | |||
72 | typedef std::shared_ptr<Generic> GenericSP; | |||
73 | ||||
74 | class Object : public std::enable_shared_from_this<Object> { | |||
75 | public: | |||
76 | Object(lldb::StructuredDataType t = lldb::eStructuredDataTypeInvalid) | |||
77 | : m_type(t) {} | |||
78 | ||||
79 | virtual ~Object() = default; | |||
80 | ||||
81 | virtual bool IsValid() const { return true; } | |||
82 | ||||
83 | virtual void Clear() { m_type = lldb::eStructuredDataTypeInvalid; } | |||
84 | ||||
85 | lldb::StructuredDataType GetType() const { return m_type; } | |||
86 | ||||
87 | void SetType(lldb::StructuredDataType t) { m_type = t; } | |||
88 | ||||
89 | Array *GetAsArray() { | |||
90 | return ((m_type == lldb::eStructuredDataTypeArray) | |||
91 | ? static_cast<Array *>(this) | |||
92 | : nullptr); | |||
93 | } | |||
94 | ||||
95 | Dictionary *GetAsDictionary() { | |||
96 | return ((m_type == lldb::eStructuredDataTypeDictionary) | |||
97 | ? static_cast<Dictionary *>(this) | |||
98 | : nullptr); | |||
99 | } | |||
100 | ||||
101 | Integer *GetAsInteger() { | |||
102 | return ((m_type == lldb::eStructuredDataTypeInteger) | |||
103 | ? static_cast<Integer *>(this) | |||
104 | : nullptr); | |||
105 | } | |||
106 | ||||
107 | uint64_t GetIntegerValue(uint64_t fail_value = 0) { | |||
108 | Integer *integer = GetAsInteger(); | |||
109 | return ((integer != nullptr) ? integer->GetValue() : fail_value); | |||
110 | } | |||
111 | ||||
112 | Float *GetAsFloat() { | |||
113 | return ((m_type == lldb::eStructuredDataTypeFloat) | |||
114 | ? static_cast<Float *>(this) | |||
115 | : nullptr); | |||
116 | } | |||
117 | ||||
118 | double GetFloatValue(double fail_value = 0.0) { | |||
119 | Float *f = GetAsFloat(); | |||
120 | return ((f != nullptr) ? f->GetValue() : fail_value); | |||
121 | } | |||
122 | ||||
123 | Boolean *GetAsBoolean() { | |||
124 | return ((m_type == lldb::eStructuredDataTypeBoolean) | |||
125 | ? static_cast<Boolean *>(this) | |||
126 | : nullptr); | |||
127 | } | |||
128 | ||||
129 | bool GetBooleanValue(bool fail_value = false) { | |||
130 | Boolean *b = GetAsBoolean(); | |||
131 | return ((b != nullptr) ? b->GetValue() : fail_value); | |||
132 | } | |||
133 | ||||
134 | String *GetAsString() { | |||
135 | return ((m_type == lldb::eStructuredDataTypeString) | |||
136 | ? static_cast<String *>(this) | |||
137 | : nullptr); | |||
138 | } | |||
139 | ||||
140 | llvm::StringRef GetStringValue(const char *fail_value = nullptr) { | |||
141 | String *s = GetAsString(); | |||
142 | if (s) | |||
143 | return s->GetValue(); | |||
144 | ||||
145 | return fail_value; | |||
146 | } | |||
147 | ||||
148 | Generic *GetAsGeneric() { | |||
149 | return ((m_type == lldb::eStructuredDataTypeGeneric) | |||
150 | ? static_cast<Generic *>(this) | |||
151 | : nullptr); | |||
152 | } | |||
153 | ||||
154 | ObjectSP GetObjectForDotSeparatedPath(llvm::StringRef path); | |||
155 | ||||
156 | void DumpToStdout(bool pretty_print = true) const; | |||
157 | ||||
158 | virtual void Dump(Stream &s, bool pretty_print = true) const = 0; | |||
159 | ||||
160 | private: | |||
161 | lldb::StructuredDataType m_type; | |||
162 | }; | |||
163 | ||||
164 | class Array : public Object { | |||
165 | public: | |||
166 | Array() : Object(lldb::eStructuredDataTypeArray) {} | |||
167 | ||||
168 | ~Array() override = default; | |||
169 | ||||
170 | bool | |||
171 | ForEach(std::function<bool(Object *object)> const &foreach_callback) const { | |||
172 | for (const auto &object_sp : m_items) { | |||
173 | if (foreach_callback(object_sp.get()) == false) | |||
174 | return false; | |||
175 | } | |||
176 | return true; | |||
177 | } | |||
178 | ||||
179 | size_t GetSize() const { return m_items.size(); } | |||
180 | ||||
181 | ObjectSP operator[](size_t idx) { | |||
182 | if (idx < m_items.size()) | |||
183 | return m_items[idx]; | |||
184 | return ObjectSP(); | |||
185 | } | |||
186 | ||||
187 | ObjectSP GetItemAtIndex(size_t idx) const { | |||
188 | assert(idx < GetSize())((idx < GetSize()) ? static_cast<void> (0) : __assert_fail ("idx < GetSize()", "/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/include/lldb/Utility/StructuredData.h" , 188, __PRETTY_FUNCTION__)); | |||
189 | if (idx < m_items.size()) | |||
190 | return m_items[idx]; | |||
191 | return ObjectSP(); | |||
192 | } | |||
193 | ||||
194 | template <class IntType> | |||
195 | bool GetItemAtIndexAsInteger(size_t idx, IntType &result) const { | |||
196 | ObjectSP value_sp = GetItemAtIndex(idx); | |||
197 | if (value_sp.get()) { | |||
198 | if (auto int_value = value_sp->GetAsInteger()) { | |||
199 | result = static_cast<IntType>(int_value->GetValue()); | |||
200 | return true; | |||
201 | } | |||
202 | } | |||
203 | return false; | |||
204 | } | |||
205 | ||||
206 | template <class IntType> | |||
207 | bool GetItemAtIndexAsInteger(size_t idx, IntType &result, | |||
208 | IntType default_val) const { | |||
209 | bool success = GetItemAtIndexAsInteger(idx, result); | |||
210 | if (!success) | |||
211 | result = default_val; | |||
212 | return success; | |||
213 | } | |||
214 | ||||
215 | bool GetItemAtIndexAsString(size_t idx, llvm::StringRef &result) const { | |||
216 | ObjectSP value_sp = GetItemAtIndex(idx); | |||
217 | if (value_sp.get()) { | |||
218 | if (auto string_value = value_sp->GetAsString()) { | |||
219 | result = string_value->GetValue(); | |||
220 | return true; | |||
221 | } | |||
222 | } | |||
223 | return false; | |||
224 | } | |||
225 | ||||
226 | bool GetItemAtIndexAsString(size_t idx, llvm::StringRef &result, | |||
227 | llvm::StringRef default_val) const { | |||
228 | bool success = GetItemAtIndexAsString(idx, result); | |||
229 | if (!success) | |||
230 | result = default_val; | |||
231 | return success; | |||
232 | } | |||
233 | ||||
234 | bool GetItemAtIndexAsString(size_t idx, ConstString &result) const { | |||
235 | ObjectSP value_sp = GetItemAtIndex(idx); | |||
236 | if (value_sp.get()) { | |||
237 | if (auto string_value = value_sp->GetAsString()) { | |||
238 | result = ConstString(string_value->GetValue()); | |||
239 | return true; | |||
240 | } | |||
241 | } | |||
242 | return false; | |||
243 | } | |||
244 | ||||
245 | bool GetItemAtIndexAsString(size_t idx, ConstString &result, | |||
246 | const char *default_val) const { | |||
247 | bool success = GetItemAtIndexAsString(idx, result); | |||
248 | if (!success) | |||
249 | result.SetCString(default_val); | |||
250 | return success; | |||
251 | } | |||
252 | ||||
253 | bool GetItemAtIndexAsDictionary(size_t idx, Dictionary *&result) const { | |||
254 | result = nullptr; | |||
255 | ObjectSP value_sp = GetItemAtIndex(idx); | |||
256 | if (value_sp.get()) { | |||
257 | result = value_sp->GetAsDictionary(); | |||
258 | return (result != nullptr); | |||
259 | } | |||
260 | return false; | |||
261 | } | |||
262 | ||||
263 | bool GetItemAtIndexAsArray(size_t idx, Array *&result) const { | |||
264 | result = nullptr; | |||
265 | ObjectSP value_sp = GetItemAtIndex(idx); | |||
266 | if (value_sp.get()) { | |||
267 | result = value_sp->GetAsArray(); | |||
268 | return (result != nullptr); | |||
269 | } | |||
270 | return false; | |||
271 | } | |||
272 | ||||
273 | void Push(ObjectSP item) { m_items.push_back(item); } | |||
274 | ||||
275 | void AddItem(ObjectSP item) { m_items.push_back(item); } | |||
276 | ||||
277 | void Dump(Stream &s, bool pretty_print = true) const override; | |||
278 | ||||
279 | protected: | |||
280 | typedef std::vector<ObjectSP> collection; | |||
281 | collection m_items; | |||
282 | }; | |||
283 | ||||
284 | class Integer : public Object { | |||
285 | public: | |||
286 | Integer(uint64_t i = 0) | |||
287 | : Object(lldb::eStructuredDataTypeInteger), m_value(i) {} | |||
288 | ||||
289 | ~Integer() override = default; | |||
290 | ||||
291 | void SetValue(uint64_t value) { m_value = value; } | |||
292 | ||||
293 | uint64_t GetValue() { return m_value; } | |||
294 | ||||
295 | void Dump(Stream &s, bool pretty_print = true) const override; | |||
296 | ||||
297 | protected: | |||
298 | uint64_t m_value; | |||
299 | }; | |||
300 | ||||
301 | class Float : public Object { | |||
302 | public: | |||
303 | Float(double d = 0.0) | |||
304 | : Object(lldb::eStructuredDataTypeFloat), m_value(d) {} | |||
305 | ||||
306 | ~Float() override = default; | |||
307 | ||||
308 | void SetValue(double value) { m_value = value; } | |||
309 | ||||
310 | double GetValue() { return m_value; } | |||
311 | ||||
312 | void Dump(Stream &s, bool pretty_print = true) const override; | |||
313 | ||||
314 | protected: | |||
315 | double m_value; | |||
316 | }; | |||
317 | ||||
318 | class Boolean : public Object { | |||
319 | public: | |||
320 | Boolean(bool b = false) | |||
321 | : Object(lldb::eStructuredDataTypeBoolean), m_value(b) {} | |||
322 | ||||
323 | ~Boolean() override = default; | |||
324 | ||||
325 | void SetValue(bool value) { m_value = value; } | |||
326 | ||||
327 | bool GetValue() { return m_value; } | |||
328 | ||||
329 | void Dump(Stream &s, bool pretty_print = true) const override; | |||
330 | ||||
331 | protected: | |||
332 | bool m_value; | |||
333 | }; | |||
334 | ||||
335 | class String : public Object { | |||
336 | public: | |||
337 | String() : Object(lldb::eStructuredDataTypeString) {} | |||
338 | explicit String(llvm::StringRef S) | |||
339 | : Object(lldb::eStructuredDataTypeString), m_value(S) {} | |||
340 | ||||
341 | void SetValue(llvm::StringRef S) { m_value = S; } | |||
342 | ||||
343 | llvm::StringRef GetValue() { return m_value; } | |||
344 | ||||
345 | void Dump(Stream &s, bool pretty_print = true) const override; | |||
346 | ||||
347 | protected: | |||
348 | std::string m_value; | |||
349 | }; | |||
350 | ||||
351 | class Dictionary : public Object { | |||
352 | public: | |||
353 | Dictionary() : Object(lldb::eStructuredDataTypeDictionary), m_dict() {} | |||
354 | ||||
355 | ~Dictionary() override = default; | |||
356 | ||||
357 | size_t GetSize() const { return m_dict.size(); } | |||
358 | ||||
359 | void ForEach(std::function<bool(ConstString key, Object *object)> const | |||
360 | &callback) const { | |||
361 | for (const auto &pair : m_dict) { | |||
362 | if (callback(pair.first, pair.second.get()) == false) | |||
363 | break; | |||
364 | } | |||
365 | } | |||
366 | ||||
367 | ObjectSP GetKeys() const { | |||
368 | auto object_sp = std::make_shared<Array>(); | |||
369 | collection::const_iterator iter; | |||
370 | for (iter = m_dict.begin(); iter != m_dict.end(); ++iter) { | |||
371 | auto key_object_sp = std::make_shared<String>(); | |||
372 | key_object_sp->SetValue(iter->first.AsCString()); | |||
373 | object_sp->Push(key_object_sp); | |||
374 | } | |||
375 | return object_sp; | |||
376 | } | |||
377 | ||||
378 | ObjectSP GetValueForKey(llvm::StringRef key) const { | |||
379 | ObjectSP value_sp; | |||
380 | if (!key.empty()) { | |||
381 | ConstString key_cs(key); | |||
382 | collection::const_iterator iter = m_dict.find(key_cs); | |||
383 | if (iter != m_dict.end()) | |||
384 | value_sp = iter->second; | |||
385 | } | |||
386 | return value_sp; | |||
387 | } | |||
388 | ||||
389 | bool GetValueForKeyAsBoolean(llvm::StringRef key, bool &result) const { | |||
390 | bool success = false; | |||
391 | ObjectSP value_sp = GetValueForKey(key); | |||
392 | if (value_sp.get()) { | |||
393 | Boolean *result_ptr = value_sp->GetAsBoolean(); | |||
394 | if (result_ptr) { | |||
395 | result = result_ptr->GetValue(); | |||
396 | success = true; | |||
397 | } | |||
398 | } | |||
399 | return success; | |||
400 | } | |||
401 | template <class IntType> | |||
402 | bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result) const { | |||
403 | ObjectSP value_sp = GetValueForKey(key); | |||
404 | if (value_sp) { | |||
405 | if (auto int_value = value_sp->GetAsInteger()) { | |||
406 | result = static_cast<IntType>(int_value->GetValue()); | |||
407 | return true; | |||
408 | } | |||
409 | } | |||
410 | return false; | |||
411 | } | |||
412 | ||||
413 | template <class IntType> | |||
414 | bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result, | |||
415 | IntType default_val) const { | |||
416 | bool success = GetValueForKeyAsInteger<IntType>(key, result); | |||
417 | if (!success) | |||
418 | result = default_val; | |||
419 | return success; | |||
420 | } | |||
421 | ||||
422 | bool GetValueForKeyAsString(llvm::StringRef key, | |||
423 | llvm::StringRef &result) const { | |||
424 | ObjectSP value_sp = GetValueForKey(key); | |||
425 | if (value_sp.get()) { | |||
426 | if (auto string_value = value_sp->GetAsString()) { | |||
427 | result = string_value->GetValue(); | |||
428 | return true; | |||
429 | } | |||
430 | } | |||
431 | return false; | |||
432 | } | |||
433 | ||||
434 | bool GetValueForKeyAsString(llvm::StringRef key, llvm::StringRef &result, | |||
435 | const char *default_val) const { | |||
436 | bool success = GetValueForKeyAsString(key, result); | |||
437 | if (!success) { | |||
438 | if (default_val) | |||
439 | result = default_val; | |||
440 | else | |||
441 | result = llvm::StringRef(); | |||
442 | } | |||
443 | return success; | |||
444 | } | |||
445 | ||||
446 | bool GetValueForKeyAsString(llvm::StringRef key, | |||
447 | ConstString &result) const { | |||
448 | ObjectSP value_sp = GetValueForKey(key); | |||
449 | if (value_sp.get()) { | |||
450 | if (auto string_value = value_sp->GetAsString()) { | |||
451 | result = ConstString(string_value->GetValue()); | |||
452 | return true; | |||
453 | } | |||
454 | } | |||
455 | return false; | |||
456 | } | |||
457 | ||||
458 | bool GetValueForKeyAsString(llvm::StringRef key, ConstString &result, | |||
459 | const char *default_val) const { | |||
460 | bool success = GetValueForKeyAsString(key, result); | |||
461 | if (!success) | |||
462 | result.SetCString(default_val); | |||
463 | return success; | |||
464 | } | |||
465 | ||||
466 | bool GetValueForKeyAsDictionary(llvm::StringRef key, | |||
467 | Dictionary *&result) const { | |||
468 | result = nullptr; | |||
469 | ObjectSP value_sp = GetValueForKey(key); | |||
| ||||
470 | if (value_sp.get()) { | |||
471 | result = value_sp->GetAsDictionary(); | |||
472 | return (result != nullptr); | |||
473 | } | |||
474 | return false; | |||
475 | } | |||
476 | ||||
477 | bool GetValueForKeyAsArray(llvm::StringRef key, Array *&result) const { | |||
478 | result = nullptr; | |||
479 | ObjectSP value_sp = GetValueForKey(key); | |||
480 | if (value_sp.get()) { | |||
481 | result = value_sp->GetAsArray(); | |||
482 | return (result != nullptr); | |||
483 | } | |||
484 | return false; | |||
485 | } | |||
486 | ||||
487 | bool HasKey(llvm::StringRef key) const { | |||
488 | ConstString key_cs(key); | |||
489 | collection::const_iterator search = m_dict.find(key_cs); | |||
490 | return search != m_dict.end(); | |||
491 | } | |||
492 | ||||
493 | void AddItem(llvm::StringRef key, ObjectSP value_sp) { | |||
494 | ConstString key_cs(key); | |||
495 | m_dict[key_cs] = value_sp; | |||
496 | } | |||
497 | ||||
498 | void AddIntegerItem(llvm::StringRef key, uint64_t value) { | |||
499 | AddItem(key, std::make_shared<Integer>(value)); | |||
500 | } | |||
501 | ||||
502 | void AddFloatItem(llvm::StringRef key, double value) { | |||
503 | AddItem(key, std::make_shared<Float>(value)); | |||
504 | } | |||
505 | ||||
506 | void AddStringItem(llvm::StringRef key, llvm::StringRef value) { | |||
507 | AddItem(key, std::make_shared<String>(std::move(value))); | |||
508 | } | |||
509 | ||||
510 | void AddBooleanItem(llvm::StringRef key, bool value) { | |||
511 | AddItem(key, std::make_shared<Boolean>(value)); | |||
512 | } | |||
513 | ||||
514 | void Dump(Stream &s, bool pretty_print = true) const override; | |||
515 | ||||
516 | protected: | |||
517 | typedef std::map<ConstString, ObjectSP> collection; | |||
518 | collection m_dict; | |||
519 | }; | |||
520 | ||||
521 | class Null : public Object { | |||
522 | public: | |||
523 | Null() : Object(lldb::eStructuredDataTypeNull) {} | |||
524 | ||||
525 | ~Null() override = default; | |||
526 | ||||
527 | bool IsValid() const override { return false; } | |||
528 | ||||
529 | void Dump(Stream &s, bool pretty_print = true) const override; | |||
530 | }; | |||
531 | ||||
532 | class Generic : public Object { | |||
533 | public: | |||
534 | explicit Generic(void *object = nullptr) | |||
535 | : Object(lldb::eStructuredDataTypeGeneric), m_object(object) {} | |||
536 | ||||
537 | void SetValue(void *value) { m_object = value; } | |||
538 | ||||
539 | void *GetValue() const { return m_object; } | |||
540 | ||||
541 | bool IsValid() const override { return m_object != nullptr; } | |||
542 | ||||
543 | void Dump(Stream &s, bool pretty_print = true) const override; | |||
544 | ||||
545 | private: | |||
546 | void *m_object; | |||
547 | }; | |||
548 | ||||
549 | static ObjectSP ParseJSON(std::string json_text); | |||
550 | ||||
551 | static ObjectSP ParseJSONFromFile(const FileSpec &file, Status &error); | |||
552 | }; | |||
553 | ||||
554 | } // namespace lldb_private | |||
555 | ||||
556 | #endif // liblldb_StructuredData_h_ |