JsonParser.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. #include <AK/JsonArray.h>
  2. #include <AK/JsonObject.h>
  3. #include <AK/JsonParser.h>
  4. #include <AK/StringBuilder.h>
  5. namespace AK {
  6. static inline bool is_whitespace(char ch)
  7. {
  8. return ch == ' ' || ch == '\n' || ch == '\t' || ch == '\v' || ch == '\r';
  9. }
  10. char JsonParser::peek() const
  11. {
  12. if (m_index < m_input.length())
  13. return m_input[m_index];
  14. return '\0';
  15. }
  16. char JsonParser::consume()
  17. {
  18. if (m_index < m_input.length())
  19. return m_input[m_index++];
  20. return '\0';
  21. }
  22. template<typename C>
  23. void JsonParser::consume_while(C condition)
  24. {
  25. while (condition(peek()))
  26. consume();
  27. }
  28. template<typename C>
  29. String JsonParser::extract_while(C condition)
  30. {
  31. StringBuilder builder;
  32. while (condition(peek()))
  33. builder.append(consume());
  34. return builder.to_string();
  35. };
  36. void JsonParser::consume_whitespace()
  37. {
  38. consume_while([](char ch) { return is_whitespace(ch); });
  39. }
  40. void JsonParser::consume_specific(char expected_ch)
  41. {
  42. char consumed_ch = consume();
  43. ASSERT(consumed_ch == expected_ch);
  44. }
  45. String JsonParser::consume_quoted_string()
  46. {
  47. consume_specific('"');
  48. StringBuilder builder;
  49. for (;;) {
  50. char ch = peek();
  51. if (ch == '"')
  52. break;
  53. if (ch != '\\') {
  54. builder.append(consume());
  55. continue;
  56. }
  57. consume();
  58. char escaped_ch = consume();
  59. switch (escaped_ch) {
  60. case 'n':
  61. case 'r':
  62. builder.append('\n');
  63. break;
  64. case 't':
  65. builder.append('\t');
  66. break;
  67. case 'b':
  68. builder.append('\b');
  69. break;
  70. case 'f':
  71. builder.append('\f');
  72. break;
  73. case 'u':
  74. consume();
  75. consume();
  76. consume();
  77. consume();
  78. // FIXME: This is obviously not correct, but we don't have non-ASCII support so meh.
  79. builder.append("?");
  80. break;
  81. default:
  82. builder.append(escaped_ch);
  83. break;
  84. }
  85. }
  86. consume_specific('"');
  87. return builder.to_string();
  88. }
  89. JsonValue JsonParser::parse_object()
  90. {
  91. JsonObject object;
  92. consume_specific('{');
  93. for (;;) {
  94. consume_whitespace();
  95. if (peek() == '}')
  96. break;
  97. consume_whitespace();
  98. auto name = consume_quoted_string();
  99. consume_whitespace();
  100. consume_specific(':');
  101. consume_whitespace();
  102. auto value = parse();
  103. object.set(name, move(value));
  104. consume_whitespace();
  105. if (peek() == '}')
  106. break;
  107. consume_specific(',');
  108. }
  109. consume_specific('}');
  110. return object;
  111. }
  112. JsonValue JsonParser::parse_array()
  113. {
  114. JsonArray array;
  115. consume_specific('[');
  116. for (;;) {
  117. consume_whitespace();
  118. if (peek() == ']')
  119. break;
  120. array.append(parse());
  121. consume_whitespace();
  122. if (peek() == ']')
  123. break;
  124. consume_specific(',');
  125. }
  126. consume_whitespace();
  127. consume_specific(']');
  128. return array;
  129. }
  130. JsonValue JsonParser::parse_string()
  131. {
  132. return consume_quoted_string();
  133. }
  134. JsonValue JsonParser::parse_number()
  135. {
  136. auto number_string = extract_while([](char ch) { return ch == '-' || (ch >= '0' && ch <= '9'); });
  137. bool ok;
  138. auto value = JsonValue(number_string.to_uint(ok));
  139. if (!ok)
  140. value = JsonValue(number_string.to_int(ok));
  141. ASSERT(ok);
  142. return value;
  143. }
  144. void JsonParser::consume_string(const char* str)
  145. {
  146. for (size_t i = 0, length = strlen(str); i < length; ++i)
  147. consume_specific(str[i]);
  148. }
  149. JsonValue JsonParser::parse_true()
  150. {
  151. consume_string("true");
  152. return JsonValue(true);
  153. }
  154. JsonValue JsonParser::parse_false()
  155. {
  156. consume_string("false");
  157. return JsonValue(false);
  158. }
  159. JsonValue JsonParser::parse_null()
  160. {
  161. consume_string("null");
  162. return JsonValue(JsonValue::Type::Null);
  163. }
  164. JsonValue JsonParser::parse_undefined()
  165. {
  166. consume_string("undefined");
  167. return JsonValue(JsonValue::Type::Undefined);
  168. }
  169. JsonValue JsonParser::parse()
  170. {
  171. consume_whitespace();
  172. auto type_hint = peek();
  173. switch (type_hint) {
  174. case '{':
  175. return parse_object();
  176. case '[':
  177. return parse_array();
  178. case '"':
  179. return parse_string();
  180. case '-':
  181. case '0':
  182. case '1':
  183. case '2':
  184. case '3':
  185. case '4':
  186. case '5':
  187. case '6':
  188. case '7':
  189. case '8':
  190. case '9':
  191. return parse_number();
  192. case 'f':
  193. return parse_false();
  194. case 't':
  195. return parse_true();
  196. case 'n':
  197. return parse_null();
  198. case 'u':
  199. return parse_undefined();
  200. }
  201. return JsonValue();
  202. }
  203. }