1#ifndef ZSERIO_JSON_DECODER_H_INC
2#define ZSERIO_JSON_DECODER_H_INC
20template <
typename ALLOC = std::allocator<u
int8_t>>
111 using namespace std::literals::string_view_literals;
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);
135 return decodeLiteral(
input,
"-Infinity"sv, -
static_cast<double>(
INFINITY));
137 return decodeNumber(
input);
139 return decodeNumber(
input);
144 template <
typename T>
145 DecoderResult decodeLiteral(std::string_view
input, std::string_view
literal, T&& value);
146 DecoderResult decodeString(std::string_view
input);
147 static bool decodeUnicodeEscape(std::string_view
input, std::string_view::const_iterator&
inputIt,
150 size_t checkNumber(std::string_view
input,
bool&
isDouble,
bool& isSigned);
151 DecoderResult decodeNumber(std::string_view
input);
152 DecoderResult decodeSigned(std::string_view
input);
153 DecoderResult decodeUnsigned(std::string_view
input);
154 DecoderResult decodeDouble(std::string_view
input,
size_t numChars);
157template <
typename ALLOC>
159typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeLiteral(
160 std::string_view input, std::string_view literal, T&& value)
162 std::string_view::const_iterator literalIt = literal.begin();
163 std::string_view::const_iterator inputIt = input.begin();
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());
183template <
typename ALLOC>
184typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeString(std::string_view input)
186 std::string_view::const_iterator inputIt = input.begin() + 1;
187 BasicString<RebindAlloc<ALLOC, char>> 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());
261template <
typename ALLOC>
262bool BasicJsonDecoder<ALLOC>::decodeUnicodeEscape(std::string_view input,
263 std::string_view::const_iterator& inputIt,
BasicString<RebindAlloc<ALLOC, char>>& value)
266 if (inputIt == input.end() || *inputIt++ !=
'0')
270 if (inputIt == input.end() || *inputIt++ !=
'0')
275 if (inputIt == input.end())
280 const int32_t hex1 = decodeHex(*inputIt++);
286 if (inputIt == input.end())
291 const int32_t hex2 = decodeHex(*inputIt++);
297 const uint32_t characterInt = (
static_cast<uint32_t
>(hex1) << 4U) |
static_cast<uint32_t
>(hex2);
298 using char_traits = std::char_traits<char>;
299 const char character = char_traits::to_char_type(
static_cast<char_traits::int_type
>(characterInt));
300 value.push_back(character);
305template <
typename ALLOC>
306int32_t BasicJsonDecoder<ALLOC>::decodeHex(
char character)
308 if (character >=
'0' && character <=
'9')
310 return static_cast<int32_t
>(character -
'0');
312 else if (character >=
'a' && character <=
'f')
314 return static_cast<int32_t
>(character -
'a' + 10);
316 else if (character >=
'A' && character <=
'F')
318 return static_cast<int32_t
>(character -
'A' + 10);
324template <
typename ALLOC>
325size_t BasicJsonDecoder<ALLOC>::checkNumber(std::string_view input,
bool& isDouble,
bool& isSigned)
327 std::string_view::const_iterator inputIt = input.begin();
328 bool acceptExpSign =
false;
329 bool isScientificDouble =
false;
342 while (inputIt != input.end())
346 acceptExpSign =
false;
347 if (*inputIt ==
'+' || *inputIt ==
'-')
354 if (*inputIt >=
'0' && *inputIt <=
'9')
360 if ((*inputIt ==
'e' || *inputIt ==
'E') && !isScientificDouble)
363 isScientificDouble =
true;
364 acceptExpSign =
true;
369 if (*inputIt ==
'.' && !isDouble)
379 const size_t numberLen =
static_cast<size_t>(inputIt - input.begin());
380 if (isSigned && numberLen == 1)
388template <
typename ALLOC>
389typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeNumber(std::string_view input)
391 bool isDouble =
false;
392 bool isSigned =
false;
393 const size_t numChars = checkNumber(input, isDouble, isSigned);
396 return DecoderResult(1, get_allocator());
403 return decodeDouble(input, numChars);
407 return decodeSigned(input);
411 return decodeUnsigned(input);
415template <
typename ALLOC>
416typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeSigned(std::string_view input)
418 const char* pBegin = &input.front();
419 char* pEnd =
nullptr;
421 const int64_t value = std::strtoll(pBegin, &pEnd, 10);
423 const bool overflow = (errno == ERANGE);
424 const size_t numRead =
static_cast<size_t>(pEnd - pBegin);
426 return DecoderResult(numRead, value, overflow, get_allocator());
429template <
typename ALLOC>
430typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeUnsigned(std::string_view input)
432 const char* pBegin = &input.front();
433 char* pEnd =
nullptr;
435 const uint64_t value = std::strtoull(pBegin, &pEnd, 10);
437 const bool overflow = (errno == ERANGE);
438 const size_t numRead =
static_cast<size_t>(pEnd - pBegin);
440 return DecoderResult(numRead, value, overflow, get_allocator());
443template <
typename ALLOC>
444typename BasicJsonDecoder<ALLOC>::DecoderResult BasicJsonDecoder<ALLOC>::decodeDouble(
445 std::string_view input,
size_t numChars)
447 const char* pBegin = &input.front();
448 char* pEnd =
nullptr;
449 const double value = std::strtod(pBegin, &pEnd);
450 if (
static_cast<size_t>(pEnd - pBegin) != numChars)
452 return DecoderResult(numChars, get_allocator());
455 return DecoderResult(numChars, value, get_allocator());
allocator_type get_allocator() const
BasicJsonDecoder(const ALLOC &allocator)
DecoderResult decodeValue(std::string_view input)
std::basic_string< char, std::char_traits< char >, ALLOC > BasicString
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)