JsonParser.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/CharacterTypes.h>
  7. #include <AK/JsonArray.h>
  8. #include <AK/JsonObject.h>
  9. #include <AK/JsonParser.h>
  10. namespace AK {
  11. constexpr bool is_space(int ch)
  12. {
  13. return ch == '\t' || ch == '\n' || ch == '\r' || ch == ' ';
  14. }
  15. ErrorOr<String> JsonParser::consume_and_unescape_string()
  16. {
  17. if (!consume_specific('"'))
  18. return Error::from_string_literal("JsonParser: Expected '\"'"sv);
  19. StringBuilder final_sb;
  20. for (;;) {
  21. size_t peek_index = m_index;
  22. char ch = 0;
  23. for (;;) {
  24. if (peek_index == m_input.length())
  25. break;
  26. ch = m_input[peek_index];
  27. if (ch == '"' || ch == '\\')
  28. break;
  29. if (is_ascii_c0_control(ch))
  30. return Error::from_string_literal("JsonParser: Error while parsing string"sv);
  31. ++peek_index;
  32. }
  33. while (peek_index != m_index) {
  34. final_sb.append(m_input[m_index]);
  35. m_index++;
  36. }
  37. if (m_index == m_input.length())
  38. break;
  39. if (ch == '"')
  40. break;
  41. if (ch != '\\') {
  42. final_sb.append(consume());
  43. continue;
  44. }
  45. ignore();
  46. if (next_is('"')) {
  47. ignore();
  48. final_sb.append('"');
  49. continue;
  50. }
  51. if (next_is('\\')) {
  52. ignore();
  53. final_sb.append('\\');
  54. continue;
  55. }
  56. if (next_is('/')) {
  57. ignore();
  58. final_sb.append('/');
  59. continue;
  60. }
  61. if (next_is('n')) {
  62. ignore();
  63. final_sb.append('\n');
  64. continue;
  65. }
  66. if (next_is('r')) {
  67. ignore();
  68. final_sb.append('\r');
  69. continue;
  70. }
  71. if (next_is('t')) {
  72. ignore();
  73. final_sb.append('\t');
  74. continue;
  75. }
  76. if (next_is('b')) {
  77. ignore();
  78. final_sb.append('\b');
  79. continue;
  80. }
  81. if (next_is('f')) {
  82. ignore();
  83. final_sb.append('\f');
  84. continue;
  85. }
  86. if (next_is('u')) {
  87. ignore();
  88. if (tell_remaining() < 4)
  89. return Error::from_string_literal("JsonParser: EOF while parsing Unicode escape"sv);
  90. auto code_point = AK::StringUtils::convert_to_uint_from_hex(consume(4));
  91. if (code_point.has_value()) {
  92. final_sb.append_code_point(code_point.value());
  93. continue;
  94. }
  95. return Error::from_string_literal("JsonParser: Error while parsing Unicode escape"sv);
  96. }
  97. return Error::from_string_literal("JsonParser: Error while parsing string"sv);
  98. }
  99. if (!consume_specific('"'))
  100. return Error::from_string_literal("JsonParser: Expected '\"'"sv);
  101. return final_sb.to_string();
  102. }
  103. ErrorOr<JsonValue> JsonParser::parse_object()
  104. {
  105. JsonObject object;
  106. if (!consume_specific('{'))
  107. return Error::from_string_literal("JsonParser: Expected '{'"sv);
  108. for (;;) {
  109. ignore_while(is_space);
  110. if (peek() == '}')
  111. break;
  112. ignore_while(is_space);
  113. auto name = TRY(consume_and_unescape_string());
  114. if (name.is_null())
  115. return Error::from_string_literal("JsonParser: Expected object property name"sv);
  116. ignore_while(is_space);
  117. if (!consume_specific(':'))
  118. return Error::from_string_literal("JsonParser: Expected ':'"sv);
  119. ignore_while(is_space);
  120. auto value = TRY(parse_helper());
  121. object.set(name, move(value));
  122. ignore_while(is_space);
  123. if (peek() == '}')
  124. break;
  125. if (!consume_specific(','))
  126. return Error::from_string_literal("JsonParser: Expected ','"sv);
  127. ignore_while(is_space);
  128. if (peek() == '}')
  129. return Error::from_string_literal("JsonParser: Unexpected '}'"sv);
  130. }
  131. if (!consume_specific('}'))
  132. return Error::from_string_literal("JsonParser: Expected '}'"sv);
  133. return JsonValue { move(object) };
  134. }
  135. ErrorOr<JsonValue> JsonParser::parse_array()
  136. {
  137. JsonArray array;
  138. if (!consume_specific('['))
  139. return Error::from_string_literal("JsonParser: Expected '['"sv);
  140. for (;;) {
  141. ignore_while(is_space);
  142. if (peek() == ']')
  143. break;
  144. auto element = TRY(parse_helper());
  145. array.append(move(element));
  146. ignore_while(is_space);
  147. if (peek() == ']')
  148. break;
  149. if (!consume_specific(','))
  150. return Error::from_string_literal("JsonParser: Expected ','"sv);
  151. ignore_while(is_space);
  152. if (peek() == ']')
  153. return Error::from_string_literal("JsonParser: Unexpected ']'"sv);
  154. }
  155. ignore_while(is_space);
  156. if (!consume_specific(']'))
  157. return Error::from_string_literal("JsonParser: Expected ']'"sv);
  158. return JsonValue { move(array) };
  159. }
  160. ErrorOr<JsonValue> JsonParser::parse_string()
  161. {
  162. auto string = TRY(consume_and_unescape_string());
  163. return JsonValue(move(string));
  164. }
  165. ErrorOr<JsonValue> JsonParser::parse_number()
  166. {
  167. JsonValue value;
  168. Vector<char, 128> number_buffer;
  169. Vector<char, 128> fraction_buffer;
  170. bool is_double = false;
  171. for (;;) {
  172. char ch = peek();
  173. if (ch == '.') {
  174. if (is_double)
  175. return Error::from_string_literal("JsonParser: Multiple '.' in number"sv);
  176. is_double = true;
  177. ++m_index;
  178. continue;
  179. }
  180. if (ch == '-' || (ch >= '0' && ch <= '9')) {
  181. if (is_double) {
  182. if (ch == '-')
  183. return Error::from_string_literal("JsonParser: Error while parsing number"sv);
  184. fraction_buffer.append(ch);
  185. } else {
  186. if (number_buffer.size() > 0) {
  187. if (number_buffer.at(0) == '0')
  188. return Error::from_string_literal("JsonParser: Error while parsing number"sv);
  189. }
  190. if (number_buffer.size() > 1) {
  191. if (number_buffer.at(0) == '-' && number_buffer.at(1) == '0')
  192. return Error::from_string_literal("JsonParser: Error while parsing number"sv);
  193. }
  194. number_buffer.append(ch);
  195. }
  196. ++m_index;
  197. continue;
  198. }
  199. break;
  200. }
  201. StringView number_string(number_buffer.data(), number_buffer.size());
  202. #ifndef KERNEL
  203. if (is_double) {
  204. // FIXME: This logic looks shaky.
  205. int whole = 0;
  206. auto to_signed_result = number_string.to_uint();
  207. if (to_signed_result.has_value()) {
  208. whole = to_signed_result.value();
  209. } else {
  210. auto number = number_string.to_int();
  211. if (!number.has_value())
  212. return Error::from_string_literal("JsonParser: Error while parsing number"sv);
  213. whole = number.value();
  214. }
  215. StringView fraction_string(fraction_buffer.data(), fraction_buffer.size());
  216. auto fraction_string_uint = fraction_string.to_uint();
  217. if (!fraction_string_uint.has_value())
  218. return Error::from_string_literal("JsonParser: Error while parsing number"sv);
  219. int fraction = fraction_string_uint.value();
  220. fraction *= (whole < 0) ? -1 : 1;
  221. auto divider = 1;
  222. for (size_t i = 0; i < fraction_buffer.size(); ++i) {
  223. divider *= 10;
  224. }
  225. value = JsonValue((double)whole + ((double)fraction / divider));
  226. } else {
  227. #endif
  228. auto to_unsigned_result = number_string.to_uint<u64>();
  229. if (to_unsigned_result.has_value()) {
  230. auto number = *to_unsigned_result;
  231. if (number <= NumericLimits<u32>::max())
  232. value = JsonValue((u32)number);
  233. else
  234. value = JsonValue(number);
  235. } else {
  236. auto number = number_string.to_int<i64>();
  237. if (!number.has_value())
  238. return Error::from_string_literal("JsonParser: Error while parsing number"sv);
  239. if (number.value() <= NumericLimits<i32>::max()) {
  240. value = JsonValue((i32)number.value());
  241. } else {
  242. value = JsonValue(number.value());
  243. }
  244. }
  245. #ifndef KERNEL
  246. }
  247. #endif
  248. return value;
  249. }
  250. ErrorOr<JsonValue> JsonParser::parse_true()
  251. {
  252. if (!consume_specific("true"))
  253. return Error::from_string_literal("JsonParser: Expected 'true'"sv);
  254. return JsonValue(true);
  255. }
  256. ErrorOr<JsonValue> JsonParser::parse_false()
  257. {
  258. if (!consume_specific("false"))
  259. return Error::from_string_literal("JsonParser: Expected 'false'"sv);
  260. return JsonValue(false);
  261. }
  262. ErrorOr<JsonValue> JsonParser::parse_null()
  263. {
  264. if (!consume_specific("null"))
  265. return Error::from_string_literal("JsonParser: Expected 'null'"sv);
  266. return JsonValue(JsonValue::Type::Null);
  267. }
  268. ErrorOr<JsonValue> JsonParser::parse_helper()
  269. {
  270. ignore_while(is_space);
  271. auto type_hint = peek();
  272. switch (type_hint) {
  273. case '{':
  274. return parse_object();
  275. case '[':
  276. return parse_array();
  277. case '"':
  278. return parse_string();
  279. case '-':
  280. case '0':
  281. case '1':
  282. case '2':
  283. case '3':
  284. case '4':
  285. case '5':
  286. case '6':
  287. case '7':
  288. case '8':
  289. case '9':
  290. return parse_number();
  291. case 'f':
  292. return parse_false();
  293. case 't':
  294. return parse_true();
  295. case 'n':
  296. return parse_null();
  297. }
  298. return Error::from_string_literal("JsonParser: Unexpected character"sv);
  299. }
  300. ErrorOr<JsonValue> JsonParser::parse()
  301. {
  302. auto result = TRY(parse_helper());
  303. ignore_while(is_space);
  304. if (!is_eof())
  305. return Error::from_string_literal("JsonParser: Didn't consume all input"sv);
  306. return result;
  307. }
  308. }