| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- //
- // json_common.h
- // json
- //
- // Created by Sam Jaffe on 4/22/16.
- //
- #pragma once
- #include <cstdint>
- #include <cstdlib>
- #include <stdexcept>
- #include <string>
- namespace json {
- using string_jt = std::string;
- using double_jt = double;
- using int_jt = int32_t;
- using uint_jt = uint32_t;
- using bool_jt = bool;
-
- class value;
-
- class malformed_json_exception :
- public std::domain_error {
- using std::domain_error::domain_error;
- };
-
- namespace {
- const constexpr json::int_jt INT_JT_MAX_LAST_DIGIT = (0x7FFFFFFF % 10);
- const constexpr json::int_jt INT_JT_MAX = json::uint_jt(-1) - 1;
- const constexpr json::int_jt INT_JT_MIN = json::int_jt(~(json::uint_jt(-1) / 2));
- const constexpr json::uint_jt INT_JT_OVER = json::uint_jt(INT_JT_MAX) + 1;
- const constexpr json::uint_jt UINT_JT_MAX = json::uint_jt(0) - 1;
- // const constexpr json::uint_jt UINT_JT_MIN = 0;
- }
- }
- namespace json {
- namespace helper {
- const char get_next_element(char const*& data);
- char const * get_numeric_token_end(char const * start);
-
- /**
- * @throws json::malformed_json_exception
- */
- void advance_to_boundary(char const endtok, char const *& data);
-
- /**
- * @throws json::malformed_json_exception
- */
- std::string parse_string(char const * & data);
-
- template <typename T>
- void parse_string(T& json, char const * & data) {
- json = parse_string(data);
- }
-
- template <typename T>
- void parse_double(T& json, char const * & data) {
- json = atof(data);
- while (isdigit(*data)) { ++data; }
- if (*data == '.' || *data == 'e') { ++data; }
- while (isdigit(*data)) { ++data; }
- }
-
- // template <typename T>
- // void parse_integer(T& json, char const * & data) {
- // json = atoi(data);
- // while (isdigit(*data)) { ++data; }
- // }
-
- template <typename J>
- void parse_numeric(J & json, char const * & data) {
- char const * start = data;
- char const * const end = get_numeric_token_end(start);
-
- if (end == start) {
- throw malformed_json_exception("Expected any token, got nothing");
- }
-
- bool const negative = *start == '-';
- if (negative) ++start;
-
- uint_jt const threshold = (UINT_JT_MAX / 10);
- uint_jt val = 0;
- for (; start != end; ++start) {
- if (!isdigit(*start)) {
- helper::parse_double(json, data);
- return;
- }
- int_jt digit = static_cast<int_jt>(*start - '0');
- if (val >= threshold) {
- if (val > threshold || (start + 1) < end || digit > INT_JT_MAX_LAST_DIGIT) {
- helper::parse_double(json, data);
- return;
- }
- }
- val = (10 * val) + digit;
- }
- if (negative && val == INT_JT_OVER) {
- json = INT_JT_MIN;
- } else if (negative) {
- json = -int_jt(val);
- } else if (val <= uint_jt(INT_JT_MAX)) {
- json = int_jt(val);
- } else {
- json = val;
- }
- data = start;
- }
- }
- }
|