]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Core/StructuredData.cpp
Upgrade to Unbound 1.5.4.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Core / StructuredData.cpp
1 //===---------------------StructuredData.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/Core/StructuredData.h"
11
12 #include <errno.h>
13 #include <stdlib.h>
14 #include <inttypes.h>
15
16 using namespace lldb_private;
17
18
19 static StructuredData::ObjectSP read_json_object (const char **ch);
20 static StructuredData::ObjectSP read_json_array (const char **ch);
21
22 static StructuredData::ObjectSP
23 read_json_number (const char **ch)
24 {
25     StructuredData::ObjectSP object_sp;
26     while (isspace (**ch))
27         (*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')
32     {
33         if (isdigit(**ch) == false && **ch != '-')
34         {
35             is_integer = false;
36             is_float = true;
37         }
38         (*ch)++;
39     }
40     while (isspace (**ch))
41         (*ch)++;
42     if (**ch == ',' || **ch == ']' || **ch == '}')
43     {
44         if (is_integer)
45         {
46             errno = 0;
47             uint64_t val = strtoul (start_of_number, NULL, 10);
48             if (errno == 0)
49             {
50                 object_sp.reset(new StructuredData::Integer());
51                 object_sp->GetAsInteger()->SetValue (val);
52             }
53         }
54         if (is_float)
55         {
56             char *end_of_number = NULL;
57             errno = 0;
58             double val = strtod (start_of_number, &end_of_number);
59             if (errno == 0 && end_of_number != start_of_number && end_of_number != NULL)
60             {
61                 object_sp.reset(new StructuredData::Float());
62                 object_sp->GetAsFloat()->SetValue (val);
63             }
64         }
65     }
66     return object_sp;
67 }
68
69 static std::string
70 read_json_string (const char **ch)
71 {
72     std::string string;
73     if (**ch == '"')
74     {
75         (*ch)++;
76         while (**ch != '\0')
77         {
78             if (**ch == '"')
79             {
80                 (*ch)++;
81                 while (isspace (**ch))
82                     (*ch)++;
83                 break;
84             }
85             else if (**ch == '\\')
86             {
87                 switch (**ch)
88                 {
89                     case '"':
90                         string.push_back('"');
91                         *ch += 2;
92                         break;
93                     case '\\':
94                         string.push_back('\\');
95                         *ch += 2;
96                         break;
97                     case '/':
98                         string.push_back('/');
99                         *ch += 2;
100                         break;
101                     case 'b':
102                         string.push_back('\b');
103                         *ch += 2;
104                         break;
105                     case 'f':
106                         string.push_back('\f');
107                         *ch += 2;
108                         break;
109                     case 'n':
110                         string.push_back('\n');
111                         *ch += 2;
112                         break;
113                     case 'r':
114                         string.push_back('\r');
115                         *ch += 2;
116                         break;
117                     case 't':
118                         string.push_back('\t');
119                         *ch += 2;
120                         break;
121                     case 'u':
122                         // FIXME handle four-hex-digits 
123                         *ch += 10;
124                         break;
125                     default:
126                         *ch += 1;
127                 }
128             }
129             else
130             {
131                 string.push_back (**ch);
132             }
133             (*ch)++;
134         }
135     }
136     return string;
137 }
138
139 static StructuredData::ObjectSP
140 read_json_value (const char **ch)
141 {
142     StructuredData::ObjectSP object_sp;
143     while (isspace (**ch))
144         (*ch)++;
145
146     if (**ch == '{')
147     {
148         object_sp = read_json_object (ch);
149     }
150     else if (**ch == '[')
151     {
152         object_sp = read_json_array (ch);
153     }
154     else if (**ch == '"')
155     {
156         std::string string = read_json_string (ch);
157         object_sp.reset(new StructuredData::String());
158         object_sp->GetAsString()->SetValue(string);
159     }
160     else
161     {
162         if (strncmp (*ch, "true", 4) == 0)
163         {
164             object_sp.reset(new StructuredData::Boolean());
165             object_sp->GetAsBoolean()->SetValue(true);
166             *ch += 4;
167         }
168         else if (strncmp (*ch, "false", 5) == 0)
169         {
170             object_sp.reset(new StructuredData::Boolean());
171             object_sp->GetAsBoolean()->SetValue(false);
172             *ch += 5;
173         }
174         else if (strncmp (*ch, "null", 4) == 0)
175         {
176             object_sp.reset(new StructuredData::Null());
177             *ch += 4;
178         }
179         else
180         {
181             object_sp = read_json_number (ch);
182         }
183     }
184     return object_sp;
185 }
186
187 static StructuredData::ObjectSP
188 read_json_array (const char **ch)
189 {
190     StructuredData::ObjectSP object_sp;
191     if (**ch == '[')
192     {
193         (*ch)++;
194         while (isspace (**ch))
195             (*ch)++;
196
197         bool first_value = true;
198         while (**ch != '\0' && (first_value || **ch == ','))
199         {
200             if (**ch == ',')
201                 (*ch)++;
202             first_value = false;
203             while (isspace (**ch))
204                 (*ch)++;
205             lldb_private::StructuredData::ObjectSP value_sp = read_json_value (ch);
206             if (value_sp)
207             {
208                 if (object_sp.get() == NULL)
209                 {
210                     object_sp.reset(new StructuredData::Array());
211                 }
212                 object_sp->GetAsArray()->Push (value_sp);
213             }
214             while (isspace (**ch))
215                 (*ch)++;
216         }
217         if (**ch == ']')
218         {
219             // FIXME should throw an error if we don't see a } to close out the JSON object
220             (*ch)++;
221             while (isspace (**ch))
222                 (*ch)++;
223         }
224     }
225     return object_sp;
226 }
227
228 static StructuredData::ObjectSP
229 read_json_object (const char **ch)
230 {
231     StructuredData::ObjectSP object_sp;
232     if (**ch == '{')
233     {
234         (*ch)++;
235         while (isspace (**ch))
236             (*ch)++;
237         bool first_pair = true;
238         while (**ch != '\0' && (first_pair || **ch == ','))
239         {
240             first_pair = false;
241             if (**ch == ',')
242                 (*ch)++;
243             while (isspace (**ch))
244                 (*ch)++;
245             if (**ch != '"')
246                 break;
247             std::string key_string = read_json_string (ch);
248             while (isspace (**ch))
249                 (*ch)++;
250             if (key_string.size() > 0 && **ch == ':')
251             {
252                 (*ch)++;
253                 while (isspace (**ch))
254                     (*ch)++;
255                 lldb_private::StructuredData::ObjectSP value_sp = read_json_value (ch);
256                 if (value_sp.get())
257                 {
258                     if (object_sp.get() == NULL)
259                     {
260                         object_sp.reset(new StructuredData::Dictionary());
261                     }
262                     object_sp->GetAsDictionary()->AddItem (key_string.c_str(), value_sp);
263                 }
264             }
265             while (isspace (**ch))
266                 (*ch)++;
267         }
268         if (**ch == '}')
269         {
270             // FIXME should throw an error if we don't see a } to close out the JSON object
271             (*ch)++;
272             while (isspace (**ch))
273                 (*ch)++;
274         }
275     }
276     return object_sp;
277 }
278
279
280 StructuredData::ObjectSP
281 StructuredData::ParseJSON (std::string json_text)
282 {
283     StructuredData::ObjectSP object_sp;
284     const size_t json_text_size = json_text.size();
285     if (json_text_size > 0)
286     {
287         const char *start_of_json_text = json_text.c_str();
288         const char *c = json_text.c_str();
289         while (*c != '\0' &&
290                static_cast<size_t>(c - start_of_json_text) <= json_text_size)
291         {
292             while (isspace (*c) &&
293                    static_cast<size_t>(c - start_of_json_text) < json_text_size)
294                 c++;
295             if (*c == '{')
296             {
297                 object_sp = read_json_object (&c);
298             }
299             else
300             {
301                 // We have bad characters here, this is likely an illegal JSON string.
302                 return object_sp;
303             }
304         }
305     }
306     return object_sp;
307 }
308
309 StructuredData::ObjectSP
310 StructuredData::Object::GetObjectForDotSeparatedPath (llvm::StringRef path)
311 {
312     if (this->GetType() == Type::eTypeDictionary)
313     {
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());
317         if (value.get())
318         {
319             // Do we have additional words to descend?  If not, return the
320             // value we're at right now.
321             if (match.second.empty())
322             {
323                 return value;
324             }
325             else
326             {
327                 return value->GetObjectForDotSeparatedPath (match.second);
328             }
329         }
330         return ObjectSP();
331     }
332
333     if (this->GetType() == Type::eTypeArray)
334     {
335         std::pair<llvm::StringRef, llvm::StringRef> match = path.split('[');
336         if (match.second.size() == 0)
337         {
338             return this->shared_from_this();
339         }
340         errno = 0;
341         uint64_t val = strtoul (match.second.str().c_str(), NULL, 10);
342         if (errno == 0)
343         {
344             return this->GetAsArray()->GetItemAtIndex(val);
345         }
346         return ObjectSP();
347     }
348
349     return this->shared_from_this();
350 }
351
352 void
353 StructuredData::Array::Dump (Stream &s) const
354 {
355     s << "[";
356     const size_t arrsize = m_items.size();
357     for (size_t i = 0; i < arrsize; ++i)
358     {
359         m_items[i]->Dump(s);
360         if (i + 1 < arrsize)
361             s << ",";
362     }
363     s << "]";
364 }
365
366 void
367 StructuredData::Integer::Dump (Stream &s) const
368 {
369     s.Printf ("%" PRIu64, m_value);
370 }
371
372
373 void
374 StructuredData::Float::Dump (Stream &s) const
375 {
376     s.Printf ("%lf", m_value);
377 }
378
379 void
380 StructuredData::Boolean::Dump (Stream &s) const
381 {
382     if (m_value == true)
383         s.PutCString ("true");
384     else
385         s.PutCString ("false");
386 }
387
388
389 void
390 StructuredData::String::Dump (Stream &s) const
391 {
392     std::string quoted;
393     const size_t strsize = m_value.size();
394     for (size_t i = 0; i < strsize ; ++i)
395     {
396         char ch = m_value[i];
397         if (ch == '"')
398             quoted.push_back ('\\');
399         quoted.push_back (ch);
400     }
401     s.Printf ("\"%s\"", quoted.c_str());
402 }
403
404 void
405 StructuredData::Dictionary::Dump (Stream &s) const
406 {
407     bool have_printed_one_elem = false;
408     s << "{";
409     for (collection::const_iterator iter = m_dict.begin(); iter != m_dict.end(); ++iter)
410     {
411         if (have_printed_one_elem == false)
412         {
413             have_printed_one_elem = true;
414         }
415         else
416         {
417             s << ",";
418         }
419         s << "\"" << iter->first.AsCString() << "\":";
420         iter->second->Dump(s);
421     }
422     s << "}";
423 }
424
425 void
426 StructuredData::Null::Dump (Stream &s) const
427 {
428     s << "null";
429 }