json.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. //
  2. // json.cpp
  3. // json
  4. //
  5. // Created by Sam Jaffe on 1/30/16.
  6. // Copyright © 2016 Sam Jaffe. All rights reserved.
  7. //
  8. #include "json.h"
  9. #include "json_parser.hpp"
  10. #include "json_binder.hpp"
  11. const json::value json::value::null_value{};
  12. namespace {
  13. void parse_object(json::value& json, char const*& data);
  14. void parse_array(json::value& json, char const*& data);
  15. void parse_one_token(json::value& json, char const*& data);
  16. void parse_one_token(json::value& json, char const*& data) {
  17. const char ch = json::helper::get_next_element(data);
  18. if (ch == '{') {
  19. parse_object(json, ++data);
  20. } else if (ch == '[') {
  21. parse_array(json, ++data);
  22. } else if (ch == '"') {
  23. json::helper::parse_string(json, ++data);
  24. } else if (isnumber(ch)) {
  25. json::helper::parse_numeric(json, data);
  26. } else if (!strncmp(data, "true", 4)) {
  27. json = true;
  28. } else if (!strncmp(data, "false", 5)) {
  29. json = false;
  30. } else {
  31. throw json::malformed_json_exception(std::string("Expected the start of a JSON element, found character '") + ch + "' instead");
  32. }
  33. }
  34. void parse_object(json::value& json, char const*& data) {
  35. std::string key;
  36. while (*data && *data != '}') {
  37. json::helper::parse_string(key, data);
  38. if (json::helper::get_next_element(data) != ':') {
  39. throw json::malformed_json_exception(std::string("Expected key:value pair delimited by ':', got '") + *data + "' instead");
  40. }
  41. parse_one_token(json[key], ++data);
  42. json::helper::advance_to_boundary<'}'>(data);
  43. }
  44. if (*data) ++data;
  45. else throw json::malformed_json_exception("Reached end of parse string without finding object end");
  46. }
  47. void parse_array(json::value& json, char const*& data) {
  48. size_t current_idx = 0;
  49. while (*data && *data != ']') {
  50. parse_one_token(json[current_idx++], data);
  51. json::helper::advance_to_boundary<']'>(data);
  52. }
  53. if (*data) ++data;
  54. else throw json::malformed_json_exception("Reached end of parse string without finding array end");
  55. }
  56. }
  57. namespace json {
  58. namespace parser {
  59. void parse(json::value& json, char const* data) {
  60. parse_one_token(json, data);
  61. if (*data) throw json::malformed_json_exception("Expected a single json token in top-level parse");
  62. }
  63. }
  64. }
  65. void json::value::parse(char const* data) { parser::parse(*this, data); }
  66. void json::value::parse(std::string const& str) { parser::parse(*this, str); }
  67. void json::value::parse(std::istream & in) { parser::parse(*this, in); }
  68. json::value& json::value::operator[](const size_t idx) {
  69. if (!is_array()) {
  70. data.set<array_jt>();
  71. }
  72. array_jt & val = data.get<array_jt>();
  73. if (val.size() <= idx) val.resize(idx+1);
  74. return val[idx];
  75. }
  76. json::value const& json::value::operator[](const size_t idx) const {
  77. if (!is_array()) return null_value;
  78. array_jt const& val = data.get<array_jt>();
  79. if (val.size() <= idx) return null_value;
  80. else return val[idx];
  81. }
  82. json::value& json::value::operator[](std::string const& key) {
  83. if (!is_object()) {
  84. data.set<object_jt>();
  85. }
  86. return data.get<object_jt>()[key];
  87. }
  88. json::value const& json::value::operator[](std::string const& key) const {
  89. if (!is_object()) return null_value;
  90. object_jt const& val = data.get<object_jt>();
  91. auto it = val.find(key);
  92. if (it != val.end()) {
  93. return it->second;
  94. } else {
  95. return null_value;
  96. }
  97. }
  98. json::value::string_jt const& json::value::as_string() const {
  99. return data.get<string_jt>();
  100. }
  101. json::value::double_jt json::value::as_double() const {
  102. if (data.is<double_jt>()) {
  103. return data.get<double_jt>();
  104. } else if (data.is<int_jt>()) {
  105. return static_cast<double_jt>(data.get<int_jt>());
  106. } else if (data.is<bool_jt>()) {
  107. return data.get<bool_jt>() ? 1.0 : 0.0;
  108. } else {
  109. return 0.0;
  110. }
  111. }
  112. json::value::int_jt json::value::as_int() const {
  113. if (data.is<double_jt>()) {
  114. return static_cast<int_jt>(data.get<double_jt>());
  115. } else if (data.is<int_jt>()) {
  116. return data.get<int_jt>();
  117. } else if (data.is<bool_jt>()) {
  118. return data.get<bool_jt>() ? 1 : 0;
  119. } else {
  120. return 0;
  121. }
  122. }
  123. json::value::bool_jt json::value::as_bool() const {
  124. if (data.is<double_jt>()) {
  125. return data.get<double_jt>() != 0;
  126. } else if (data.is<int_jt>()) {
  127. return data.get<int_jt>() != 0;
  128. } else if (data.is<bool_jt>()) {
  129. return data.get<bool_jt>();
  130. } else {
  131. return false;
  132. }
  133. }