1 //===---------------------StructuredData.cpp ---------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/Core/StructuredData.h"
16 using namespace lldb_private;
19 static StructuredData::ObjectSP read_json_object (const char **ch);
20 static StructuredData::ObjectSP read_json_array (const char **ch);
22 static StructuredData::ObjectSP
23 read_json_number (const char **ch)
25 StructuredData::ObjectSP object_sp;
26 while (isspace (**ch))
28 const char *start_of_number = *ch;
29 bool is_integer = true;
30 bool is_float = false;
31 while (isdigit(**ch) || **ch == '-' || **ch == '.' || **ch == '+' || **ch == 'e' || **ch == 'E')
33 if (isdigit(**ch) == false && **ch != '-')
40 while (isspace (**ch))
42 if (**ch == ',' || **ch == ']' || **ch == '}')
47 uint64_t val = strtoul (start_of_number, NULL, 10);
50 object_sp.reset(new StructuredData::Integer());
51 object_sp->GetAsInteger()->SetValue (val);
56 char *end_of_number = NULL;
58 double val = strtod (start_of_number, &end_of_number);
59 if (errno == 0 && end_of_number != start_of_number && end_of_number != NULL)
61 object_sp.reset(new StructuredData::Float());
62 object_sp->GetAsFloat()->SetValue (val);
70 read_json_string (const char **ch)
81 while (isspace (**ch))
85 else if (**ch == '\\')
90 string.push_back('"');
94 string.push_back('\\');
98 string.push_back('/');
102 string.push_back('\b');
106 string.push_back('\f');
110 string.push_back('\n');
114 string.push_back('\r');
118 string.push_back('\t');
122 // FIXME handle four-hex-digits
131 string.push_back (**ch);
139 static StructuredData::ObjectSP
140 read_json_value (const char **ch)
142 StructuredData::ObjectSP object_sp;
143 while (isspace (**ch))
148 object_sp = read_json_object (ch);
150 else if (**ch == '[')
152 object_sp = read_json_array (ch);
154 else if (**ch == '"')
156 std::string string = read_json_string (ch);
157 object_sp.reset(new StructuredData::String());
158 object_sp->GetAsString()->SetValue(string);
162 if (strncmp (*ch, "true", 4) == 0)
164 object_sp.reset(new StructuredData::Boolean());
165 object_sp->GetAsBoolean()->SetValue(true);
168 else if (strncmp (*ch, "false", 5) == 0)
170 object_sp.reset(new StructuredData::Boolean());
171 object_sp->GetAsBoolean()->SetValue(false);
174 else if (strncmp (*ch, "null", 4) == 0)
176 object_sp.reset(new StructuredData::Null());
181 object_sp = read_json_number (ch);
187 static StructuredData::ObjectSP
188 read_json_array (const char **ch)
190 StructuredData::ObjectSP object_sp;
194 while (isspace (**ch))
197 bool first_value = true;
198 while (**ch != '\0' && (first_value || **ch == ','))
203 while (isspace (**ch))
205 lldb_private::StructuredData::ObjectSP value_sp = read_json_value (ch);
208 if (object_sp.get() == NULL)
210 object_sp.reset(new StructuredData::Array());
212 object_sp->GetAsArray()->Push (value_sp);
214 while (isspace (**ch))
219 // FIXME should throw an error if we don't see a } to close out the JSON object
221 while (isspace (**ch))
228 static StructuredData::ObjectSP
229 read_json_object (const char **ch)
231 StructuredData::ObjectSP object_sp;
235 while (isspace (**ch))
237 bool first_pair = true;
238 while (**ch != '\0' && (first_pair || **ch == ','))
243 while (isspace (**ch))
247 std::string key_string = read_json_string (ch);
248 while (isspace (**ch))
250 if (key_string.size() > 0 && **ch == ':')
253 while (isspace (**ch))
255 lldb_private::StructuredData::ObjectSP value_sp = read_json_value (ch);
258 if (object_sp.get() == NULL)
260 object_sp.reset(new StructuredData::Dictionary());
262 object_sp->GetAsDictionary()->AddItem (key_string.c_str(), value_sp);
265 while (isspace (**ch))
270 // FIXME should throw an error if we don't see a } to close out the JSON object
272 while (isspace (**ch))
280 StructuredData::ObjectSP
281 StructuredData::ParseJSON (std::string json_text)
283 StructuredData::ObjectSP object_sp;
284 const size_t json_text_size = json_text.size();
285 if (json_text_size > 0)
287 const char *start_of_json_text = json_text.c_str();
288 const char *c = json_text.c_str();
290 static_cast<size_t>(c - start_of_json_text) <= json_text_size)
292 while (isspace (*c) &&
293 static_cast<size_t>(c - start_of_json_text) < json_text_size)
297 object_sp = read_json_object (&c);
301 // We have bad characters here, this is likely an illegal JSON string.
309 StructuredData::ObjectSP
310 StructuredData::Object::GetObjectForDotSeparatedPath (llvm::StringRef path)
312 if (this->GetType() == Type::eTypeDictionary)
314 std::pair<llvm::StringRef, llvm::StringRef> match = path.split('.');
315 std::string key = match.first.str();
316 ObjectSP value = this->GetAsDictionary()->GetValueForKey (key.c_str());
319 // Do we have additional words to descend? If not, return the
320 // value we're at right now.
321 if (match.second.empty())
327 return value->GetObjectForDotSeparatedPath (match.second);
333 if (this->GetType() == Type::eTypeArray)
335 std::pair<llvm::StringRef, llvm::StringRef> match = path.split('[');
336 if (match.second.size() == 0)
338 return this->shared_from_this();
341 uint64_t val = strtoul (match.second.str().c_str(), NULL, 10);
344 return this->GetAsArray()->GetItemAtIndex(val);
349 return this->shared_from_this();
353 StructuredData::Array::Dump (Stream &s) const
356 const size_t arrsize = m_items.size();
357 for (size_t i = 0; i < arrsize; ++i)
367 StructuredData::Integer::Dump (Stream &s) const
369 s.Printf ("%" PRIu64, m_value);
374 StructuredData::Float::Dump (Stream &s) const
376 s.Printf ("%lf", m_value);
380 StructuredData::Boolean::Dump (Stream &s) const
383 s.PutCString ("true");
385 s.PutCString ("false");
390 StructuredData::String::Dump (Stream &s) const
393 const size_t strsize = m_value.size();
394 for (size_t i = 0; i < strsize ; ++i)
396 char ch = m_value[i];
398 quoted.push_back ('\\');
399 quoted.push_back (ch);
401 s.Printf ("\"%s\"", quoted.c_str());
405 StructuredData::Dictionary::Dump (Stream &s) const
407 bool have_printed_one_elem = false;
409 for (collection::const_iterator iter = m_dict.begin(); iter != m_dict.end(); ++iter)
411 if (have_printed_one_elem == false)
413 have_printed_one_elem = true;
419 s << "\"" << iter->first.AsCString() << "\":";
420 iter->second->Dump(s);
426 StructuredData::Null::Dump (Stream &s) const