// Copyright (c) 2018-2020 Dr. Colin Hirsch and Daniel Frey // Please see LICENSE for license or visit https://github.com/taocpp/json/ #ifndef TAO_JSON_INTERNAL_PARSE_UTIL_HPP #define TAO_JSON_INTERNAL_PARSE_UTIL_HPP #include #include "../external/pegtl/parse_error.hpp" #include "../utf8.hpp" #include "endian.hpp" #include "format.hpp" #ifdef _MSC_VER #pragma warning( push ) #pragma warning( disable : 4702 ) #endif namespace tao::json::internal { template< typename Input > void throw_on_empty( Input& in ) { if( in.empty() ) { throw pegtl::parse_error( format( "unexpected end of input" ), in ); } } template< typename Input > void throw_on_empty( Input& in, const std::size_t required ) { const auto available = in.size( required ); if( available < required ) { throw pegtl::parse_error( format( "unexpected end of input -- required ", required, " available ", available ), in ); } } template< typename Input > [[nodiscard]] std::uint8_t peek_uint8( Input& in ) { throw_on_empty( in ); return in.peek_uint8(); } template< typename Input > [[nodiscard]] char peek_char( Input& in ) { throw_on_empty( in ); return in.peek_char(); } template< typename Input > [[nodiscard]] char read_char_unsafe( Input& in ) { const auto r = in.peek_char(); in.bump_in_this_line( 1 ); return r; } template< typename Input > [[nodiscard]] char read_char( Input& in ) { throw_on_empty( in ); return read_char_unsafe( in ); } template< utf8_mode U, typename Result, typename Input > [[nodiscard]] Result read_string( Input& in, const std::size_t size ) { using value_t = typename Result::value_type; json::internal::throw_on_empty( in, size ); const auto* pointer = reinterpret_cast< const value_t* >( in.current() ); const Result result( pointer, size ); json::internal::consume_utf8_throws< U >( in, size ); return result; } template< typename Result, typename Number = Result, typename Input > [[nodiscard]] Result read_big_endian_number( Input& in, const std::size_t extra = 0 ) { throw_on_empty( in, extra + sizeof( Number ) ); const auto result = static_cast< Result >( be_to_h< Number >( in.current() + extra ) ); in.bump_in_this_line( extra + sizeof( Number ) ); return result; } template< typename Integer > [[nodiscard]] Integer hex_char_to_integer( const char c ) noexcept { if( ( '0' <= c ) && ( c <= '9' ) ) { return static_cast< Integer >( c - '0' ); } if( ( 'a' <= c ) && ( c <= 'f' ) ) { return static_cast< Integer >( c - 'a' + 10 ); } if( ( 'A' <= c ) && ( c <= 'F' ) ) { return static_cast< Integer >( c - 'A' + 10 ); } // LCOV_EXCL_START assert( false ); return 0; // LCOV_EXCL_STOP } } // namespace tao::json::internal #ifdef _MSC_VER #pragma warning( pop ) #endif #endif