json_common.cpp 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. //
  2. // json_binder.cpp
  3. // json
  4. //
  5. // Created by Sam Jaffe on 4/23/16.
  6. //
  7. #include "json_common.hpp"
  8. namespace json {
  9. namespace helper {
  10. namespace {
  11. std::string get_no_end_error(char expected, char found) {
  12. char str[64] = { '\0' };
  13. snprintf(str, sizeof(str),
  14. "Expected delimeter: ',' or '%c', got '%c' instead",
  15. expected, found);
  16. return str;
  17. }
  18. }
  19. numeric_token_info::numeric_token_info(char const * start)
  20. : val(0)
  21. , it(start)
  22. , end(start)
  23. , is_double(false)
  24. , is_negative(*start == '-') {
  25. if ( is_negative ) { ++it; ++end; }
  26. for (char c = *end;
  27. strchr(",]}", c) == NULL && !isspace(c);
  28. c = *++end) {
  29. is_double |= !isdigit(*end);
  30. }
  31. if (end == it) {
  32. throw unterminated_json_exception("Expected any token, got nothing");
  33. }
  34. }
  35. numeric_state numeric_token_info::parse_numeric() {
  36. static uint_jt const threshold = (UINT_JT_MAX / 10);
  37. val = 0;
  38. for (char c = *it; it != end; c = *++it) {
  39. int_jt digit = static_cast<int_jt>(c - '0');
  40. if (val > threshold ||
  41. ( val == threshold && ((it + 1) < end ||
  42. digit > INT_JT_MAX_LAST_DIGIT))) {
  43. return DOUBLE;
  44. }
  45. val = (10 * val) + digit;
  46. }
  47. return INTEGER;
  48. }
  49. const char get_next_element(char const*& data) {
  50. while (isspace(*data)) ++data;
  51. return *data;
  52. }
  53. void advance_to_boundary(char const endtok, char const*& data) {
  54. char const next = get_next_element(data);
  55. if (next == ',') {
  56. ++data;
  57. } else if (next != endtok) {
  58. throw json::unterminated_json_exception(get_no_end_error(endtok, *data));
  59. }
  60. }
  61. int reverse_count(char const * data, char val) {
  62. int i = 0;
  63. while (*data-- == val) { ++i; }
  64. return i;
  65. }
  66. std::string replace_all(std::string && str, std::string const & from, std::string const & to) {
  67. std::string::size_type start_pos = 0;
  68. while((start_pos = str.find(from, start_pos)) != std::string::npos) {
  69. str.replace(start_pos, from.length(), to);
  70. start_pos += to.length(); // ...
  71. }
  72. return std::move(str);
  73. }
  74. std::string parse_string(char const * & data) {
  75. char const* start = data;
  76. while (*++data) {
  77. if (*data == '"' && (reverse_count(data-1, '\\') % 2) == 0) {
  78. return replace_all(std::string(start+1, data++), "\\\"", "\"");
  79. }
  80. }
  81. throw json::unterminated_json_exception("Could not locate end of string");
  82. }
  83. }
  84. }