1 #ifndef ZSERIO_JSON_DECODER_H_INC
2 #define ZSERIO_JSON_DECODER_H_INC
22 template <
typename ALLOC = std::allocator<u
int8_t>>
53 DecoderResult(
size_t numRead, T&& decodedValue,
const ALLOC& allocator) :
55 value(std::forward<T>(decodedValue), allocator),
68 DecoderResult(
size_t numRead, T&& decodedValue,
bool overflow,
const ALLOC& allocator) :
70 value(createValue(decodedValue, overflow, allocator)),
81 AnyHolder<ALLOC> createValue(T&& decodedValue,
bool overflow,
const ALLOC& allocator)
119 return decodeLiteral(input,
"null"_sv,
nullptr);
121 return decodeLiteral(input,
"true"_sv,
true);
123 return decodeLiteral(input,
"false"_sv,
false);
125 return decodeLiteral(input,
"NaN"_sv,
static_cast<double>(NAN));
127 return decodeLiteral(input,
"Infinity"_sv,
static_cast<double>(INFINITY));
129 return decodeString(input);
131 if (input.
size() > 1 && input[1] ==
'I')
132 return decodeLiteral(input,
"-Infinity"_sv, -
static_cast<double>(INFINITY));
133 return decodeNumber(input);
135 return decodeNumber(input);
140 template <
typename T>
143 static bool decodeUnicodeEscape(
145 static char decodeHex(
char character);
146 size_t checkNumber(
StringView input,
bool& isDouble,
bool& isSigned);
149 DecoderResult decodeUnsigned(
StringView input);
150 DecoderResult decodeDouble(
StringView input,
size_t numChars);
153 template <
typename ALLOC>
154 template <
typename T>
155 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeLiteral(
160 while (inputIt != input.end() && literalIt != literal.end())
162 if (*inputIt++ != *literalIt++)
165 return DecoderResult(
static_cast<size_t>(inputIt - input.begin()), get_allocator());
169 if (literalIt != literal.end())
172 return DecoderResult(input.size(), get_allocator());
176 return DecoderResult(literal.size(), std::forward<T>(value), get_allocator());
179 template <
typename ALLOC>
180 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeString(
StringView input)
183 string<ALLOC> value(get_allocator());
185 while (inputIt != input.end())
187 if (*inputIt ==
'\\')
190 if (inputIt == input.end())
193 return DecoderResult(
static_cast<size_t>(inputIt - input.begin()), get_allocator());
196 char nextChar = *inputIt;
201 value.push_back(nextChar);
205 value.push_back(
'\b');
209 value.push_back(
'\f');
213 value.push_back(
'\n');
217 value.push_back(
'\r');
221 value.push_back(
'\t');
227 if (!decodeUnicodeEscape(input, inputIt, value))
230 return DecoderResult(
static_cast<size_t>(inputIt - input.begin()), get_allocator());
237 return DecoderResult(
static_cast<size_t>(inputIt - input.begin()), get_allocator());
240 else if (*inputIt ==
'"')
244 return DecoderResult(
245 static_cast<size_t>(inputIt - input.begin()), std::move(value), get_allocator());
249 value.push_back(*inputIt++);
254 return DecoderResult(input.size(), get_allocator());
257 template <
typename ALLOC>
258 bool BasicJsonDecoder<ALLOC>::decodeUnicodeEscape(
263 if (inputIt == input.end() || *inputIt++ !=
'0')
265 if (inputIt == input.end() || *inputIt++ !=
'0')
268 if (inputIt == input.end())
270 const char char1 = decodeHex(*inputIt++);
274 if (inputIt == input.end())
276 const char char2 = decodeHex(*inputIt++);
280 value.push_back(
static_cast<char>((
static_cast<uint32_t
>(char1) << 4U) |
static_cast<uint32_t
>(char2)));
284 template <
typename ALLOC>
285 char BasicJsonDecoder<ALLOC>::decodeHex(
char character)
287 if (character >=
'0' && character <=
'9')
288 return static_cast<char>(character -
'0');
289 else if (character >=
'a' && character <=
'f')
290 return static_cast<char>(character -
'a' + 10);
291 else if (character >=
'A' && character <=
'F')
292 return static_cast<char>(character -
'A' + 10);
297 template <
typename ALLOC>
298 size_t BasicJsonDecoder<ALLOC>::checkNumber(
StringView input,
bool& isDouble,
bool& isSigned)
301 bool acceptExpSign =
false;
302 bool isScientificDouble =
false;
315 while (inputIt != input.end())
319 acceptExpSign =
false;
320 if (*inputIt ==
'+' || *inputIt ==
'-')
327 if (*inputIt >=
'0' && *inputIt <=
'9')
333 if ((*inputIt ==
'e' || *inputIt ==
'E') && !isScientificDouble)
336 isScientificDouble =
true;
337 acceptExpSign =
true;
342 if (*inputIt ==
'.' && !isDouble)
352 const size_t numberLen =
static_cast<size_t>(inputIt - input.begin());
353 if (isSigned && numberLen == 1)
359 template <
typename ALLOC>
360 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeNumber(
StringView input)
362 bool isDouble =
false;
363 bool isSigned =
false;
364 const size_t numChars = checkNumber(input, isDouble, isSigned);
366 return DecoderResult(1, get_allocator());
371 return decodeDouble(input, numChars);
373 return decodeSigned(input);
375 return decodeUnsigned(input);
378 template <
typename ALLOC>
379 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeSigned(
StringView input)
381 char* pEnd =
nullptr;
383 const int64_t value = std::strtoll(input.begin(), &pEnd, 10);
385 const bool overflow = (errno == ERANGE);
387 return DecoderResult(
static_cast<size_t>(pEnd - input.begin()), value, overflow, get_allocator());
390 template <
typename ALLOC>
391 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeUnsigned(
StringView input)
393 char* pEnd =
nullptr;
395 const uint64_t value = std::strtoull(input.begin(), &pEnd, 10);
397 const bool overflow = (errno == ERANGE);
399 return DecoderResult(
static_cast<size_t>(pEnd - input.begin()), value, overflow, get_allocator());
402 template <
typename ALLOC>
403 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeDouble(
406 char* pEnd =
nullptr;
407 const double value = std::strtod(input.begin(), &pEnd);
408 if (
static_cast<size_t>(pEnd - input.begin()) != numChars)
409 return DecoderResult(numChars, get_allocator());
411 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)