All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Public Types | Public Member Functions | Static Public Member Functions | Private Types | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
nlohmann::detail::lexer< BasicJsonType > Class Template Reference

lexical analysis More...

#include <json.hpp>

Public Types

enum  token_type {
  token_type::uninitialized, token_type::literal_true, token_type::literal_false, token_type::literal_null,
  token_type::value_string, token_type::value_unsigned, token_type::value_integer, token_type::value_float,
  token_type::begin_array, token_type::begin_object, token_type::end_array, token_type::end_object,
  token_type::name_separator, token_type::value_separator, token_type::parse_error, token_type::end_of_input,
  token_type::literal_or_value
}
 token types for the parser More...
 

Public Member Functions

 lexer (detail::input_adapter_t &&adapter)
 
 lexer (const lexer &)=delete
 
 lexer (lexer &&)=delete
 
lexeroperator= (lexer &)=delete
 
lexeroperator= (lexer &&)=delete
 
 ~lexer ()=default
 
constexpr number_integer_t get_number_integer () const noexcept
 return integer value More...
 
constexpr number_unsigned_t get_number_unsigned () const noexcept
 return unsigned integer value More...
 
constexpr number_float_t get_number_float () const noexcept
 return floating-point value More...
 
string_tget_string ()
 return current string value (implicitly resets the token; useful only once) More...
 
constexpr position_t get_position () const noexcept
 return position of last read token More...
 
std::string get_token_string () const
 
JSON_HEDLEY_RETURNS_NON_NULL
constexpr const char * 
get_error_message () const noexcept
 return syntax error message More...
 
bool skip_bom ()
 skip the UTF-8 byte order mark More...
 
token_type scan ()
 

Static Public Member Functions

JSON_HEDLEY_RETURNS_NON_NULL
static JSON_HEDLEY_CONST const
char * 
token_type_name (const token_type t) noexcept
 return name of values of type token_type (only used for errors) More...
 

Private Types

using number_integer_t = typename BasicJsonType::number_integer_t
 
using number_unsigned_t = typename BasicJsonType::number_unsigned_t
 
using number_float_t = typename BasicJsonType::number_float_t
 
using string_t = typename BasicJsonType::string_t
 

Private Member Functions

int get_codepoint ()
 get codepoint from 4 hex characters following \u More...
 
bool next_byte_in_range (std::initializer_list< int > ranges)
 check if the next byte(s) are inside a given range More...
 
token_type scan_string ()
 scan a string literal More...
 
token_type scan_number ()
 scan a number literal More...
 
token_type scan_literal (const char *literal_text, const std::size_t length, token_type return_type)
 
void reset () noexcept
 reset token_buffer; current character is beginning of token More...
 
std::char_traits< char >::int_type get ()
 
void unget ()
 unget current character (read it again on next get) More...
 
void add (int c)
 add a character to token_buffer More...
 

Static Private Member Functions

static JSON_HEDLEY_PURE char get_decimal_point () noexcept
 return the locale-dependent decimal point More...
 
static void strtof (float &f, const char *str, char **endptr) noexcept
 
static void strtof (double &f, const char *str, char **endptr) noexcept
 
static void strtof (long double &f, const char *str, char **endptr) noexcept
 

Private Attributes

detail::input_adapter_t ia = nullptr
 input adapter More...
 
std::char_traits< char >::int_type current = std::char_traits<char>::eof()
 the current character More...
 
bool next_unget = false
 whether the next get() call should just return current More...
 
position_t position {}
 the start position of the current token More...
 
std::vector< char > token_string {}
 raw input token string (for error messages) More...
 
string_t token_buffer {}
 buffer for variable-length tokens (numbers, strings) More...
 
const char * error_message = ""
 a description of occurred lexer errors More...
 
number_integer_t value_integer = 0
 
number_unsigned_t value_unsigned = 0
 
number_float_t value_float = 0
 
const char decimal_point_char = '.'
 the decimal point More...
 

Detailed Description

template<typename BasicJsonType>
class nlohmann::detail::lexer< BasicJsonType >

lexical analysis

This class organizes the lexical analysis during JSON deserialization.

Definition at line 7161 of file json.hpp.

Member Typedef Documentation

template<typename BasicJsonType >
using nlohmann::detail::lexer< BasicJsonType >::number_float_t = typename BasicJsonType::number_float_t
private

Definition at line 7165 of file json.hpp.

template<typename BasicJsonType >
using nlohmann::detail::lexer< BasicJsonType >::number_integer_t = typename BasicJsonType::number_integer_t
private

Definition at line 7163 of file json.hpp.

template<typename BasicJsonType >
using nlohmann::detail::lexer< BasicJsonType >::number_unsigned_t = typename BasicJsonType::number_unsigned_t
private

Definition at line 7164 of file json.hpp.

template<typename BasicJsonType >
using nlohmann::detail::lexer< BasicJsonType >::string_t = typename BasicJsonType::string_t
private

Definition at line 7166 of file json.hpp.

Member Enumeration Documentation

template<typename BasicJsonType >
enum nlohmann::detail::lexer::token_type
strong

token types for the parser

Enumerator
uninitialized 

indicating the scanner is uninitialized

literal_true 

the true literal

literal_false 

the false literal

literal_null 

the null literal

value_string 

a string – use get_string() for actual value

value_unsigned 

an unsigned integer – use get_number_unsigned() for actual value

value_integer 

a signed integer – use get_number_integer() for actual value

value_float 

an floating point number – use get_number_float() for actual value

begin_array 

the character for array begin [

begin_object 

the character for object begin {

end_array 

the character for array end ]

end_object 

the character for object end }

name_separator 

the name separator :

value_separator 

the value separator ,

parse_error 

indicating a parse error

end_of_input 

indicating the end of the input buffer

literal_or_value 

a literal or the begin of a value (only for diagnostics)

Definition at line 7170 of file json.hpp.

7171  {
7172  uninitialized, ///< indicating the scanner is uninitialized
7173  literal_true, ///< the `true` literal
7174  literal_false, ///< the `false` literal
7175  literal_null, ///< the `null` literal
7176  value_string, ///< a string -- use get_string() for actual value
7177  value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value
7178  value_integer, ///< a signed integer -- use get_number_integer() for actual value
7179  value_float, ///< an floating point number -- use get_number_float() for actual value
7180  begin_array, ///< the character for array begin `[`
7181  begin_object, ///< the character for object begin `{`
7182  end_array, ///< the character for array end `]`
7183  end_object, ///< the character for object end `}`
7184  name_separator, ///< the name separator `:`
7185  value_separator, ///< the value separator `,`
7186  parse_error, ///< indicating a parse error
7187  end_of_input, ///< indicating the end of the input buffer
7188  literal_or_value ///< a literal or the begin of a value (only for diagnostics)
7189  };
number_unsigned_t value_unsigned
Definition: json.hpp:8635
number_integer_t value_integer
Definition: json.hpp:8634
number_float_t value_float
Definition: json.hpp:8636

Constructor & Destructor Documentation

template<typename BasicJsonType >
nlohmann::detail::lexer< BasicJsonType >::lexer ( detail::input_adapter_t &&  adapter)
inlineexplicit

Definition at line 7237 of file json.hpp.

7238  : ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}
detail::input_adapter_t ia
input adapter
Definition: json.hpp:8613
const char decimal_point_char
the decimal point
Definition: json.hpp:8639
static JSON_HEDLEY_PURE char get_decimal_point() noexcept
return the locale-dependent decimal point
Definition: json.hpp:7254
template<typename BasicJsonType >
nlohmann::detail::lexer< BasicJsonType >::lexer ( const lexer< BasicJsonType > &  )
delete
template<typename BasicJsonType >
nlohmann::detail::lexer< BasicJsonType >::lexer ( lexer< BasicJsonType > &&  )
delete
template<typename BasicJsonType >
nlohmann::detail::lexer< BasicJsonType >::~lexer ( )
default

Member Function Documentation

template<typename BasicJsonType >
void nlohmann::detail::lexer< BasicJsonType >::add ( int  c)
inlineprivate

add a character to token_buffer

Definition at line 8441 of file json.hpp.

8442  {
8443  token_buffer.push_back(std::char_traits<char>::to_char_type(c));
8444  }
string_t token_buffer
buffer for variable-length tokens (numbers, strings)
Definition: json.hpp:8628
template<typename BasicJsonType >
std::char_traits<char>::int_type nlohmann::detail::lexer< BasicJsonType >::get ( )
inlineprivate

Definition at line 8377 of file json.hpp.

8378  {
8381 
8382  if (next_unget)
8383  {
8384  // just reset the next_unget variable and work with current
8385  next_unget = false;
8386  }
8387  else
8388  {
8389  current = ia->get_character();
8390  }
8391 
8392  if (JSON_HEDLEY_LIKELY(current != std::char_traits<char>::eof()))
8393  {
8394  token_string.push_back(std::char_traits<char>::to_char_type(current));
8395  }
8396 
8397  if (current == '\n')
8398  {
8399  ++position.lines_read;
8401  }
8402 
8403  return current;
8404  }
detail::input_adapter_t ia
input adapter
Definition: json.hpp:8613
std::size_t chars_read_current_line
the number of characters read in the current line
Definition: json.hpp:94
position_t position
the start position of the current token
Definition: json.hpp:8622
#define JSON_HEDLEY_LIKELY(expr)
Definition: json.hpp:1123
std::char_traits< char >::int_type current
the current character
Definition: json.hpp:8616
bool next_unget
whether the next get() call should just return current
Definition: json.hpp:8619
std::size_t lines_read
the number of lines read
Definition: json.hpp:96
std::vector< char > token_string
raw input token string (for error messages)
Definition: json.hpp:8625
std::size_t chars_read_total
the total number of characters read
Definition: json.hpp:92
template<typename BasicJsonType >
int nlohmann::detail::lexer< BasicJsonType >::get_codepoint ( )
inlineprivate

get codepoint from 4 hex characters following \u

For input "\u c1 c2 c3 c4" the codepoint is: (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4 = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)

Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f' must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The conversion is done by subtracting the offset (0x30, 0x37, and 0x57) between the ASCII value of the character and the desired integer value.

Returns
codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or non-hex character)

Definition at line 7280 of file json.hpp.

7281  {
7282  // this function only makes sense after reading `\u`
7283  assert(current == 'u');
7284  int codepoint = 0;
7285 
7286  const auto factors = { 12u, 8u, 4u, 0u };
7287  for (const auto factor : factors)
7288  {
7289  get();
7290 
7291  if (current >= '0' and current <= '9')
7292  {
7293  codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7294  }
7295  else if (current >= 'A' and current <= 'F')
7296  {
7297  codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7298  }
7299  else if (current >= 'a' and current <= 'f')
7300  {
7301  codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7302  }
7303  else
7304  {
7305  return -1;
7306  }
7307  }
7308 
7309  assert(0x0000 <= codepoint and codepoint <= 0xFFFF);
7310  return codepoint;
7311  }
return match has_match and(match.match_pdg==11 or match.match_pdg==-11)
std::char_traits< char >::int_type current
the current character
Definition: json.hpp:8616
template<typename BasicJsonType >
static JSON_HEDLEY_PURE char nlohmann::detail::lexer< BasicJsonType >::get_decimal_point ( )
inlinestaticprivatenoexcept

return the locale-dependent decimal point

Definition at line 7254 of file json.hpp.

7255  {
7256  const auto loc = localeconv();
7257  assert(loc != nullptr);
7258  return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7259  }
template<typename BasicJsonType >
JSON_HEDLEY_RETURNS_NON_NULL constexpr const char* nlohmann::detail::lexer< BasicJsonType >::get_error_message ( ) const
inlinenoexcept

return syntax error message

Definition at line 8513 of file json.hpp.

8514  {
8515  return error_message;
8516  }
const char * error_message
a description of occurred lexer errors
Definition: json.hpp:8631
template<typename BasicJsonType >
constexpr number_float_t nlohmann::detail::lexer< BasicJsonType >::get_number_float ( ) const
inlinenoexcept

return floating-point value

Definition at line 8464 of file json.hpp.

8465  {
8466  return value_float;
8467  }
number_float_t value_float
Definition: json.hpp:8636
template<typename BasicJsonType >
constexpr number_integer_t nlohmann::detail::lexer< BasicJsonType >::get_number_integer ( ) const
inlinenoexcept

return integer value

Definition at line 8452 of file json.hpp.

8453  {
8454  return value_integer;
8455  }
number_integer_t value_integer
Definition: json.hpp:8634
template<typename BasicJsonType >
constexpr number_unsigned_t nlohmann::detail::lexer< BasicJsonType >::get_number_unsigned ( ) const
inlinenoexcept

return unsigned integer value

Definition at line 8458 of file json.hpp.

8459  {
8460  return value_unsigned;
8461  }
number_unsigned_t value_unsigned
Definition: json.hpp:8635
template<typename BasicJsonType >
constexpr position_t nlohmann::detail::lexer< BasicJsonType >::get_position ( ) const
inlinenoexcept

return position of last read token

Definition at line 8480 of file json.hpp.

8481  {
8482  return position;
8483  }
position_t position
the start position of the current token
Definition: json.hpp:8622
template<typename BasicJsonType >
string_t& nlohmann::detail::lexer< BasicJsonType >::get_string ( )
inline

return current string value (implicitly resets the token; useful only once)

Definition at line 8470 of file json.hpp.

8471  {
8472  return token_buffer;
8473  }
string_t token_buffer
buffer for variable-length tokens (numbers, strings)
Definition: json.hpp:8628
template<typename BasicJsonType >
std::string nlohmann::detail::lexer< BasicJsonType >::get_token_string ( ) const
inline

return the last read token (for errors only). Will never contain EOF (an arbitrary value that is not a valid char value, often -1), because 255 may legitimately occur. May contain NUL, which should be escaped.

Definition at line 8488 of file json.hpp.

8489  {
8490  // escape control characters
8491  std::string result;
8492  for (const auto c : token_string)
8493  {
8494  if ('\x00' <= c and c <= '\x1F')
8495  {
8496  // escape control characters
8497  std::array<char, 9> cs{{}};
8498  (std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c));
8499  result += cs.data();
8500  }
8501  else
8502  {
8503  // add character as is
8504  result.push_back(c);
8505  }
8506  }
8507 
8508  return result;
8509  }
return match has_match and(match.match_pdg==11 or match.match_pdg==-11)
std::vector< char > token_string
raw input token string (for error messages)
Definition: json.hpp:8625
template<typename BasicJsonType >
bool nlohmann::detail::lexer< BasicJsonType >::next_byte_in_range ( std::initializer_list< int >  ranges)
inlineprivate

check if the next byte(s) are inside a given range

Adds the current byte and, for each passed range, reads a new byte and checks if it is inside the range. If a violation was detected, set up an error message and return false. Otherwise, return true.

Parameters
[in]rangeslist of integers; interpreted as list of pairs of inclusive lower and upper bound, respectively
Precondition
The passed list ranges must have 2, 4, or 6 elements; that is, 1, 2, or 3 pairs. This precondition is enforced by an assertion.
Returns
true if and only if no range violation was detected

Definition at line 7328 of file json.hpp.

7329  {
7330  assert(ranges.size() == 2 or ranges.size() == 4 or ranges.size() == 6);
7331  add(current);
7332 
7333  for (auto range = ranges.begin(); range != ranges.end(); ++range)
7334  {
7335  get();
7336  if (JSON_HEDLEY_LIKELY(*range <= current and current <= *(++range)))
7337  {
7338  add(current);
7339  }
7340  else
7341  {
7342  error_message = "invalid string: ill-formed UTF-8 byte";
7343  return false;
7344  }
7345  }
7346 
7347  return true;
7348  }
void add(int c)
add a character to token_buffer
Definition: json.hpp:8441
return match has_match and(match.match_pdg==11 or match.match_pdg==-11)
const char * error_message
a description of occurred lexer errors
Definition: json.hpp:8631
#define JSON_HEDLEY_LIKELY(expr)
Definition: json.hpp:1123
std::char_traits< char >::int_type current
the current character
Definition: json.hpp:8616
template<typename BasicJsonType >
lexer& nlohmann::detail::lexer< BasicJsonType >::operator= ( lexer< BasicJsonType > &  )
delete
template<typename BasicJsonType >
lexer& nlohmann::detail::lexer< BasicJsonType >::operator= ( lexer< BasicJsonType > &&  )
delete
template<typename BasicJsonType >
void nlohmann::detail::lexer< BasicJsonType >::reset ( )
inlineprivatenoexcept

reset token_buffer; current character is beginning of token

Definition at line 8360 of file json.hpp.

8361  {
8362  token_buffer.clear();
8363  token_string.clear();
8364  token_string.push_back(std::char_traits<char>::to_char_type(current));
8365  }
string_t token_buffer
buffer for variable-length tokens (numbers, strings)
Definition: json.hpp:8628
std::char_traits< char >::int_type current
the current character
Definition: json.hpp:8616
std::vector< char > token_string
raw input token string (for error messages)
Definition: json.hpp:8625
template<typename BasicJsonType >
token_type nlohmann::detail::lexer< BasicJsonType >::scan ( )
inline

Definition at line 8540 of file json.hpp.

8541  {
8542  // initially, skip the BOM
8543  if (position.chars_read_total == 0 and not skip_bom())
8544  {
8545  error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8546  return token_type::parse_error;
8547  }
8548 
8549  // read next character and ignore whitespace
8550  do
8551  {
8552  get();
8553  }
8554  while (current == ' ' or current == '\t' or current == '\n' or current == '\r');
8555 
8556  switch (current)
8557  {
8558  // structural characters
8559  case '[':
8560  return token_type::begin_array;
8561  case ']':
8562  return token_type::end_array;
8563  case '{':
8564  return token_type::begin_object;
8565  case '}':
8566  return token_type::end_object;
8567  case ':':
8569  case ',':
8571 
8572  // literals
8573  case 't':
8574  return scan_literal("true", 4, token_type::literal_true);
8575  case 'f':
8576  return scan_literal("false", 5, token_type::literal_false);
8577  case 'n':
8578  return scan_literal("null", 4, token_type::literal_null);
8579 
8580  // string
8581  case '\"':
8582  return scan_string();
8583 
8584  // number
8585  case '-':
8586  case '0':
8587  case '1':
8588  case '2':
8589  case '3':
8590  case '4':
8591  case '5':
8592  case '6':
8593  case '7':
8594  case '8':
8595  case '9':
8596  return scan_number();
8597 
8598  // end of input (the null byte is needed when parsing from
8599  // string literals)
8600  case '\0':
8601  case std::char_traits<char>::eof():
8602  return token_type::end_of_input;
8603 
8604  // error
8605  default:
8606  error_message = "invalid literal";
8607  return token_type::parse_error;
8608  }
8609  }
token_type
token types for the parser
Definition: json.hpp:7170
bool skip_bom()
skip the UTF-8 byte order mark
Definition: json.hpp:8526
the character for object begin {
position_t position
the start position of the current token
Definition: json.hpp:8622
return match has_match and(match.match_pdg==11 or match.match_pdg==-11)
const char * error_message
a description of occurred lexer errors
Definition: json.hpp:8631
std::char_traits< char >::int_type current
the current character
Definition: json.hpp:8616
the character for array begin [
token_type scan_literal(const char *literal_text, const std::size_t length, token_type return_type)
Definition: json.hpp:8340
token_type scan_number()
scan a number literal
Definition: json.hpp:8009
token_type scan_string()
scan a string literal
Definition: json.hpp:7365
std::size_t chars_read_total
the total number of characters read
Definition: json.hpp:92
template<typename BasicJsonType >
token_type nlohmann::detail::lexer< BasicJsonType >::scan_literal ( const char *  literal_text,
const std::size_t  length,
token_type  return_type 
)
inlineprivate
Parameters
[in]literal_textthe literal text to expect
[in]lengththe length of the passed literal text
[in]return_typethe token type to return on success

Definition at line 8340 of file json.hpp.

8342  {
8343  assert(current == literal_text[0]);
8344  for (std::size_t i = 1; i < length; ++i)
8345  {
8346  if (JSON_HEDLEY_UNLIKELY(get() != literal_text[i]))
8347  {
8348  error_message = "invalid literal";
8349  return token_type::parse_error;
8350  }
8351  }
8352  return return_type;
8353  }
const char * error_message
a description of occurred lexer errors
Definition: json.hpp:8631
std::char_traits< char >::int_type current
the current character
Definition: json.hpp:8616
#define JSON_HEDLEY_UNLIKELY(expr)
Definition: json.hpp:1124
template<typename BasicJsonType >
token_type nlohmann::detail::lexer< BasicJsonType >::scan_number ( )
inlineprivate

scan a number literal

This function scans a string according to Sect. 6 of RFC 7159.

The function is realized with a deterministic finite state machine derived from the grammar described in RFC 7159. Starting in state "init", the input is read and used to determined the next state. Only state "done" accepts the number. State "error" is a trap state to model errors. In the table below, "anything" means any character but the ones listed before.

state 0 1-9 e E + - . anything
init zero any1 [error] [error] minus [error] [error]
minus zero any1 [error] [error] [error] [error] [error]
zero done done exponent done done decimal1 done
any1 any1 any1 exponent done done decimal1 done
decimal1 decimal2 [error] [error] [error] [error] [error] [error]
decimal2 decimal2 decimal2 exponent done done done done
exponent any2 any2 [error] sign sign [error] [error]
sign any2 any2 [error] [error] [error] [error] [error]
any2 any2 any2 done done done done done

The state machine is realized with one label per state (prefixed with "scan_number_") and goto statements between them. The state machine contains cycles, but any cycle can be left when EOF is read. Therefore, the function is guaranteed to terminate.

During scanning, the read bytes are stored in token_buffer. This string is then converted to a signed integer, an unsigned integer, or a floating-point number.

Returns
token_type::value_unsigned, token_type::value_integer, or token_type::value_float if number could be successfully scanned, token_type::parse_error otherwise
Note
The scanner is independent of the current locale. Internally, the locale's decimal point is used instead of . to work with the locale-dependent converters.

Definition at line 8009 of file json.hpp.

8010  {
8011  // reset token_buffer to store the number's bytes
8012  reset();
8013 
8014  // the type of the parsed number; initially set to unsigned; will be
8015  // changed if minus sign, decimal point or exponent is read
8016  token_type number_type = token_type::value_unsigned;
8017 
8018  // state (init): we just found out we need to scan a number
8019  switch (current)
8020  {
8021  case '-':
8022  {
8023  add(current);
8024  goto scan_number_minus;
8025  }
8026 
8027  case '0':
8028  {
8029  add(current);
8030  goto scan_number_zero;
8031  }
8032 
8033  case '1':
8034  case '2':
8035  case '3':
8036  case '4':
8037  case '5':
8038  case '6':
8039  case '7':
8040  case '8':
8041  case '9':
8042  {
8043  add(current);
8044  goto scan_number_any1;
8045  }
8046 
8047  // all other characters are rejected outside scan_number()
8048  default: // LCOV_EXCL_LINE
8049  assert(false); // LCOV_EXCL_LINE
8050  }
8051 
8052 scan_number_minus:
8053  // state: we just parsed a leading minus sign
8054  number_type = token_type::value_integer;
8055  switch (get())
8056  {
8057  case '0':
8058  {
8059  add(current);
8060  goto scan_number_zero;
8061  }
8062 
8063  case '1':
8064  case '2':
8065  case '3':
8066  case '4':
8067  case '5':
8068  case '6':
8069  case '7':
8070  case '8':
8071  case '9':
8072  {
8073  add(current);
8074  goto scan_number_any1;
8075  }
8076 
8077  default:
8078  {
8079  error_message = "invalid number; expected digit after '-'";
8080  return token_type::parse_error;
8081  }
8082  }
8083 
8084 scan_number_zero:
8085  // state: we just parse a zero (maybe with a leading minus sign)
8086  switch (get())
8087  {
8088  case '.':
8089  {
8091  goto scan_number_decimal1;
8092  }
8093 
8094  case 'e':
8095  case 'E':
8096  {
8097  add(current);
8098  goto scan_number_exponent;
8099  }
8100 
8101  default:
8102  goto scan_number_done;
8103  }
8104 
8105 scan_number_any1:
8106  // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8107  switch (get())
8108  {
8109  case '0':
8110  case '1':
8111  case '2':
8112  case '3':
8113  case '4':
8114  case '5':
8115  case '6':
8116  case '7':
8117  case '8':
8118  case '9':
8119  {
8120  add(current);
8121  goto scan_number_any1;
8122  }
8123 
8124  case '.':
8125  {
8127  goto scan_number_decimal1;
8128  }
8129 
8130  case 'e':
8131  case 'E':
8132  {
8133  add(current);
8134  goto scan_number_exponent;
8135  }
8136 
8137  default:
8138  goto scan_number_done;
8139  }
8140 
8141 scan_number_decimal1:
8142  // state: we just parsed a decimal point
8143  number_type = token_type::value_float;
8144  switch (get())
8145  {
8146  case '0':
8147  case '1':
8148  case '2':
8149  case '3':
8150  case '4':
8151  case '5':
8152  case '6':
8153  case '7':
8154  case '8':
8155  case '9':
8156  {
8157  add(current);
8158  goto scan_number_decimal2;
8159  }
8160 
8161  default:
8162  {
8163  error_message = "invalid number; expected digit after '.'";
8164  return token_type::parse_error;
8165  }
8166  }
8167 
8168 scan_number_decimal2:
8169  // we just parsed at least one number after a decimal point
8170  switch (get())
8171  {
8172  case '0':
8173  case '1':
8174  case '2':
8175  case '3':
8176  case '4':
8177  case '5':
8178  case '6':
8179  case '7':
8180  case '8':
8181  case '9':
8182  {
8183  add(current);
8184  goto scan_number_decimal2;
8185  }
8186 
8187  case 'e':
8188  case 'E':
8189  {
8190  add(current);
8191  goto scan_number_exponent;
8192  }
8193 
8194  default:
8195  goto scan_number_done;
8196  }
8197 
8198 scan_number_exponent:
8199  // we just parsed an exponent
8200  number_type = token_type::value_float;
8201  switch (get())
8202  {
8203  case '+':
8204  case '-':
8205  {
8206  add(current);
8207  goto scan_number_sign;
8208  }
8209 
8210  case '0':
8211  case '1':
8212  case '2':
8213  case '3':
8214  case '4':
8215  case '5':
8216  case '6':
8217  case '7':
8218  case '8':
8219  case '9':
8220  {
8221  add(current);
8222  goto scan_number_any2;
8223  }
8224 
8225  default:
8226  {
8227  error_message =
8228  "invalid number; expected '+', '-', or digit after exponent";
8229  return token_type::parse_error;
8230  }
8231  }
8232 
8233 scan_number_sign:
8234  // we just parsed an exponent sign
8235  switch (get())
8236  {
8237  case '0':
8238  case '1':
8239  case '2':
8240  case '3':
8241  case '4':
8242  case '5':
8243  case '6':
8244  case '7':
8245  case '8':
8246  case '9':
8247  {
8248  add(current);
8249  goto scan_number_any2;
8250  }
8251 
8252  default:
8253  {
8254  error_message = "invalid number; expected digit after exponent sign";
8255  return token_type::parse_error;
8256  }
8257  }
8258 
8259 scan_number_any2:
8260  // we just parsed a number after the exponent or exponent sign
8261  switch (get())
8262  {
8263  case '0':
8264  case '1':
8265  case '2':
8266  case '3':
8267  case '4':
8268  case '5':
8269  case '6':
8270  case '7':
8271  case '8':
8272  case '9':
8273  {
8274  add(current);
8275  goto scan_number_any2;
8276  }
8277 
8278  default:
8279  goto scan_number_done;
8280  }
8281 
8282 scan_number_done:
8283  // unget the character after the number (we only read it to know that
8284  // we are done scanning a number)
8285  unget();
8286 
8287  char* endptr = nullptr;
8288  errno = 0;
8289 
8290  // try to parse integers first and fall back to floats
8291  if (number_type == token_type::value_unsigned)
8292  {
8293  const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8294 
8295  // we checked the number format before
8296  assert(endptr == token_buffer.data() + token_buffer.size());
8297 
8298  if (errno == 0)
8299  {
8300  value_unsigned = static_cast<number_unsigned_t>(x);
8301  if (value_unsigned == x)
8302  {
8304  }
8305  }
8306  }
8307  else if (number_type == token_type::value_integer)
8308  {
8309  const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8310 
8311  // we checked the number format before
8312  assert(endptr == token_buffer.data() + token_buffer.size());
8313 
8314  if (errno == 0)
8315  {
8316  value_integer = static_cast<number_integer_t>(x);
8317  if (value_integer == x)
8318  {
8320  }
8321  }
8322  }
8323 
8324  // this code is reached if we parse a floating-point number or if an
8325  // integer conversion above failed
8326  strtof(value_float, token_buffer.data(), &endptr);
8327 
8328  // we checked the number format before
8329  assert(endptr == token_buffer.data() + token_buffer.size());
8330 
8331  return token_type::value_float;
8332  }
number_unsigned_t value_unsigned
Definition: json.hpp:8635
token_type
token types for the parser
Definition: json.hpp:7170
process_name opflash particleana ie x
a signed integer – use get_number_integer() for actual value
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition: json.hpp:7164
number_integer_t value_integer
Definition: json.hpp:8634
typename BasicJsonType::number_integer_t number_integer_t
Definition: json.hpp:7163
string_t token_buffer
buffer for variable-length tokens (numbers, strings)
Definition: json.hpp:8628
void unget()
unget current character (read it again on next get)
Definition: json.hpp:8414
void add(int c)
add a character to token_buffer
Definition: json.hpp:8441
an unsigned integer – use get_number_unsigned() for actual value
void reset() noexcept
reset token_buffer; current character is beginning of token
Definition: json.hpp:8360
an floating point number – use get_number_float() for actual value
static void strtof(float &f, const char *str, char **endptr) noexcept
Definition: json.hpp:7952
const char decimal_point_char
the decimal point
Definition: json.hpp:8639
const char * error_message
a description of occurred lexer errors
Definition: json.hpp:8631
std::char_traits< char >::int_type current
the current character
Definition: json.hpp:8616
number_float_t value_float
Definition: json.hpp:8636
template<typename BasicJsonType >
token_type nlohmann::detail::lexer< BasicJsonType >::scan_string ( )
inlineprivate

scan a string literal

This function scans a string according to Sect. 7 of RFC 7159. While scanning, bytes are escaped and copied into buffer token_buffer. Then the function returns successfully, token_buffer is not null-terminated (as it may contain \0 bytes), and token_buffer.size() is the number of bytes in the string.

Returns
token_type::value_string if string could be successfully scanned, token_type::parse_error otherwise
Note
In case of errors, variable error_message contains a textual description.

Definition at line 7365 of file json.hpp.

7366  {
7367  // reset token_buffer (ignore opening quote)
7368  reset();
7369 
7370  // we entered the function by reading an open quote
7371  assert(current == '\"');
7372 
7373  while (true)
7374  {
7375  // get next character
7376  switch (get())
7377  {
7378  // end of file while parsing string
7379  case std::char_traits<char>::eof():
7380  {
7381  error_message = "invalid string: missing closing quote";
7382  return token_type::parse_error;
7383  }
7384 
7385  // closing quote
7386  case '\"':
7387  {
7388  return token_type::value_string;
7389  }
7390 
7391  // escapes
7392  case '\\':
7393  {
7394  switch (get())
7395  {
7396  // quotation mark
7397  case '\"':
7398  add('\"');
7399  break;
7400  // reverse solidus
7401  case '\\':
7402  add('\\');
7403  break;
7404  // solidus
7405  case '/':
7406  add('/');
7407  break;
7408  // backspace
7409  case 'b':
7410  add('\b');
7411  break;
7412  // form feed
7413  case 'f':
7414  add('\f');
7415  break;
7416  // line feed
7417  case 'n':
7418  add('\n');
7419  break;
7420  // carriage return
7421  case 'r':
7422  add('\r');
7423  break;
7424  // tab
7425  case 't':
7426  add('\t');
7427  break;
7428 
7429  // unicode escapes
7430  case 'u':
7431  {
7432  const int codepoint1 = get_codepoint();
7433  int codepoint = codepoint1; // start with codepoint1
7434 
7435  if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7436  {
7437  error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7438  return token_type::parse_error;
7439  }
7440 
7441  // check if code point is a high surrogate
7442  if (0xD800 <= codepoint1 and codepoint1 <= 0xDBFF)
7443  {
7444  // expect next \uxxxx entry
7445  if (JSON_HEDLEY_LIKELY(get() == '\\' and get() == 'u'))
7446  {
7447  const int codepoint2 = get_codepoint();
7448 
7449  if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7450  {
7451  error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7452  return token_type::parse_error;
7453  }
7454 
7455  // check if codepoint2 is a low surrogate
7456  if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF))
7457  {
7458  // overwrite codepoint
7459  codepoint = static_cast<int>(
7460  // high surrogate occupies the most significant 22 bits
7461  (static_cast<unsigned int>(codepoint1) << 10u)
7462  // low surrogate occupies the least significant 15 bits
7463  + static_cast<unsigned int>(codepoint2)
7464  // there is still the 0xD800, 0xDC00 and 0x10000 noise
7465  // in the result so we have to subtract with:
7466  // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7467  - 0x35FDC00u);
7468  }
7469  else
7470  {
7471  error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
7472  return token_type::parse_error;
7473  }
7474  }
7475  else
7476  {
7477  error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
7478  return token_type::parse_error;
7479  }
7480  }
7481  else
7482  {
7483  if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 and codepoint1 <= 0xDFFF))
7484  {
7485  error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7486  return token_type::parse_error;
7487  }
7488  }
7489 
7490  // result of the above calculation yields a proper codepoint
7491  assert(0x00 <= codepoint and codepoint <= 0x10FFFF);
7492 
7493  // translate codepoint into bytes
7494  if (codepoint < 0x80)
7495  {
7496  // 1-byte characters: 0xxxxxxx (ASCII)
7497  add(codepoint);
7498  }
7499  else if (codepoint <= 0x7FF)
7500  {
7501  // 2-byte characters: 110xxxxx 10xxxxxx
7502  add(static_cast<int>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7503  add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7504  }
7505  else if (codepoint <= 0xFFFF)
7506  {
7507  // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7508  add(static_cast<int>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7509  add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7510  add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7511  }
7512  else
7513  {
7514  // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7515  add(static_cast<int>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7516  add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7517  add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7518  add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7519  }
7520 
7521  break;
7522  }
7523 
7524  // other characters after escape
7525  default:
7526  error_message = "invalid string: forbidden character after backslash";
7527  return token_type::parse_error;
7528  }
7529 
7530  break;
7531  }
7532 
7533  // invalid control characters
7534  case 0x00:
7535  {
7536  error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7537  return token_type::parse_error;
7538  }
7539 
7540  case 0x01:
7541  {
7542  error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7543  return token_type::parse_error;
7544  }
7545 
7546  case 0x02:
7547  {
7548  error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7549  return token_type::parse_error;
7550  }
7551 
7552  case 0x03:
7553  {
7554  error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7555  return token_type::parse_error;
7556  }
7557 
7558  case 0x04:
7559  {
7560  error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7561  return token_type::parse_error;
7562  }
7563 
7564  case 0x05:
7565  {
7566  error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7567  return token_type::parse_error;
7568  }
7569 
7570  case 0x06:
7571  {
7572  error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7573  return token_type::parse_error;
7574  }
7575 
7576  case 0x07:
7577  {
7578  error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7579  return token_type::parse_error;
7580  }
7581 
7582  case 0x08:
7583  {
7584  error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7585  return token_type::parse_error;
7586  }
7587 
7588  case 0x09:
7589  {
7590  error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7591  return token_type::parse_error;
7592  }
7593 
7594  case 0x0A:
7595  {
7596  error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7597  return token_type::parse_error;
7598  }
7599 
7600  case 0x0B:
7601  {
7602  error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7603  return token_type::parse_error;
7604  }
7605 
7606  case 0x0C:
7607  {
7608  error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7609  return token_type::parse_error;
7610  }
7611 
7612  case 0x0D:
7613  {
7614  error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7615  return token_type::parse_error;
7616  }
7617 
7618  case 0x0E:
7619  {
7620  error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7621  return token_type::parse_error;
7622  }
7623 
7624  case 0x0F:
7625  {
7626  error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7627  return token_type::parse_error;
7628  }
7629 
7630  case 0x10:
7631  {
7632  error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7633  return token_type::parse_error;
7634  }
7635 
7636  case 0x11:
7637  {
7638  error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7639  return token_type::parse_error;
7640  }
7641 
7642  case 0x12:
7643  {
7644  error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7645  return token_type::parse_error;
7646  }
7647 
7648  case 0x13:
7649  {
7650  error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7651  return token_type::parse_error;
7652  }
7653 
7654  case 0x14:
7655  {
7656  error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7657  return token_type::parse_error;
7658  }
7659 
7660  case 0x15:
7661  {
7662  error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7663  return token_type::parse_error;
7664  }
7665 
7666  case 0x16:
7667  {
7668  error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7669  return token_type::parse_error;
7670  }
7671 
7672  case 0x17:
7673  {
7674  error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7675  return token_type::parse_error;
7676  }
7677 
7678  case 0x18:
7679  {
7680  error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7681  return token_type::parse_error;
7682  }
7683 
7684  case 0x19:
7685  {
7686  error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7687  return token_type::parse_error;
7688  }
7689 
7690  case 0x1A:
7691  {
7692  error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7693  return token_type::parse_error;
7694  }
7695 
7696  case 0x1B:
7697  {
7698  error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7699  return token_type::parse_error;
7700  }
7701 
7702  case 0x1C:
7703  {
7704  error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
7705  return token_type::parse_error;
7706  }
7707 
7708  case 0x1D:
7709  {
7710  error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7711  return token_type::parse_error;
7712  }
7713 
7714  case 0x1E:
7715  {
7716  error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7717  return token_type::parse_error;
7718  }
7719 
7720  case 0x1F:
7721  {
7722  error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7723  return token_type::parse_error;
7724  }
7725 
7726  // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7727  case 0x20:
7728  case 0x21:
7729  case 0x23:
7730  case 0x24:
7731  case 0x25:
7732  case 0x26:
7733  case 0x27:
7734  case 0x28:
7735  case 0x29:
7736  case 0x2A:
7737  case 0x2B:
7738  case 0x2C:
7739  case 0x2D:
7740  case 0x2E:
7741  case 0x2F:
7742  case 0x30:
7743  case 0x31:
7744  case 0x32:
7745  case 0x33:
7746  case 0x34:
7747  case 0x35:
7748  case 0x36:
7749  case 0x37:
7750  case 0x38:
7751  case 0x39:
7752  case 0x3A:
7753  case 0x3B:
7754  case 0x3C:
7755  case 0x3D:
7756  case 0x3E:
7757  case 0x3F:
7758  case 0x40:
7759  case 0x41:
7760  case 0x42:
7761  case 0x43:
7762  case 0x44:
7763  case 0x45:
7764  case 0x46:
7765  case 0x47:
7766  case 0x48:
7767  case 0x49:
7768  case 0x4A:
7769  case 0x4B:
7770  case 0x4C:
7771  case 0x4D:
7772  case 0x4E:
7773  case 0x4F:
7774  case 0x50:
7775  case 0x51:
7776  case 0x52:
7777  case 0x53:
7778  case 0x54:
7779  case 0x55:
7780  case 0x56:
7781  case 0x57:
7782  case 0x58:
7783  case 0x59:
7784  case 0x5A:
7785  case 0x5B:
7786  case 0x5D:
7787  case 0x5E:
7788  case 0x5F:
7789  case 0x60:
7790  case 0x61:
7791  case 0x62:
7792  case 0x63:
7793  case 0x64:
7794  case 0x65:
7795  case 0x66:
7796  case 0x67:
7797  case 0x68:
7798  case 0x69:
7799  case 0x6A:
7800  case 0x6B:
7801  case 0x6C:
7802  case 0x6D:
7803  case 0x6E:
7804  case 0x6F:
7805  case 0x70:
7806  case 0x71:
7807  case 0x72:
7808  case 0x73:
7809  case 0x74:
7810  case 0x75:
7811  case 0x76:
7812  case 0x77:
7813  case 0x78:
7814  case 0x79:
7815  case 0x7A:
7816  case 0x7B:
7817  case 0x7C:
7818  case 0x7D:
7819  case 0x7E:
7820  case 0x7F:
7821  {
7822  add(current);
7823  break;
7824  }
7825 
7826  // U+0080..U+07FF: bytes C2..DF 80..BF
7827  case 0xC2:
7828  case 0xC3:
7829  case 0xC4:
7830  case 0xC5:
7831  case 0xC6:
7832  case 0xC7:
7833  case 0xC8:
7834  case 0xC9:
7835  case 0xCA:
7836  case 0xCB:
7837  case 0xCC:
7838  case 0xCD:
7839  case 0xCE:
7840  case 0xCF:
7841  case 0xD0:
7842  case 0xD1:
7843  case 0xD2:
7844  case 0xD3:
7845  case 0xD4:
7846  case 0xD5:
7847  case 0xD6:
7848  case 0xD7:
7849  case 0xD8:
7850  case 0xD9:
7851  case 0xDA:
7852  case 0xDB:
7853  case 0xDC:
7854  case 0xDD:
7855  case 0xDE:
7856  case 0xDF:
7857  {
7858  if (JSON_HEDLEY_UNLIKELY(not next_byte_in_range({0x80, 0xBF})))
7859  {
7860  return token_type::parse_error;
7861  }
7862  break;
7863  }
7864 
7865  // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
7866  case 0xE0:
7867  {
7868  if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
7869  {
7870  return token_type::parse_error;
7871  }
7872  break;
7873  }
7874 
7875  // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
7876  // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
7877  case 0xE1:
7878  case 0xE2:
7879  case 0xE3:
7880  case 0xE4:
7881  case 0xE5:
7882  case 0xE6:
7883  case 0xE7:
7884  case 0xE8:
7885  case 0xE9:
7886  case 0xEA:
7887  case 0xEB:
7888  case 0xEC:
7889  case 0xEE:
7890  case 0xEF:
7891  {
7892  if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
7893  {
7894  return token_type::parse_error;
7895  }
7896  break;
7897  }
7898 
7899  // U+D000..U+D7FF: bytes ED 80..9F 80..BF
7900  case 0xED:
7901  {
7902  if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
7903  {
7904  return token_type::parse_error;
7905  }
7906  break;
7907  }
7908 
7909  // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
7910  case 0xF0:
7911  {
7912  if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7913  {
7914  return token_type::parse_error;
7915  }
7916  break;
7917  }
7918 
7919  // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
7920  case 0xF1:
7921  case 0xF2:
7922  case 0xF3:
7923  {
7924  if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7925  {
7926  return token_type::parse_error;
7927  }
7928  break;
7929  }
7930 
7931  // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
7932  case 0xF4:
7933  {
7934  if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
7935  {
7936  return token_type::parse_error;
7937  }
7938  break;
7939  }
7940 
7941  // remaining bytes (80..C1 and F5..FF) are ill-formed
7942  default:
7943  {
7944  error_message = "invalid string: ill-formed UTF-8 byte";
7945  return token_type::parse_error;
7946  }
7947  }
7948  }
7949  }
void reset() noexcept
reset token_buffer; current character is beginning of token
Definition: json.hpp:8360
return match has_match and(match.match_pdg==11 or match.match_pdg==-11)
#define JSON_HEDLEY_LIKELY(expr)
Definition: json.hpp:1123
std::char_traits< char >::int_type current
the current character
Definition: json.hpp:8616
#define JSON_HEDLEY_UNLIKELY(expr)
Definition: json.hpp:1124
template<typename BasicJsonType >
bool nlohmann::detail::lexer< BasicJsonType >::skip_bom ( )
inline

skip the UTF-8 byte order mark

Returns
true iff there is no BOM or the correct BOM has been skipped

Definition at line 8526 of file json.hpp.

8527  {
8528  if (get() == 0xEF)
8529  {
8530  // check if we completely parse the BOM
8531  return get() == 0xBB and get() == 0xBF;
8532  }
8533 
8534  // the first character is not the beginning of the BOM; unget it to
8535  // process is later
8536  unget();
8537  return true;
8538  }
void unget()
unget current character (read it again on next get)
Definition: json.hpp:8414
return match has_match and(match.match_pdg==11 or match.match_pdg==-11)
template<typename BasicJsonType >
static void nlohmann::detail::lexer< BasicJsonType >::strtof ( float &  f,
const char *  str,
char **  endptr 
)
inlinestaticprivatenoexcept

Definition at line 7952 of file json.hpp.

7953  {
7954  f = std::strtof(str, endptr);
7955  }
template<typename BasicJsonType >
static void nlohmann::detail::lexer< BasicJsonType >::strtof ( double &  f,
const char *  str,
char **  endptr 
)
inlinestaticprivatenoexcept

Definition at line 7958 of file json.hpp.

7959  {
7960  f = std::strtod(str, endptr);
7961  }
template<typename BasicJsonType >
static void nlohmann::detail::lexer< BasicJsonType >::strtof ( long double &  f,
const char *  str,
char **  endptr 
)
inlinestaticprivatenoexcept

Definition at line 7964 of file json.hpp.

7965  {
7966  f = std::strtold(str, endptr);
7967  }
template<typename BasicJsonType >
JSON_HEDLEY_RETURNS_NON_NULL static JSON_HEDLEY_CONST const char* nlohmann::detail::lexer< BasicJsonType >::token_type_name ( const token_type  t)
inlinestaticnoexcept

return name of values of type token_type (only used for errors)

Definition at line 7194 of file json.hpp.

7195  {
7196  switch (t)
7197  {
7199  return "<uninitialized>";
7201  return "true literal";
7203  return "false literal";
7205  return "null literal";
7207  return "string literal";
7211  return "number literal";
7213  return "'['";
7215  return "'{'";
7216  case token_type::end_array:
7217  return "']'";
7219  return "'}'";
7221  return "':'";
7223  return "','";
7225  return "<parse error>";
7227  return "end of input";
7229  return "'[', '{', or a literal";
7230  // LCOV_EXCL_START
7231  default: // catch non-enum values
7232  return "unknown token";
7233  // LCOV_EXCL_STOP
7234  }
7235  }
a signed integer – use get_number_integer() for actual value
a string – use get_string() for actual value
the character for object begin {
an unsigned integer – use get_number_unsigned() for actual value
an floating point number – use get_number_float() for actual value
the character for array begin [
a literal or the begin of a value (only for diagnostics)
indicating the scanner is uninitialized
indicating the end of the input buffer
template<typename BasicJsonType >
void nlohmann::detail::lexer< BasicJsonType >::unget ( )
inlineprivate

unget current character (read it again on next get)

We implement unget by setting variable next_unget to true. The input is not changed - we just simulate ungetting by modifying chars_read_total, chars_read_current_line, and token_string. The next call to get() will behave as if the unget character is read again.

Definition at line 8414 of file json.hpp.

8415  {
8416  next_unget = true;
8417 
8419 
8420  // in case we "unget" a newline, we have to also decrement the lines_read
8422  {
8423  if (position.lines_read > 0)
8424  {
8425  --position.lines_read;
8426  }
8427  }
8428  else
8429  {
8431  }
8432 
8433  if (JSON_HEDLEY_LIKELY(current != std::char_traits<char>::eof()))
8434  {
8435  assert(not token_string.empty());
8436  token_string.pop_back();
8437  }
8438  }
std::size_t chars_read_current_line
the number of characters read in the current line
Definition: json.hpp:94
position_t position
the start position of the current token
Definition: json.hpp:8622
#define JSON_HEDLEY_LIKELY(expr)
Definition: json.hpp:1123
std::char_traits< char >::int_type current
the current character
Definition: json.hpp:8616
bool next_unget
whether the next get() call should just return current
Definition: json.hpp:8619
std::size_t lines_read
the number of lines read
Definition: json.hpp:96
std::vector< char > token_string
raw input token string (for error messages)
Definition: json.hpp:8625
std::size_t chars_read_total
the total number of characters read
Definition: json.hpp:92

Member Data Documentation

template<typename BasicJsonType >
std::char_traits<char>::int_type nlohmann::detail::lexer< BasicJsonType >::current = std::char_traits<char>::eof()
private

the current character

Definition at line 8616 of file json.hpp.

template<typename BasicJsonType >
const char nlohmann::detail::lexer< BasicJsonType >::decimal_point_char = '.'
private

the decimal point

Definition at line 8639 of file json.hpp.

template<typename BasicJsonType >
const char* nlohmann::detail::lexer< BasicJsonType >::error_message = ""
private

a description of occurred lexer errors

Definition at line 8631 of file json.hpp.

template<typename BasicJsonType >
detail::input_adapter_t nlohmann::detail::lexer< BasicJsonType >::ia = nullptr
private

input adapter

Definition at line 8613 of file json.hpp.

template<typename BasicJsonType >
bool nlohmann::detail::lexer< BasicJsonType >::next_unget = false
private

whether the next get() call should just return current

Definition at line 8619 of file json.hpp.

template<typename BasicJsonType >
position_t nlohmann::detail::lexer< BasicJsonType >::position {}
private

the start position of the current token

Definition at line 8622 of file json.hpp.

template<typename BasicJsonType >
string_t nlohmann::detail::lexer< BasicJsonType >::token_buffer {}
private

buffer for variable-length tokens (numbers, strings)

Definition at line 8628 of file json.hpp.

template<typename BasicJsonType >
std::vector<char> nlohmann::detail::lexer< BasicJsonType >::token_string {}
private

raw input token string (for error messages)

Definition at line 8625 of file json.hpp.

template<typename BasicJsonType >
number_float_t nlohmann::detail::lexer< BasicJsonType >::value_float = 0
private

Definition at line 8636 of file json.hpp.

template<typename BasicJsonType >
number_integer_t nlohmann::detail::lexer< BasicJsonType >::value_integer = 0
private

Definition at line 8634 of file json.hpp.

template<typename BasicJsonType >
number_unsigned_t nlohmann::detail::lexer< BasicJsonType >::value_unsigned = 0
private

Definition at line 8635 of file json.hpp.


The documentation for this class was generated from the following file: