libzypp  17.37.5
json.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
9 
10 #include "json.h"
11 #include <zypp-core/AutoDispose.h>
12 
13 namespace zypp::json {
14 
15  constexpr std::string_view TOK_NAMES[Parser::Token::TOK_COUNT] = {
16  "TOK_STRING",
17  "TOK_NUMBER_FLOAT",
18  "TOK_NUMBER_UINT",
19  "TOK_NUMBER_INT",
20  "TOK_BOOL_TRUE",
21  "TOK_BOOL_FALSE",
22  "TOK_NULL",
23  "TOK_LSQUARE_BRACKET",
24  "TOK_RSQUARE_BRACKET",
25  "TOK_LCURLY_BRACKET",
26  "TOK_RCURLY_BRACKET",
27  "TOK_COMMA",
28  "TOK_COLON",
29  "TOK_END"
30  };
31 
32  static bool isWhiteSpace ( const char ch ) {
33  static constexpr char whitespaces[] { ' ', '\n', '\r', '\t', 0 };
34  return ( std::find (whitespaces, whitespaces+4, ch ) != whitespaces+4 );
35  }
36 
38  {
39  using namespace zyppng::operators;
40  _stream = input_r;
41  zypp_defer{
42  _stream.reset();
43  };
44 
45  auto document = nextToken()
46  | and_then( [&](Parser::Token t) {
47  switch ( t._type ) {
48  case Token::TOK_LSQUARE_BRACKET:
49  return parseArray() | and_then([&]( Array a ){ return zyppng::make_expected_success( Value(std::move(a))); } );
51  return parseObject() | and_then([&]( Object a ){ return zyppng::make_expected_success( Value(std::move(a))); } );
52  case Token::TOK_STRING:
53  return zyppng::make_expected_success<Value>( String(t._token) );
55  return zyppng::make_expected_success<Value>( Bool(false) );
57  return zyppng::make_expected_success<Value>( Bool(true) );
59  return Number::fromString( t._token ) | and_then( []( Number n ){ return zyppng::make_expected_success( Value(std::move(n)) ); } );
61  return UInt::fromString( t._token ) | and_then( []( UInt n ){ return zyppng::make_expected_success( Value(std::move(n)) ); } );
63  return Int::fromString( t._token ) | and_then( []( Int n ){ return zyppng::make_expected_success( Value(std::move(n)) ); } );
64  case Token::TOK_NULL:
66  case Token::TOK_END:
68  default:
69  return makeParseError<Value>( str::Str() << "Unexpected token " << TOK_NAMES[t._type] << ", json document must consist of a valid JSON value, object or array.", ZYPP_EX_CODELOCATION );
70  }
71  });
72 
73  if ( !document )
74  return document;
75 
76  // expect end of document
77  auto endToken = nextToken();
78  if ( !endToken )
79  return zyppng::expected<Value>::error( endToken.error() );
80  if ( endToken->_type != Token::TOK_END ) {
81  return makeParseError<Value>( str::Str() << "Unexpected token " << TOK_NAMES[endToken->_type] << ", EOF was expected.", ZYPP_EX_CODELOCATION );
82  }
83  // all good
84  return document;
85  }
86 
88  {
89  using namespace zyppng::operators;
90 
91  _nestingDepth++;
93  if ( _nestingDepth > 1000 ) {
94  return makeParseError<Object>( str::Str() << "Nesting level is too deep ( > 1000 ).", ZYPP_EX_CODELOCATION );
95  }
96 
97  enum State {
98  Obj_Start,
99  Obj_Expect_Comma_Or_End,
100  Obj_Expect_Pair
101  } state = Obj_Start;
102 
103  Object o;
104 
105  const auto &parsePair = [&]( String &&key ) {
106  return nextToken()
107  | and_then([&]( Token maybeColon ) {
108  if ( maybeColon._type == Token::TOK_COLON )
109  return parseValue();
110  else
111  return makeParseError<Value>( str::Str() << "Unexpected token " << TOK_NAMES[maybeColon._type] << ", colon was expected in key, value pair.", ZYPP_EX_CODELOCATION );
112  })
113  | and_then([&]( Value val ){
114  o.add ( key, std::move(val) );
116  });
117  };
118 
119  while ( true ) {
120 
121  auto t = nextToken();
122  if ( !t )
123  return zyppng::expected<Object>::error( t.error( ) );
124 
125  switch ( state ) {
126  case Obj_Start: {
127  // we can have either the start of a key-value pair or a closing }
128  switch ( t->_type ) {
129  case Token::TOK_STRING: {
130  auto res = parsePair( String( std::move(t->_token) ) );
131  if ( !res )
132  return zyppng::expected<Object>::error( res.error( ) );
133 
134  state = Obj_Expect_Comma_Or_End;
135  break;
136  }
138  return zyppng::make_expected_success(std::move(o));
139  break;
140  }
141  default:
142  return makeParseError<Object>( str::Str() << "Unexpected token " << TOK_NAMES[t->_type] << " while parsing a Object.", ZYPP_EX_CODELOCATION );
143  break;
144  }
145  break;
146  }
147  case Obj_Expect_Comma_Or_End: {
148  switch ( t->_type ) {
149  case Token::TOK_COMMA: {
150  state = Obj_Expect_Pair;
151  break;
152  }
154  return zyppng::make_expected_success(std::move(o));
155  break;
156  }
157  default:
158  return makeParseError<Object>( str::Str() << "Unexpected token " << TOK_NAMES[t->_type] << " while parsing a Object.", ZYPP_EX_CODELOCATION );
159  break;
160  }
161  break;
162  }
163  case Obj_Expect_Pair: {
164  // we can have either the start of a key-value pair or a closing }
165  switch ( t->_type ) {
166  case Token::TOK_STRING: {
167  auto res = parsePair( String( std::move(t->_token) ) );
168  if ( !res )
169  return zyppng::expected<Object>::error( res.error( ) );
170 
171  state = Obj_Expect_Comma_Or_End;
172  break;
173  }
174  default:
175  return makeParseError<Object>( str::Str() << "Unexpected token " << TOK_NAMES[t->_type] << " while parsing a Object.", ZYPP_EX_CODELOCATION );
176  break;
177  }
178  break;
179  }
180  }
181  }
182  }
183 
185  {
186  using namespace zyppng::operators;
187 
188  _nestingDepth++;
190  if ( _nestingDepth > 1000 ) {
191  return makeParseError<Array>( str::Str() << "Nesting level is too deep ( > 1000 ).", ZYPP_EX_CODELOCATION );
192  }
193 
194  enum State {
195  Arr_Init, // can be value or array end token
196  Arr_Value, // next token must be a value
197  Arr_Expect_Comma_Or_End, // next token must be TOK_COMMA or TOK_RSQUARE_BRACKET
198  } state = Arr_Init;
199 
200  Array a;
201  while ( true ) {
202  switch ( state ) {
203  case Arr_Init: {
204  auto tok = nextToken();
205  if ( !tok )
206  return zyppng::expected<Array>::error( tok.error( ) );
207 
208  if ( tok->_type == Token::TOK_RSQUARE_BRACKET )
209  return zyppng::make_expected_success( std::move(a) );
210 
211  auto maybeVal = finishParseValue( std::move(*tok) );
212  if ( !maybeVal )
213  return zyppng::expected<Array>::error( maybeVal.error( ) );
214 
215  a.add( std::move(*maybeVal) );
216  state = Arr_Expect_Comma_Or_End;
217  break;
218  }
219  case Arr_Value: {
220  auto maybeVal = parseValue();
221  if ( !maybeVal )
222  return zyppng::expected<Array>::error( maybeVal.error( ) );
223 
224  a.add( std::move(*maybeVal) );
225  state = Arr_Expect_Comma_Or_End;
226  break;
227  }
228  case Arr_Expect_Comma_Or_End: {
229  auto tok = nextToken();
230  if ( !tok )
231  return zyppng::expected<Array>::error( tok.error( ) );
232 
233  switch(tok->_type) {
235  return zyppng::make_expected_success( std::move(a) );
236  case Token::TOK_COMMA:
237  state = Arr_Value;
238  break;
239  default:
240  return makeParseError<Array>( str::Str() << "Unexpected token " << TOK_NAMES[tok->_type] << " while parsing a JSON value.", ZYPP_EX_CODELOCATION );
241  break;
242  }
243  break;
244  }
245  }
246  }
247  }
248 
253  {
254  using namespace zyppng::operators;
255  return nextToken()
256  | and_then([&]( Token &&tok ) {
257  return finishParseValue ( std::move(tok) );
258  });
259  }
260 
266  {
267  using namespace zyppng::operators;
268  switch( begin._type ) {
269  case Token::TOK_STRING:
270  return zyppng::make_expected_success( Value( String( std::move(begin._token) )));
272  return Number::fromString( begin._token ) | and_then( []( Number n ){ return zyppng::make_expected_success( Value(std::move(n)) ); } );
274  return UInt::fromString( begin._token ) | and_then( []( UInt n ){ return zyppng::make_expected_success( Value(std::move(n)) ); } );
276  return Int::fromString( begin._token ) | and_then( []( Int n ){ return zyppng::make_expected_success( Value(std::move(n)) ); } );
278  return zyppng::make_expected_success( Value( Bool( true ) ));
280  return zyppng::make_expected_success( Value( Bool( false ) ));
281  case Token::TOK_NULL:
284  return parseArray() | and_then( []( Array a ){ return zyppng::make_expected_success( Value(std::move(a)) ); } );
286  return parseObject() | and_then( []( Object o ){ return zyppng::make_expected_success( Value(std::move(o)) ); } );
287  default:
288  return makeParseError<Value>( str::Str() << "Unexpected token " << TOK_NAMES[begin._type] << " while parsing a JSON value.", ZYPP_EX_CODELOCATION );
289  break;
290  }
291  }
292 
294  {
295  using namespace zyppng::operators;
296  return consumeString ( "null" )
297  | and_then ( [&](){
299  });
300  }
301 
303  {
304  using namespace zyppng::operators;
305  char next = peekChar();
306  if ( next == 't' ) {
307  return consumeString ( "true" )
308  | and_then ( [&](){
310  });
311  } else if ( next == 'f' ) {
312  return consumeString ( "false" )
313  | and_then ( [&](){
315  });
316  } else if ( next == eofChar() ) {
317  return makeParseError( str::Str() << "Unexpected EOF while parsing a boolean", ZYPP_EX_CODELOCATION );
318  } else {
319  return makeParseError( str::Str() << "Unexpected char " << next << " while parsing a boolean", ZYPP_EX_CODELOCATION );
320  }
321  }
322 
324  {
325  enum State {
326  Begin, // accepts sign, 0-9
327  ExpectFraction_or_End, // received 0 in init state, now needs a fraction a exponent or an end
328  ExpectDigit, // requires a digit to be next
329  Digit, // expects digit 0-9 or e E to move into exponent parsing, any other char ends number parsing
330  Exponent_Begin, // we saw a e or E and now expect a sign or digit
331  Exponent_ExpectDigit, // state entered after a sign, where we require a digit
332  Exponent // digits until we see something else
333  } state = Begin;
334 
335  Token t;
336  bool isSigned = false;
337  bool acceptSign = true;
338  bool done = false;
339  bool isFloating = false;
340  bool hasFraction = false;
341 
342  while ( !done ) {
343  char c = peekChar();
344 
345  switch ( state ) {
346  case Begin: {
347  if ( c == '-' && acceptSign ) {
348  acceptSign = false;
349  isSigned = true;
350  t._token.push_back(c);
351  consumeChar();
352  } else if ( c >= '1' && c <= '9' ) {
353  t._token.push_back (c);
354  consumeChar();
355  state = Digit;
356  } else if ( c == '0' ) {
357  t._token.push_back (c);
358  consumeChar();
359  state = ExpectFraction_or_End;
360  } else if ( c == eofChar() ) {
361  return makeParseError( str::Str() << "Unexpected EOF while parsing a number.", ZYPP_EX_CODELOCATION );
362  } else {
363  return makeParseError( str::Str() << "Unexpected char " << c << " while parsing a number.", ZYPP_EX_CODELOCATION );
364  }
365  break;
366  }
367  case ExpectFraction_or_End: {
368  if ( c == '.' ) {
369  t._token.push_back(c);
370  consumeChar();
371  isFloating = true;
372  hasFraction = true;
373  state = ExpectDigit;
374  } else if ( c == 'e' || c == 'E' ) {
375  t._token.push_back (c);
376  consumeChar();
377  state = Exponent_Begin;
378  isFloating = true;
379  } else {
380  // any other char marks the end of the number
381  done = true;
382  }
383  break;
384  }
385  case ExpectDigit: {
386  if ( c >= '0' && c <= '9' ) {
387  t._token.push_back (c);
388  consumeChar();
389  state = Digit;
390  } else {
391  // any other char is a error
392  return makeParseError( str::Str() << "Unexpected char " << c << " while parsing a number, digit was expected.", ZYPP_EX_CODELOCATION );
393  }
394  break;
395  }
396  case Digit: {
397  if ( c >= '0' && c <= '9' ) {
398  t._token.push_back (c);
399  consumeChar();
400  } else if ( c == 'e' || c == 'E' ) {
401  t._token.push_back (c);
402  consumeChar();
403  state = Exponent_Begin;
404  isFloating = true;
405  } else if ( c == '.' && !hasFraction ) {
406  t._token.push_back(c);
407  consumeChar();
408  isFloating = true;
409  hasFraction = true;
410  state = ExpectDigit;
411  } else {
412  // any other char marks the end of the number
413  done = true;
414  }
415  break;
416  }
417  case Exponent_Begin: {
418  if ( c == '+' || c == '-' ) {
419  t._token.push_back (c);
420  consumeChar();
421  state = Exponent_ExpectDigit;
422  } else if ( c >= '0' && c <= '9') {
423  t._token.push_back (c);
424  consumeChar();
425  state = Exponent;
426  } else if ( c == eofChar() ) {
427  return makeParseError( str::Str() << "Unexpected EOF while parsing a number.", ZYPP_EX_CODELOCATION );
428  } else {
429  return makeParseError( str::Str() << "Unexpected char " << c << " while parsing a number, sign or digit was expected.", ZYPP_EX_CODELOCATION );
430  }
431  break;
432  }
433  case Exponent_ExpectDigit:
434  case Exponent: {
435  if ( c >= '0' && c <= '9' ) {
436 
437  if ( state != Exponent )
438  state = Exponent;
439 
440  t._token.push_back (c);
441  consumeChar();
442 
443  } else if ( state == Exponent_ExpectDigit ) {
444  return makeParseError( str::Str() << "Unexpected char " << c << " while parsing a number with exponent, digit was expected.", ZYPP_EX_CODELOCATION );
445  } else {
446  // any other char marks the end of the number
447  done = true;
448  }
449  break;
450  }
451  }
452  }
453 
454  if ( isFloating ) {
456  } else {
457  if ( isSigned ) {
459  } else {
461  }
462  }
463  return zyppng::make_expected_success( std::move(t) );
464  }
465 
466  std::istream::char_type Parser::popChar()
467  {
468  if ( !_stream )
469  return std::istream::traits_type::eof();
470 
471  auto &input = _stream->stream();
472  if ( input.eof () )
473  return std::istream::traits_type::eof();
474 
475  return input.get();
476  }
477 
478  std::istream::char_type Parser::peekChar()
479  {
480  if ( !_stream )
481  return std::istream::traits_type::eof();
482 
483  auto &input = _stream->stream();
484  if ( input.eof () )
485  return std::istream::traits_type::eof();
486 
487  return input.peek();
488  }
489 
491  {
492  if ( _stream )
493  _stream->stream().ignore();
494  }
495 
497  {
498  for ( uint i = 0; i < str.size(); i++ ) {
499  char c = popChar();
500  if ( c == eofChar () )
501  return makeParseError<void>( str::Str() << "Unexpected EOF while parsing: " << str, ZYPP_EX_CODELOCATION );
502  if ( c != str.at(i) )
503  return makeParseError<void>( str::Str() << "Unexpected char " << c << " ,character " << str.at(i) << " was expected while parsing: " << str, ZYPP_EX_CODELOCATION );
504  }
506  }
507 
509  {
510  try {
511  char nextChar = peekChar();
512 
513  while ( nextChar != eofChar()
514  && isWhiteSpace (nextChar) ) {
515  consumeChar ();
516  nextChar = peekChar();
517  }
518 
519  if ( nextChar == eofChar() ) {
522  } );
523  }
524 
525  switch ( nextChar ) {
526  case '"': {
527  return parseStringToken ();
528  }
529  case '-':
530  case '0':
531  case '1':
532  case '2':
533  case '3':
534  case '4':
535  case '5':
536  case '6':
537  case '7':
538  case '8':
539  case '9': {
540  return parseNumberToken();
541  }
542  case 't':
543  case 'f': {
544  return parseBoolToken();
545  }
546  case 'n': {
547  return parseNullToken();
548  }
549  case '{': {
550  consumeChar ();
553  } );
554  }
555  case '}': {
556  consumeChar ();
559  } );
560  }
561  case '[': {
562  consumeChar ();
565  } );
566  }
567  case ']': {
568  consumeChar ();
571  } );
572  }
573  case ':': {
574  consumeChar ();
577  } );
578  }
579  case ',': {
580  consumeChar ();
583  } );
584  }
585  default:
586  return makeParseError( ( str::Str() << "Unexpected token: " << nextChar << " in json stream."), ZYPP_EX_CODELOCATION );
587  break;
588  }
589  } catch (...) {
591  }
592  }
593 
595  {
596  using namespace zyppng::operators;
597  auto c = popChar ();
598 
599  // shouldn't happen because we peeked before that there is a "
600  if ( c != '"' ) {
601  return makeParseError( ( str::Str() << "Unexpected token: " << c << ", a JSON String must start with \"."), ZYPP_EX_CODELOCATION );
602  }
603 
604  Token t {
606  };
607 
608  while( true ) {
609  c = popChar();
610  // escaped
611  if ( c == eofChar () ) {
612  return makeParseError( ( str::Str() << "Unexpected EOF token in the middle of a string."), ZYPP_EX_CODELOCATION );
613 
614  } else if ( c == '\\' ) {
615 
616  c = this->popChar();
617  if ( c == eofChar() ) {
618  return makeParseError( "Unexpected EOF in escaped string character.", ZYPP_EX_CODELOCATION );
619  }
620 
621  switch ( c ) {
622  case '"' :
623  case '\\':
624  case '/' :
625  {
626  t._token.push_back(c);
627  break;
628  }
629  case 'b' : {
630  t._token.push_back( '\b' );
631  break;
632  }
633  case 'f' : {
634  t._token.push_back( '\f' );
635  break;
636  }
637  case 'n' : {
638  t._token.push_back( '\n' );
639  break;
640  }
641  case 'r' : {
642  t._token.push_back( '\r' );
643  break;
644  }
645  case 't' : {
646  t._token.push_back( '\t' );
647  break;
648  }
649  case 'u' : {
650  const auto &pop4HexBytes = [&]( ) {
651  std::vector<char> data( 4, '\0' );
652  for (int i = 0; i < 4; i++) {
653  data[i] = this->popChar();
654  if ( data[i] == eofChar() ) {
655  return makeParseError<std::vector<char>>( "Unexpected EOF in \\u escaped string character.", ZYPP_EX_CODELOCATION );
656  }
657 
658  if ( (data[i] >= '0' && data[i] <= '9' )
659  || (data[i] >= 'A' && data[i] <= 'F' )
660  || (data[i] >= 'a' && data[i] <= 'f' )
661  ) {
662  // accept char
663  continue;
664  }
665  return makeParseError<std::vector<char>>( str::Str() << "Unexpected token " << str::hexstring(c) << " in \\u escaped string character.", ZYPP_EX_CODELOCATION );
666  }
667  return zyppng::expected<std::vector<char>>::success( std::move(data) );
668  };
669 
670  // check data and convert it to a codepoint, if data contains the
671  // start of a surrogate pair, read the second value and return the resulting codepoint
672  const auto &convertToCodepoint = [&]( std::vector<char> data ){
673  // check if the codepoint is int the UTF-16 surrogate pair range,
674  // if yes we need to fetch another 4 bits
675 
676  const auto data1View = std::string_view(data.data(), data.size());
677  auto cp = str::hexCharToValue<uint32_t>( data1View );
678 
679  if ( !cp ) {
680  return makeParseError<uint32_t>( str::Str() << "Invalid \\u escaped character: " << data1View , ZYPP_EX_CODELOCATION );
681  }
682 
683  // UTF16 surrogate pair?
684  if ( (*cp) >= 0xd800 && (*cp) <= 0xdbff ) {
685  return consumeString ("\\u" ) // require another \u
686  | and_then( [&](){ return pop4HexBytes( ); })
687  | and_then( [&]( std::vector<char> data2 ){
688  // convert to codepoint
689  const auto data2View = std::string_view(data2.data(), data2.size());
690  const auto lowCp = str::hexCharToValue<uint32_t>( data2View );
691 
692  if ( !lowCp ) {
693  return makeParseError<uint32_t>( str::Str() << "Invalid \\u escaped character: " << data2View , ZYPP_EX_CODELOCATION );
694  }
695 
696  if ( *lowCp < 0xDC00 || *lowCp > 0xDFFF) {
697  return makeParseError<uint32_t>( str::Str() << "Invalid UTF16 surrogate pair: (" << data1View << "," << data2View <<")" , ZYPP_EX_CODELOCATION );
698  }
699 
700  constexpr uint16_t low10BitMask = 0x3FF; // low 10 bits
701  uint32_t codepoint = (( (*cp) & low10BitMask ) << 10 ) | ( (*lowCp) & low10BitMask );
702  codepoint += 0x10000;
703  return zyppng::expected<uint32_t>::success( codepoint );
704  });
705 
706  } else {
708  }
709  };
710 
711  const auto &codepointToUtf8String = [&]( uint32_t cp ) {
712  if ( cp == 0 ) {
713  // json does allow a null character to be part of the string
714  t._token += '\0';
716  }
717  const auto &conv = str::codepointToUtf8String( cp );
718  if ( conv.size () == 0 ) {
719  return makeParseError<void>( str::Str() << "Invalid codepoint in string " << cp, ZYPP_EX_CODELOCATION );
720  }
721  if ( !str::validateUtf8(conv) ) {
722  return makeParseError<void>( str::Str() << "Invalid codepoint in string " << cp << " ,this is not a valid UTF-8 character.", ZYPP_EX_CODELOCATION );
723  }
724  t._token += conv;
726  };
727 
728  auto res = pop4HexBytes()
729  | and_then( convertToCodepoint )
731 
732  if ( !res )
733  return zyppng::expected<Parser::Token>::error(res.error());
734 
735  break;
736  }
737  default:
738  return makeParseError( str::Str() << "Unexpected token " << str::hexstring(c) << " in \\ escaped string character.", ZYPP_EX_CODELOCATION );
739  }
740  } else if( c == '"' ) {
741  break;
742  } else if( c >= 0 && c <= 0x1f ) {
743  return makeParseError( str::Str() << "Unescaped control character " << str::hexstring(c) << " in string is not allowed.", ZYPP_EX_CODELOCATION );
744  } else {
745  t._token.push_back(c);
746  }
747  }
748 
750  }
751 
753  {
754  return Token {
756  };
757  }
758 
759 
760 }
761 
762 
static std::istream::char_type eofChar()
Definition: json.h:91
std::string _token
Definition: json.h:64
zyppng::expected< Token > parseNumberToken()
Definition: json.cc:323
String related utilities and Regular expression matching.
static expected< std::decay_t< Type >, Err > make_expected_success(Type &&t)
Definition: expected.h:397
zyppng::expected< Value > finishParseValue(Token begin)
Definition: json.cc:265
zyppng::expected< T > makeParseError(const std::string &message, exception_detail::CodeLocation &&loc)
Definition: json.h:96
Helper to create and pass std::istream.
Definition: inputstream.h:56
static zyppng::expected< UInt > fromString(const std::string &str)
Definition: JsonNumber.h:123
zyppng::expected< Value > parseValue()
Definition: json.cc:252
#define zypp_defer
Definition: AutoDispose.h:293
std::optional< InputStream > _stream
Definition: json.h:101
zyppng::expected< Array > parseArray()
Definition: json.cc:184
zyppng::expected< Token > parseStringToken()
Definition: json.cc:594
std::istream::char_type peekChar()
Definition: json.cc:478
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition: String.h:212
static zyppng::expected< Int > fromString(const std::string &str)
Definition: JsonNumber.h:86
int _nestingDepth
Definition: json.h:102
static zyppng::expected< Number > fromString(const std::string &str)
Definition: JsonNumber.h:32
zyppng::expected< void > consumeString(const std::string &str)
Definition: json.cc:496
std::string codepointToUtf8String(uint32_t unichar)
Definition: String.cc:525
static expected success(ConsParams &&...params)
Definition: expected.h:115
static Token eof()
Definition: json.cc:752
static bool isWhiteSpace(const char ch)
Definition: json.cc:32
zyppng::expected< Token > parseNullToken()
Definition: json.cc:293
void consumeChar()
Definition: json.cc:490
void add(String key_r, Value val_r)
Add key/value pair.
Definition: JsonValue.cc:48
std::istream::char_type popChar()
Definition: json.cc:466
bool validateUtf8(std::string_view str)
Definition: String.cc:520
unsigned short a
ResultType and_then(const expected< T, E > &exp, Function &&f)
Definition: expected.h:423
#define ZYPP_FWD_CURRENT_EXCPT()
Drops a logline and returns the current Exception as a std::exception_ptr.
Definition: Exception.h:471
constexpr std::string_view TOK_NAMES[Parser::Token::TOK_COUNT]
Definition: json.cc:15
zyppng::expected< Object > parseObject()
Definition: json.cc:87
zyppng::expected< Token > nextToken()
Definition: json.cc:508
std::string hexstring(char n, int w=4)
Definition: String.h:325
zyppng::expected< Token > parseBoolToken()
Definition: json.cc:302
#define ZYPP_EX_CODELOCATION
Create CodeLocation object storing the current location.
Definition: Exception.h:69
zyppng::expected< Value > parse(const InputStream &input_r)
Parse the stream.
Definition: json.cc:37