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)
121 return decodeLiteral(input,
"null"_sv,
nullptr);
123 return decodeLiteral(input,
"true"_sv,
true);
125 return decodeLiteral(input,
"false"_sv,
false);
127 return decodeLiteral(input,
"NaN"_sv,
static_cast<double>(NAN));
129 return decodeLiteral(input,
"Infinity"_sv,
static_cast<double>(INFINITY));
131 return decodeString(input);
133 if (input.
size() > 1 && input[1] ==
'I')
135 return decodeLiteral(input,
"-Infinity"_sv, -
static_cast<double>(INFINITY));
137 return decodeNumber(input);
139 return decodeNumber(input);
144 template <
typename T>
147 static bool decodeUnicodeEscape(
149 static char decodeHex(
char character);
150 size_t checkNumber(
StringView input,
bool& isDouble,
bool& isSigned);
153 DecoderResult decodeUnsigned(
StringView input);
154 DecoderResult decodeDouble(
StringView input,
size_t numChars);
157 template <
typename ALLOC>
158 template <
typename T>
159 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeLiteral(
164 while (inputIt != input.end() && literalIt != literal.end())
166 if (*inputIt++ != *literalIt++)
169 return DecoderResult(
static_cast<size_t>(inputIt - input.begin()), get_allocator());
173 if (literalIt != literal.end())
176 return DecoderResult(input.size(), get_allocator());
180 return DecoderResult(literal.size(), std::forward<T>(value), get_allocator());
183 template <
typename ALLOC>
184 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeString(
StringView input)
187 string<ALLOC> value(get_allocator());
189 while (inputIt != input.end())
191 if (*inputIt ==
'\\')
194 if (inputIt == input.end())
197 return DecoderResult(
static_cast<size_t>(inputIt - input.begin()), get_allocator());
200 char nextChar = *inputIt;
205 value.push_back(nextChar);
209 value.push_back(
'\b');
213 value.push_back(
'\f');
217 value.push_back(
'\n');
221 value.push_back(
'\r');
225 value.push_back(
'\t');
231 if (!decodeUnicodeEscape(input, inputIt, value))
234 return DecoderResult(
static_cast<size_t>(inputIt - input.begin()), get_allocator());
241 return DecoderResult(
static_cast<size_t>(inputIt - input.begin()), get_allocator());
244 else if (*inputIt ==
'"')
248 return DecoderResult(
249 static_cast<size_t>(inputIt - input.begin()), std::move(value), get_allocator());
253 value.push_back(*inputIt++);
258 return DecoderResult(input.size(), get_allocator());
261 template <
typename ALLOC>
262 bool BasicJsonDecoder<ALLOC>::decodeUnicodeEscape(
267 if (inputIt == input.end() || *inputIt++ !=
'0')
271 if (inputIt == input.end() || *inputIt++ !=
'0')
276 if (inputIt == input.end())
280 const char char1 = decodeHex(*inputIt++);
286 if (inputIt == input.end())
290 const char char2 = decodeHex(*inputIt++);
296 value.push_back(
static_cast<char>((
static_cast<uint32_t
>(char1) << 4U) |
static_cast<uint32_t
>(char2)));
300 template <
typename ALLOC>
301 char BasicJsonDecoder<ALLOC>::decodeHex(
char character)
303 if (character >=
'0' && character <=
'9')
305 return static_cast<char>(character -
'0');
307 else if (character >=
'a' && character <=
'f')
309 return static_cast<char>(character -
'a' + 10);
311 else if (character >=
'A' && character <=
'F')
313 return static_cast<char>(character -
'A' + 10);
319 template <
typename ALLOC>
320 size_t BasicJsonDecoder<ALLOC>::checkNumber(
StringView input,
bool& isDouble,
bool& isSigned)
323 bool acceptExpSign =
false;
324 bool isScientificDouble =
false;
337 while (inputIt != input.end())
341 acceptExpSign =
false;
342 if (*inputIt ==
'+' || *inputIt ==
'-')
349 if (*inputIt >=
'0' && *inputIt <=
'9')
355 if ((*inputIt ==
'e' || *inputIt ==
'E') && !isScientificDouble)
358 isScientificDouble =
true;
359 acceptExpSign =
true;
364 if (*inputIt ==
'.' && !isDouble)
374 const size_t numberLen =
static_cast<size_t>(inputIt - input.begin());
375 if (isSigned && numberLen == 1)
383 template <
typename ALLOC>
384 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeNumber(
StringView input)
386 bool isDouble =
false;
387 bool isSigned =
false;
388 const size_t numChars = checkNumber(input, isDouble, isSigned);
391 return DecoderResult(1, get_allocator());
398 return decodeDouble(input, numChars);
402 return decodeSigned(input);
406 return decodeUnsigned(input);
410 template <
typename ALLOC>
411 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeSigned(
StringView input)
413 char* pEnd =
nullptr;
415 const int64_t value = std::strtoll(input.begin(), &pEnd, 10);
417 const bool overflow = (errno == ERANGE);
419 return DecoderResult(
static_cast<size_t>(pEnd - input.begin()), value, overflow, get_allocator());
422 template <
typename ALLOC>
423 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeUnsigned(
StringView input)
425 char* pEnd =
nullptr;
427 const uint64_t value = std::strtoull(input.begin(), &pEnd, 10);
429 const bool overflow = (errno == ERANGE);
431 return DecoderResult(
static_cast<size_t>(pEnd - input.begin()), value, overflow, get_allocator());
434 template <
typename ALLOC>
435 typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeDouble(
438 char* pEnd =
nullptr;
439 const double value = std::strtod(input.begin(), &pEnd);
440 if (
static_cast<size_t>(pEnd - input.begin()) != numChars)
442 return DecoderResult(numChars, get_allocator());
445 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)