| 6048 | */ |
| 6049 | template<typename BasicJsonType, typename InputAdapterType> |
| 6050 | class lexer : public lexer_base<BasicJsonType> |
| 6051 | { |
| 6052 | using number_integer_t = typename BasicJsonType::number_integer_t; |
| 6053 | using number_unsigned_t = typename BasicJsonType::number_unsigned_t; |
| 6054 | using number_float_t = typename BasicJsonType::number_float_t; |
| 6055 | using string_t = typename BasicJsonType::string_t; |
| 6056 | using char_type = typename InputAdapterType::char_type; |
| 6057 | using char_int_type = typename std::char_traits<char_type>::int_type; |
| 6058 | |
| 6059 | public: |
| 6060 | using token_type = typename lexer_base<BasicJsonType>::token_type; |
| 6061 | |
| 6062 | explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) |
| 6063 | : ia(std::move(adapter)) |
| 6064 | , ignore_comments(ignore_comments_) |
| 6065 | , decimal_point_char(static_cast<char_int_type>(get_decimal_point())) |
| 6066 | {} |
| 6067 | |
| 6068 | // delete because of pointer members |
| 6069 | lexer(const lexer&) = delete; |
| 6070 | lexer(lexer&&) = default; |
| 6071 | lexer& operator=(lexer&) = delete; |
| 6072 | lexer& operator=(lexer&&) = default; |
| 6073 | ~lexer() = default; |
| 6074 | |
| 6075 | private: |
| 6076 | ///////////////////// |
| 6077 | // locales |
| 6078 | ///////////////////// |
| 6079 | |
| 6080 | /// return the locale-dependent decimal point |
| 6081 | JSON_HEDLEY_PURE |
| 6082 | static char get_decimal_point() noexcept |
| 6083 | { |
| 6084 | const auto* loc = localeconv(); |
| 6085 | JSON_ASSERT(loc != nullptr); |
| 6086 | return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point); |
| 6087 | } |
| 6088 | |
| 6089 | ///////////////////// |
| 6090 | // scan functions |
| 6091 | ///////////////////// |
| 6092 | |
| 6093 | /*! |
| 6094 | @brief get codepoint from 4 hex characters following `\u` |
| 6095 | |
| 6096 | For input "\u c1 c2 c3 c4" the codepoint is: |
| 6097 | (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4 |
| 6098 | = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0) |
| 6099 | |
| 6100 | Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f' |
| 6101 | must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The |
| 6102 | conversion is done by subtracting the offset (0x30, 0x37, and 0x57) |
| 6103 | between the ASCII value of the character and the desired integer value. |
| 6104 | |
| 6105 | @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or |
| 6106 | non-hex character) |
| 6107 | */ |