[libc++] Remove duplicated _LIBCPP_HIDE_FROM_ABI from a few declarations (#122323)
[llvm-project.git] / lldb / tools / debugserver / source / JSON.cpp
blob5453d857cb214cc144095509b356e21ba05331b7
1 //===--------------------- JSON.cpp -----------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "JSON.h"
11 // C includes
12 #include <cassert>
13 #include <climits>
15 // C++ includes
16 #include "StringConvert.h"
17 #include <iomanip>
18 #include <sstream>
20 std::string JSONString::json_string_quote_metachars(const std::string &s) {
21 if (s.find('"') == std::string::npos)
22 return s;
24 std::string output;
25 const size_t s_size = s.size();
26 const char *s_chars = s.c_str();
27 for (size_t i = 0; i < s_size; i++) {
28 unsigned char ch = *(s_chars + i);
29 if (ch == '"') {
30 output.push_back('\\');
32 output.push_back(ch);
34 return output;
37 JSONString::JSONString() : JSONValue(JSONValue::Kind::String), m_data() {}
39 JSONString::JSONString(const char *s)
40 : JSONValue(JSONValue::Kind::String), m_data(s ? s : "") {}
42 JSONString::JSONString(const std::string &s)
43 : JSONValue(JSONValue::Kind::String), m_data(s) {}
45 void JSONString::Write(std::ostream &s) {
46 s << "\"" << json_string_quote_metachars(m_data) << "\"";
49 uint64_t JSONNumber::GetAsUnsigned() const {
50 switch (m_data_type) {
51 case DataType::Unsigned:
52 return m_data.m_unsigned;
53 case DataType::Signed:
54 return (uint64_t)m_data.m_signed;
55 case DataType::Double:
56 return (uint64_t)m_data.m_double;
60 int64_t JSONNumber::GetAsSigned() const {
61 switch (m_data_type) {
62 case DataType::Unsigned:
63 return (int64_t)m_data.m_unsigned;
64 case DataType::Signed:
65 return m_data.m_signed;
66 case DataType::Double:
67 return (int64_t)m_data.m_double;
71 double JSONNumber::GetAsDouble() const {
72 switch (m_data_type) {
73 case DataType::Unsigned:
74 return (double)m_data.m_unsigned;
75 case DataType::Signed:
76 return (double)m_data.m_signed;
77 case DataType::Double:
78 return m_data.m_double;
82 void JSONNumber::Write(std::ostream &s) {
83 switch (m_data_type) {
84 case DataType::Unsigned:
85 s << m_data.m_unsigned;
86 break;
87 case DataType::Signed:
88 s << m_data.m_signed;
89 break;
90 case DataType::Double:
91 // Set max precision to emulate %g.
92 s << std::setprecision(std::numeric_limits<double>::digits10 + 1);
93 s << m_data.m_double;
94 break;
98 JSONTrue::JSONTrue() : JSONValue(JSONValue::Kind::True) {}
100 void JSONTrue::Write(std::ostream &s) { s << "true"; }
102 JSONFalse::JSONFalse() : JSONValue(JSONValue::Kind::False) {}
104 void JSONFalse::Write(std::ostream &s) { s << "false"; }
106 JSONNull::JSONNull() : JSONValue(JSONValue::Kind::Null) {}
108 void JSONNull::Write(std::ostream &s) { s << "null"; }
110 JSONObject::JSONObject() : JSONValue(JSONValue::Kind::Object) {}
112 void JSONObject::Write(std::ostream &s) {
113 bool first = true;
114 s << '{';
115 auto iter = m_elements.begin(), end = m_elements.end();
116 for (; iter != end; iter++) {
117 if (first)
118 first = false;
119 else
120 s << ',';
121 JSONString key(iter->first);
122 JSONValue::SP value(iter->second);
123 key.Write(s);
124 s << ':';
125 value->Write(s);
127 s << '}';
130 bool JSONObject::SetObject(const std::string &key, JSONValue::SP value) {
131 if (key.empty() || nullptr == value.get())
132 return false;
133 m_elements[key] = value;
134 return true;
137 JSONValue::SP JSONObject::GetObject(const std::string &key) const {
138 auto iter = m_elements.find(key), end = m_elements.end();
139 if (iter == end)
140 return JSONValue::SP();
141 return iter->second;
144 bool JSONObject::GetObjectAsBool(const std::string &key, bool &value) const {
145 auto value_sp = GetObject(key);
146 if (!value_sp) {
147 // The given key doesn't exist, so we have no value.
148 return false;
151 if (JSONTrue::classof(value_sp.get())) {
152 // We have the value, and it is true.
153 value = true;
154 return true;
155 } else if (JSONFalse::classof(value_sp.get())) {
156 // We have the value, and it is false.
157 value = false;
158 return true;
159 } else {
160 // We don't have a valid bool value for the given key.
161 return false;
165 bool JSONObject::GetObjectAsString(const std::string &key,
166 std::string &value) const {
167 auto value_sp = GetObject(key);
168 if (!value_sp) {
169 // The given key doesn't exist, so we have no value.
170 return false;
173 if (!JSONString::classof(value_sp.get()))
174 return false;
176 value = static_cast<JSONString *>(value_sp.get())->GetData();
177 return true;
180 JSONArray::JSONArray() : JSONValue(JSONValue::Kind::Array) {}
182 void JSONArray::Write(std::ostream &s) {
183 bool first = true;
184 s << '[';
185 auto iter = m_elements.begin(), end = m_elements.end();
186 for (; iter != end; iter++) {
187 if (first)
188 first = false;
189 else
190 s << ',';
191 (*iter)->Write(s);
193 s << ']';
196 bool JSONArray::SetObject(Index i, JSONValue::SP value) {
197 if (value.get() == nullptr)
198 return false;
199 if (i < m_elements.size()) {
200 m_elements[i] = value;
201 return true;
203 if (i == m_elements.size()) {
204 m_elements.push_back(value);
205 return true;
207 return false;
210 bool JSONArray::AppendObject(JSONValue::SP value) {
211 if (value.get() == nullptr)
212 return false;
213 m_elements.push_back(value);
214 return true;
217 JSONValue::SP JSONArray::GetObject(Index i) {
218 if (i < m_elements.size())
219 return m_elements[i];
220 return JSONValue::SP();
223 JSONArray::Size JSONArray::GetNumElements() { return m_elements.size(); }
225 JSONParser::JSONParser(const char *cstr) : StdStringExtractor(cstr) {}
227 JSONParser::Token JSONParser::GetToken(std::string &value) {
228 std::ostringstream error;
230 value.clear();
231 SkipSpaces();
232 const uint64_t start_index = m_index;
233 const char ch = GetChar();
234 switch (ch) {
235 case '{':
236 return Token::ObjectStart;
237 case '}':
238 return Token::ObjectEnd;
239 case '[':
240 return Token::ArrayStart;
241 case ']':
242 return Token::ArrayEnd;
243 case ',':
244 return Token::Comma;
245 case ':':
246 return Token::Colon;
247 case '\0':
248 return Token::EndOfFile;
249 case 't':
250 if (GetChar() == 'r')
251 if (GetChar() == 'u')
252 if (GetChar() == 'e')
253 return Token::True;
254 break;
256 case 'f':
257 if (GetChar() == 'a')
258 if (GetChar() == 'l')
259 if (GetChar() == 's')
260 if (GetChar() == 'e')
261 return Token::False;
262 break;
264 case 'n':
265 if (GetChar() == 'u')
266 if (GetChar() == 'l')
267 if (GetChar() == 'l')
268 return Token::Null;
269 break;
271 case '"': {
272 while (true) {
273 bool was_escaped = false;
274 int escaped_ch = GetEscapedChar(was_escaped);
275 if (escaped_ch == -1) {
276 error << "error: an error occurred getting a character from offset "
277 << start_index;
278 value = error.str();
279 return Token::Status;
281 } else {
282 const bool is_end_quote = escaped_ch == '"';
283 const bool is_null = escaped_ch == 0;
284 if (was_escaped || (!is_end_quote && !is_null)) {
285 if (CHAR_MIN <= escaped_ch && escaped_ch <= CHAR_MAX) {
286 value.append(1, (char)escaped_ch);
287 } else {
288 error << "error: wide character support is needed for unicode "
289 "character 0x"
290 << std::setprecision(4) << std::hex << escaped_ch;
291 error << " at offset " << start_index;
292 value = error.str();
293 return Token::Status;
295 } else if (is_end_quote) {
296 return Token::String;
297 } else if (is_null) {
298 value = "error: missing end quote for string";
299 return Token::Status;
303 } break;
305 case '-':
306 case '0':
307 case '1':
308 case '2':
309 case '3':
310 case '4':
311 case '5':
312 case '6':
313 case '7':
314 case '8':
315 case '9': {
316 bool done = false;
317 bool got_decimal_point = false;
318 uint64_t exp_index = 0;
319 bool got_int_digits = (ch >= '0') && (ch <= '9');
320 bool got_frac_digits = false;
321 bool got_exp_digits = false;
322 while (!done) {
323 const char next_ch = PeekChar();
324 switch (next_ch) {
325 case '0':
326 case '1':
327 case '2':
328 case '3':
329 case '4':
330 case '5':
331 case '6':
332 case '7':
333 case '8':
334 case '9':
335 if (exp_index != 0) {
336 got_exp_digits = true;
337 } else if (got_decimal_point) {
338 got_frac_digits = true;
339 } else {
340 got_int_digits = true;
342 ++m_index; // Skip this character
343 break;
345 case '.':
346 if (got_decimal_point) {
347 error << "error: extra decimal point found at offset " << start_index;
348 value = error.str();
349 return Token::Status;
350 } else {
351 got_decimal_point = true;
352 ++m_index; // Skip this character
354 break;
356 case 'e':
357 case 'E':
358 if (exp_index != 0) {
359 error << "error: extra exponent character found at offset "
360 << start_index;
361 value = error.str();
362 return Token::Status;
363 } else {
364 exp_index = m_index;
365 ++m_index; // Skip this character
367 break;
369 case '+':
370 case '-':
371 // The '+' and '-' can only come after an exponent character...
372 if (exp_index == m_index - 1) {
373 ++m_index; // Skip the exponent sign character
374 } else {
375 error << "error: unexpected " << next_ch << " character at offset "
376 << start_index;
377 value = error.str();
378 return Token::Status;
380 break;
382 default:
383 done = true;
384 break;
388 if (m_index > start_index) {
389 value = m_packet.substr(start_index, m_index - start_index);
390 if (got_decimal_point) {
391 if (exp_index != 0) {
392 // We have an exponent, make sure we got exponent digits
393 if (got_exp_digits) {
394 return Token::Float;
395 } else {
396 error << "error: got exponent character but no exponent digits at "
397 "offset in float value \""
398 << value << "\"";
399 value = error.str();
400 return Token::Status;
402 } else {
403 // No exponent, but we need at least one decimal after the decimal
404 // point
405 if (got_frac_digits) {
406 return Token::Float;
407 } else {
408 error << "error: no digits after decimal point \"" << value << "\"";
409 value = error.str();
410 return Token::Status;
413 } else {
414 // No decimal point
415 if (got_int_digits) {
416 // We need at least some integer digits to make an integer
417 return Token::Integer;
418 } else {
419 error << "error: no digits negate sign \"" << value << "\"";
420 value = error.str();
421 return Token::Status;
424 } else {
425 error << "error: invalid number found at offset " << start_index;
426 value = error.str();
427 return Token::Status;
429 } break;
430 default:
431 break;
433 error << "error: failed to parse token at offset " << start_index
434 << " (around character '" << ch << "')";
435 value = error.str();
436 return Token::Status;
439 int JSONParser::GetEscapedChar(bool &was_escaped) {
440 was_escaped = false;
441 const char ch = GetChar();
442 if (ch == '\\') {
443 was_escaped = true;
444 const char ch2 = GetChar();
445 switch (ch2) {
446 case '"':
447 case '\\':
448 case '/':
449 default:
450 break;
452 case 'b':
453 return '\b';
454 case 'f':
455 return '\f';
456 case 'n':
457 return '\n';
458 case 'r':
459 return '\r';
460 case 't':
461 return '\t';
462 case 'u': {
463 const int hi_byte = DecodeHexU8();
464 const int lo_byte = DecodeHexU8();
465 if (hi_byte >= 0 && lo_byte >= 0)
466 return hi_byte << 8 | lo_byte;
467 return -1;
468 } break;
470 return ch2;
472 return ch;
475 JSONValue::SP JSONParser::ParseJSONObject() {
476 // The "JSONParser::Token::ObjectStart" token should have already been
477 // consumed
478 // by the time this function is called
479 std::unique_ptr<JSONObject> dict_up(new JSONObject());
481 std::string value;
482 std::string key;
483 while (true) {
484 JSONParser::Token token = GetToken(value);
486 if (token == JSONParser::Token::String) {
487 key.swap(value);
488 token = GetToken(value);
489 if (token == JSONParser::Token::Colon) {
490 JSONValue::SP value_sp = ParseJSONValue();
491 if (value_sp)
492 dict_up->SetObject(key, value_sp);
493 else
494 break;
496 } else if (token == JSONParser::Token::ObjectEnd) {
497 return JSONValue::SP(dict_up.release());
498 } else if (token == JSONParser::Token::Comma) {
499 continue;
500 } else {
501 break;
504 return JSONValue::SP();
507 JSONValue::SP JSONParser::ParseJSONArray() {
508 // The "JSONParser::Token::ObjectStart" token should have already been
509 // consumed
510 // by the time this function is called
511 std::unique_ptr<JSONArray> array_up(new JSONArray());
513 std::string value;
514 std::string key;
515 while (true) {
516 JSONParser::Token token = GetToken(value);
517 if (token == JSONParser::Token::ArrayEnd)
518 return JSONValue::SP(array_up.release());
519 JSONValue::SP value_sp = ParseJSONValue(value, token);
520 if (value_sp)
521 array_up->AppendObject(value_sp);
522 else
523 break;
525 token = GetToken(value);
526 if (token == JSONParser::Token::Comma) {
527 continue;
528 } else if (token == JSONParser::Token::ArrayEnd) {
529 return JSONValue::SP(array_up.release());
530 } else {
531 break;
534 return JSONValue::SP();
537 JSONValue::SP JSONParser::ParseJSONValue() {
538 std::string value;
539 const JSONParser::Token token = GetToken(value);
540 return ParseJSONValue(value, token);
543 JSONValue::SP JSONParser::ParseJSONValue(const std::string &value,
544 const Token &token) {
545 switch (token) {
546 case JSONParser::Token::ObjectStart:
547 return ParseJSONObject();
549 case JSONParser::Token::ArrayStart:
550 return ParseJSONArray();
552 case JSONParser::Token::Integer: {
553 if (value.front() == '-') {
554 bool success = false;
555 int64_t sval = StringConvert::ToSInt64(value.c_str(), 0, 0, &success);
556 if (success)
557 return JSONValue::SP(new JSONNumber(sval));
558 } else {
559 bool success = false;
560 uint64_t uval = StringConvert::ToUInt64(value.c_str(), 0, 0, &success);
561 if (success)
562 return JSONValue::SP(new JSONNumber(uval));
564 } break;
566 case JSONParser::Token::Float: {
567 bool success = false;
568 double val = StringConvert::ToDouble(value.c_str(), 0.0, &success);
569 if (success)
570 return JSONValue::SP(new JSONNumber(val));
571 } break;
573 case JSONParser::Token::String:
574 return JSONValue::SP(new JSONString(value));
576 case JSONParser::Token::True:
577 return JSONValue::SP(new JSONTrue());
579 case JSONParser::Token::False:
580 return JSONValue::SP(new JSONFalse());
582 case JSONParser::Token::Null:
583 return JSONValue::SP(new JSONNull());
585 default:
586 break;
588 return JSONValue::SP();