1 #ifndef ZSERIO_JSON_DECODER_H_INC
2 #define ZSERIO_JSON_DECODER_H_INC
20 template <
typename ALLOC = std::allocator<u
int8_t>>
51 DecoderResult(
size_t numRead, T&& decodedValue,
const ALLOC& allocator) :
53 value(
std::forward<T>(decodedValue), allocator),
66 DecoderResult(
size_t numRead, T&& decodedValue,
bool overflow,
const ALLOC& allocator) :
68 value(createValue(
std::forward<T>(decodedValue), overflow, allocator)),
79 BasicAny<ALLOC> createValue(T&& decodedValue,
bool overflow,
const ALLOC& allocator)
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);
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>
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,
149 static int32_t decodeHex(
char character);
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);
157 template <
typename ALLOC>
158 template <
typename T>
159 typename 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())
180 return DecoderResult(literal.size(), std::forward<T>(value),
get_allocator());
183 template <
typename ALLOC>
184 typename 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++);
261 template <
typename ALLOC>
262 bool 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);
305 template <
typename ALLOC>
306 int32_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);
324 template <
typename ALLOC>
325 size_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)
388 template <
typename ALLOC>
389 typename 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);
403 return decodeDouble(input, numChars);
407 return decodeSigned(input);
411 return decodeUnsigned(input);
415 template <
typename ALLOC>
416 typename 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());
429 template <
typename ALLOC>
430 typename 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());
443 template <
typename ALLOC>
444 typename 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)
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
typename std::allocator_traits< ALLOC >::template rebind_alloc< T > RebindAlloc
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)