json_common.hpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. //
  2. // json_common.h
  3. // json
  4. //
  5. // Created by Sam Jaffe on 4/22/16.
  6. //
  7. #pragma once
  8. #include <cstdint>
  9. #include <cstdlib>
  10. #include <stdexcept>
  11. #include <string>
  12. namespace json {
  13. using string_jt = std::string;
  14. using double_jt = double;
  15. using int_jt = int32_t;
  16. using uint_jt = uint32_t;
  17. using bool_jt = bool;
  18. class value;
  19. class malformed_json_exception :
  20. public std::domain_error {
  21. using std::domain_error::domain_error;
  22. };
  23. namespace {
  24. const constexpr json::int_jt INT_JT_MAX_LAST_DIGIT = (0x7FFFFFFF % 10);
  25. const constexpr json::int_jt INT_JT_MAX = json::uint_jt(-1) - 1;
  26. const constexpr json::int_jt INT_JT_MIN = json::int_jt(~(json::uint_jt(-1) / 2));
  27. const constexpr json::uint_jt INT_JT_OVER = json::uint_jt(INT_JT_MAX) + 1;
  28. const constexpr json::uint_jt UINT_JT_MAX = json::uint_jt(0) - 1;
  29. // const constexpr json::uint_jt UINT_JT_MIN = 0;
  30. }
  31. }
  32. namespace json {
  33. namespace helper {
  34. const char get_next_element(char const*& data);
  35. enum numeric_state {
  36. DOUBLE, INTEGER
  37. };
  38. struct numeric_token_info {
  39. numeric_token_info(char const * start);
  40. numeric_state parse_numeric();
  41. uint_jt val;
  42. char const * it;
  43. char const * end;
  44. bool is_double;
  45. bool is_negative;
  46. };
  47. numeric_token_info get_numeric_token_info(char const * it);
  48. /**
  49. * @throws json::malformed_json_exception
  50. */
  51. void advance_to_boundary(char const endtok, char const *& data);
  52. /**
  53. * @throws json::malformed_json_exception
  54. */
  55. std::string parse_string(char const * & data);
  56. template <typename T>
  57. void parse_string(T& json, char const * & data) {
  58. json = parse_string(data);
  59. }
  60. template <typename T>
  61. void parse_double(T& json, char const * & data) {
  62. json = atof(data);
  63. while (isdigit(*data)) { ++data; }
  64. if (*data == '.' || *data == 'e') { ++data; }
  65. while (isdigit(*data)) { ++data; }
  66. }
  67. // template <typename T>
  68. // void parse_integer(T& json, char const * & data) {
  69. // json = atoi(data);
  70. // while (isdigit(*data)) { ++data; }
  71. // }
  72. template <typename J>
  73. void parse_numeric(J & json, char const * & data) {
  74. numeric_token_info info = data;
  75. if ( info.is_double ) {
  76. helper::parse_double(json, data);
  77. } else if ( info.parse_numeric() == DOUBLE ) {
  78. helper::parse_double(json, data);
  79. } else {
  80. uint_jt const val = info.val;
  81. if (info.is_negative) {
  82. if (val == INT_JT_OVER) {
  83. json = INT_JT_MIN;
  84. } else {
  85. json = -int_jt(val);
  86. }
  87. } else if (val <= uint_jt(INT_JT_MAX)) {
  88. json = int_jt(val);
  89. } else {
  90. json = val;
  91. }
  92. data = info.it;
  93. }
  94. }
  95. }
  96. }