json_parser.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. //
  2. // json_parser.cpp
  3. // json
  4. //
  5. // Created by Sam Jaffe on 4/24/16.
  6. //
  7. #include "json.hpp"
  8. namespace json { namespace {
  9. char const * get_numeric_token_end(char const * start);
  10. void parse_numeric(value& json, char const*& data);
  11. void parse_object(value& json, char const*& data);
  12. void parse_array(value& json, char const*& data);
  13. void parse_one_token(value& json, char const*& data);
  14. void parse_one_token(value& json, char const*& data) {
  15. const char ch = helper::get_next_element(data);
  16. if (ch == '{') {
  17. parse_object(json, ++data);
  18. } else if (ch == '[') {
  19. parse_array(json, ++data);
  20. } else if (ch == '"') {
  21. helper::parse_string(json, ++data);
  22. } else if (!strncmp(data, "true", 4)) {
  23. json = true;
  24. } else if (!strncmp(data, "false", 5)) {
  25. json = false;
  26. } else {
  27. parse_numeric(json, data);
  28. }
  29. }
  30. char const * get_numeric_token_end(char const * start) {
  31. while (strchr(",]}", *start) == NULL &&
  32. !isspace(*start)) {
  33. ++start;
  34. }
  35. return start;
  36. }
  37. void parse_numeric(value & json, char const * & data) {
  38. char const * start = data;
  39. char const * const end = get_numeric_token_end(start);
  40. if (end == start) {
  41. throw malformed_json_exception("Expected any token, got nothing");
  42. }
  43. bool const negative = *start == '-';
  44. if (negative) ++start;
  45. uint_jt const threshold = (UINT_JT_MAX / 10);
  46. uint_jt val = 0;
  47. for (; start != end; ++start) {
  48. if (!isdigit(*start)) {
  49. helper::parse_double(json, start);
  50. return;
  51. }
  52. int_jt digit = static_cast<int_jt>(*start - '\0');
  53. if (val >= threshold) {
  54. if (val > threshold || (start + 1) < end || digit > INT_JT_MAX_LAST_DIGIT) {
  55. helper::parse_double(json, start);
  56. return;
  57. }
  58. }
  59. val = (10 * val) + digit;
  60. }
  61. if (negative && val == INT_JT_OVER) {
  62. json = INT_JT_MIN;
  63. } else if (negative) {
  64. json = -int_jt(val);
  65. } else if (val <= uint_jt(INT_JT_MAX)) {
  66. json = int_jt(val);
  67. } else {
  68. json = val;
  69. }
  70. }
  71. void parse_object(value& json, char const*& data) {
  72. std::string key;
  73. while (*data && *data != '}') {
  74. helper::parse_string(key, data);
  75. if (helper::get_next_element(data) != ':') {
  76. throw malformed_json_exception(std::string("Expected key:value pair delimited by ':', got '") + *data + "' instead");
  77. }
  78. parse_one_token(json[key], ++data);
  79. helper::advance_to_boundary('}', data);
  80. }
  81. if (*data) ++data;
  82. else throw malformed_json_exception("Reached end of parse string without finding object end");
  83. }
  84. void parse_array(value& json, char const*& data) {
  85. size_t current_idx = 0;
  86. while (*data && *data != ']') {
  87. parse_one_token(json[current_idx++], data);
  88. helper::advance_to_boundary(']', data);
  89. }
  90. if (*data) ++data;
  91. else throw malformed_json_exception("Reached end of parse string without finding array end");
  92. }
  93. } }
  94. namespace json {
  95. namespace parser {
  96. void parse(value& json, char const* data) {
  97. parse_one_token(json, data);
  98. if (*data) throw malformed_json_exception("Expected a single json token in top-level parse");
  99. }
  100. }
  101. }
  102. void json::value::parse(char const* data) {
  103. parser::parse(*this, data);
  104. }
  105. void json::value::parse(std::string const& str) {
  106. parser::parse(*this, str);
  107. }
  108. void json::value::parse(std::istream & in) {
  109. parser::parse(*this, in);
  110. }