1 #ifndef ZSERIO_JSON_DECODER_H_INC
2 #define ZSERIO_JSON_DECODER_H_INC
23 template <
typename ALLOC = std::allocator<u
int8_t>>
54 DecoderResult(
size_t numRead, T&& decodedValue,
const ALLOC& allocator) :
56 value(std::forward<T>(decodedValue), allocator),
69 DecoderResult(
size_t numRead, T&& decodedValue,
bool overflow,
const ALLOC& allocator) :
71 value(createValue(std::forward<T>(decodedValue), overflow, allocator)),
82 AnyHolder<ALLOC> createValue(T&& decodedValue,
bool overflow,
const ALLOC& allocator)
122 return decodeLiteral(input,
"null"_sv,
nullptr);
124 return decodeLiteral(input,
"true"_sv,
true);
126 return decodeLiteral(input,
"false"_sv,
false);
128 return decodeLiteral(input,
"NaN"_sv,
static_cast<double>(NAN));
130 return decodeLiteral(input,
"Infinity"_sv,
static_cast<double>(INFINITY));
132 return decodeString(input);
134 if (input.
size() > 1 && input[1] ==
'I')
136 return decodeLiteral(input,
"-Infinity"_sv, -
static_cast<double>(INFINITY));
138 return decodeNumber(input);
140 return decodeNumber(input);
145 template <
typename T>
148 static bool decodeUnicodeEscape(
150 static int32_t decodeHex(
char character);
151 size_t checkNumber(
StringView input,
bool& isDouble,
bool& isSigned);
154 DecoderResult decodeUnsigned(
StringView input);
155 DecoderResult decodeDouble(
StringView input,
size_t numChars);
158 template <
typename ALLOC>
159 template <
typename T>
160 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeLiteral(
165 while (inputIt != input.end() && literalIt != literal.end())
167 if (*inputIt++ != *literalIt++)
170 return DecoderResult(
static_cast<size_t>(inputIt - input.begin()), get_allocator());
174 if (literalIt != literal.end())
177 return DecoderResult(input.size(), get_allocator());
181 return DecoderResult(literal.size(), std::forward<T>(value), get_allocator());
184 template <
typename ALLOC>
185 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeString(
StringView input)
188 string<ALLOC> value(get_allocator());
190 while (inputIt != input.end())
192 if (*inputIt ==
'\\')
195 if (inputIt == input.end())
198 return DecoderResult(
static_cast<size_t>(inputIt - input.begin()), get_allocator());
201 char nextChar = *inputIt;
206 value.push_back(nextChar);
210 value.push_back(
'\b');
214 value.push_back(
'\f');
218 value.push_back(
'\n');
222 value.push_back(
'\r');
226 value.push_back(
'\t');
232 if (!decodeUnicodeEscape(input, inputIt, value))
235 return DecoderResult(
static_cast<size_t>(inputIt - input.begin()), get_allocator());
242 return DecoderResult(
static_cast<size_t>(inputIt - input.begin()), get_allocator());
245 else if (*inputIt ==
'"')
249 return DecoderResult(
250 static_cast<size_t>(inputIt - input.begin()), std::move(value), get_allocator());
254 value.push_back(*inputIt++);
259 return DecoderResult(input.size(), get_allocator());
262 template <
typename ALLOC>
263 bool BasicJsonDecoder<ALLOC>::decodeUnicodeEscape(
268 if (inputIt == input.end() || *inputIt++ !=
'0')
272 if (inputIt == input.end() || *inputIt++ !=
'0')
277 if (inputIt == input.end())
282 const int32_t hex1 = decodeHex(*inputIt++);
288 if (inputIt == input.end())
293 const int32_t hex2 = decodeHex(*inputIt++);
299 const uint32_t characterInt = (
static_cast<uint32_t
>(hex1) << 4U) |
static_cast<uint32_t
>(hex2);
300 using char_traits = std::char_traits<char>;
301 const char character = char_traits::to_char_type(
static_cast<char_traits::int_type
>(characterInt));
302 value.push_back(character);
307 template <
typename ALLOC>
308 int32_t BasicJsonDecoder<ALLOC>::decodeHex(
char character)
310 if (character >=
'0' && character <=
'9')
312 return static_cast<int32_t
>(character -
'0');
314 else if (character >=
'a' && character <=
'f')
316 return static_cast<int32_t
>(character -
'a' + 10);
318 else if (character >=
'A' && character <=
'F')
320 return static_cast<int32_t
>(character -
'A' + 10);
326 template <
typename ALLOC>
327 size_t BasicJsonDecoder<ALLOC>::checkNumber(
StringView input,
bool& isDouble,
bool& isSigned)
330 bool acceptExpSign =
false;
331 bool isScientificDouble =
false;
344 while (inputIt != input.end())
348 acceptExpSign =
false;
349 if (*inputIt ==
'+' || *inputIt ==
'-')
356 if (*inputIt >=
'0' && *inputIt <=
'9')
362 if ((*inputIt ==
'e' || *inputIt ==
'E') && !isScientificDouble)
365 isScientificDouble =
true;
366 acceptExpSign =
true;
371 if (*inputIt ==
'.' && !isDouble)
381 const size_t numberLen =
static_cast<size_t>(inputIt - input.begin());
382 if (isSigned && numberLen == 1)
390 template <
typename ALLOC>
391 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeNumber(
StringView input)
393 bool isDouble =
false;
394 bool isSigned =
false;
395 const size_t numChars = checkNumber(input, isDouble, isSigned);
398 return DecoderResult(1, get_allocator());
405 return decodeDouble(input, numChars);
409 return decodeSigned(input);
413 return decodeUnsigned(input);
417 template <
typename ALLOC>
418 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeSigned(
StringView input)
420 char* pEnd =
nullptr;
422 const int64_t value = std::strtoll(input.begin(), &pEnd, 10);
424 const bool overflow = (errno == ERANGE);
426 return DecoderResult(
static_cast<size_t>(pEnd - input.begin()), value, overflow, get_allocator());
429 template <
typename ALLOC>
430 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeUnsigned(
StringView input)
432 char* pEnd =
nullptr;
434 const uint64_t value = std::strtoull(input.begin(), &pEnd, 10);
436 const bool overflow = (errno == ERANGE);
438 return DecoderResult(
static_cast<size_t>(pEnd - input.begin()), value, overflow, get_allocator());
441 template <
typename ALLOC>
442 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeDouble(
445 char* pEnd =
nullptr;
446 const double value = std::strtod(input.begin(), &pEnd);
447 if (
static_cast<size_t>(pEnd - input.begin()) != numChars)
449 return DecoderResult(numChars, get_allocator());
452 return DecoderResult(numChars, value, get_allocator());
allocator_type get_allocator() const
BasicJsonDecoder(const ALLOC &allocator)
DecoderResult decodeValue(StringView input)
const_pointer const_iterator
constexpr size_type size() const noexcept
constexpr bool empty() const noexcept
BasicStringView< char, std::char_traits< char > > StringView
std::basic_string< char, std::char_traits< char >, RebindAlloc< ALLOC, char > > string
DecoderResult(size_t numRead, T &&decodedValue, bool overflow, const ALLOC &allocator)
DecoderResult(size_t numRead, const ALLOC &allocator)
DecoderResult(size_t numRead, T &&decodedValue, const ALLOC &allocator)