1 #ifndef ZSERIO_JSON_DECODER_H_INC
2 #define ZSERIO_JSON_DECODER_H_INC
24 template <
typename ALLOC = std::allocator<u
int8_t>>
55 DecoderResult(
size_t numRead, T&& decodedValue,
const ALLOC& allocator) :
57 value(std::forward<T>(decodedValue), allocator),
70 DecoderResult(
size_t numRead, T&& decodedValue,
bool overflow,
const ALLOC& allocator) :
72 value(createValue(std::forward<T>(decodedValue), overflow, allocator)),
83 AnyHolder<ALLOC> createValue(T&& decodedValue,
bool overflow,
const ALLOC& allocator)
123 return decodeLiteral(input,
"null"_sv,
nullptr);
125 return decodeLiteral(input,
"true"_sv,
true);
127 return decodeLiteral(input,
"false"_sv,
false);
129 return decodeLiteral(input,
"NaN"_sv,
static_cast<double>(NAN));
131 return decodeLiteral(input,
"Infinity"_sv,
static_cast<double>(INFINITY));
133 return decodeString(input);
135 if (input.
size() > 1 && input[1] ==
'I')
137 return decodeLiteral(input,
"-Infinity"_sv, -
static_cast<double>(INFINITY));
139 return decodeNumber(input);
141 return decodeNumber(input);
146 template <
typename T>
149 static bool decodeUnicodeEscape(
151 static int32_t decodeHex(
char character);
152 size_t checkNumber(
StringView input,
bool& isDouble,
bool& isSigned);
155 DecoderResult decodeUnsigned(
StringView input);
156 DecoderResult decodeDouble(
StringView input,
size_t numChars);
159 template <
typename ALLOC>
160 template <
typename T>
161 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeLiteral(
166 while (inputIt != input.end() && literalIt != literal.end())
168 if (*inputIt++ != *literalIt++)
171 return DecoderResult(
static_cast<size_t>(inputIt - input.begin()), get_allocator());
175 if (literalIt != literal.end())
178 return DecoderResult(input.size(), get_allocator());
182 return DecoderResult(literal.size(), std::forward<T>(value), get_allocator());
185 template <
typename ALLOC>
186 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeString(
StringView input)
189 string<ALLOC> value(get_allocator());
191 while (inputIt != input.end())
193 if (*inputIt ==
'\\')
196 if (inputIt == input.end())
199 return DecoderResult(
static_cast<size_t>(inputIt - input.begin()), get_allocator());
202 char nextChar = *inputIt;
207 value.push_back(nextChar);
211 value.push_back(
'\b');
215 value.push_back(
'\f');
219 value.push_back(
'\n');
223 value.push_back(
'\r');
227 value.push_back(
'\t');
233 if (!decodeUnicodeEscape(input, inputIt, value))
236 return DecoderResult(
static_cast<size_t>(inputIt - input.begin()), get_allocator());
243 return DecoderResult(
static_cast<size_t>(inputIt - input.begin()), get_allocator());
246 else if (*inputIt ==
'"')
250 return DecoderResult(
251 static_cast<size_t>(inputIt - input.begin()), std::move(value), get_allocator());
255 value.push_back(*inputIt++);
260 return DecoderResult(input.size(), get_allocator());
263 template <
typename ALLOC>
264 bool BasicJsonDecoder<ALLOC>::decodeUnicodeEscape(
269 if (inputIt == input.end() || *inputIt++ !=
'0')
273 if (inputIt == input.end() || *inputIt++ !=
'0')
278 if (inputIt == input.end())
283 const int32_t hex1 = decodeHex(*inputIt++);
289 if (inputIt == input.end())
294 const int32_t hex2 = decodeHex(*inputIt++);
300 const uint32_t characterInt = (
static_cast<uint32_t
>(hex1) << 4U) |
static_cast<uint32_t
>(hex2);
301 using char_traits = std::char_traits<char>;
302 const char character = char_traits::to_char_type(
static_cast<char_traits::int_type
>(characterInt));
303 value.push_back(character);
308 template <
typename ALLOC>
309 int32_t BasicJsonDecoder<ALLOC>::decodeHex(
char character)
311 if (character >=
'0' && character <=
'9')
313 return static_cast<int32_t
>(character -
'0');
315 else if (character >=
'a' && character <=
'f')
317 return static_cast<int32_t
>(character -
'a' + 10);
319 else if (character >=
'A' && character <=
'F')
321 return static_cast<int32_t
>(character -
'A' + 10);
327 template <
typename ALLOC>
328 size_t BasicJsonDecoder<ALLOC>::checkNumber(
StringView input,
bool& isDouble,
bool& isSigned)
331 bool acceptExpSign =
false;
332 bool isScientificDouble =
false;
345 while (inputIt != input.end())
349 acceptExpSign =
false;
350 if (*inputIt ==
'+' || *inputIt ==
'-')
357 if (*inputIt >=
'0' && *inputIt <=
'9')
363 if ((*inputIt ==
'e' || *inputIt ==
'E') && !isScientificDouble)
366 isScientificDouble =
true;
367 acceptExpSign =
true;
372 if (*inputIt ==
'.' && !isDouble)
382 const size_t numberLen =
static_cast<size_t>(inputIt - input.begin());
383 if (isSigned && numberLen == 1)
391 template <
typename ALLOC>
392 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeNumber(
StringView input)
394 bool isDouble =
false;
395 bool isSigned =
false;
396 const size_t numChars = checkNumber(input, isDouble, isSigned);
399 return DecoderResult(1, get_allocator());
406 return decodeDouble(input, numChars);
410 return decodeSigned(input);
414 return decodeUnsigned(input);
418 template <
typename ALLOC>
419 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeSigned(
StringView input)
421 char* pEnd =
nullptr;
423 const int64_t value = std::strtoll(input.begin(), &pEnd, 10);
425 const bool overflow = (errno == ERANGE);
427 return DecoderResult(
static_cast<size_t>(pEnd - input.begin()), value, overflow, get_allocator());
430 template <
typename ALLOC>
431 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeUnsigned(
StringView input)
433 char* pEnd =
nullptr;
435 const uint64_t value = std::strtoull(input.begin(), &pEnd, 10);
437 const bool overflow = (errno == ERANGE);
439 return DecoderResult(
static_cast<size_t>(pEnd - input.begin()), value, overflow, get_allocator());
442 template <
typename ALLOC>
443 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeDouble(
446 char* pEnd =
nullptr;
447 const double value = std::strtod(input.begin(), &pEnd);
448 if (
static_cast<size_t>(pEnd - input.begin()) != numChars)
450 return DecoderResult(numChars, get_allocator());
453 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)