1 #ifndef GENESIS_UTILS_IO_INPUT_STREAM_H_
2 #define GENESIS_UTILS_IO_INPUT_STREAM_H_
104 : source_name_(
"invalid source" )
113 explicit InputStream( std::shared_ptr<BaseInputSource> input_source )
117 init_( input_source );
130 *
this = std::move( other );
165 throw std::runtime_error(
170 throw std::domain_error(
171 "Invalid input char in " +
source_name() +
" at " +
at() +
"."
204 if( current_ ==
'\n' ) {
243 void get_line( std::string& target );
275 throw std::runtime_error(
277 "Expecting " +
char_to_hex( criterion ) +
" at " +
at() +
", " +
278 "but received " +
char_to_hex( current_ ) +
" instead."
281 assert(
good() && current_ == criterion );
298 throw std::runtime_error(
300 "Unexpected char " +
char_to_hex( current_ ) +
" at " +
at() +
"."
304 auto const chr = current_;
316 #if defined(__GNUC__) || defined(__GNUG__) || defined(__clang__)
322 size_t parse_unsigned_integer_gcc_intrinsic_();
328 size_t parse_unsigned_integer_from_chars_();
333 #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
339 size_t parse_unsigned_integer_std_from_chars_();
346 size_t parse_unsigned_integer_naive_();
351 size_t parse_unsigned_integer_size_t_();
376 auto const x = parse_unsigned_integer_size_t_();
380 auto const r =
static_cast<T
>(x);
381 if(
static_cast<size_t>(r) != x || r < 0 ) {
382 throw std::overflow_error(
383 "Numerical overflow in " +
source_name() +
" at " +
at() +
"."
402 std::is_signed<T>::value,
403 "Need signed type for parse_signed_integer()"
406 if( data_pos_ >= data_end_ ) {
407 throw std::runtime_error(
413 if( current_ ==
'-' || current_ ==
'+' ) {
414 if( current_ ==
'-' ) {
421 assert( data_pos_ < data_end_ );
422 assert( current_ !=
'\n' );
425 current_ = buffer_[ data_pos_ ];
433 auto const x = parse_unsigned_integer_size_t_();
434 auto const r = sign *
static_cast<T
>(x);
435 if(
static_cast<size_t>( sign * r ) != x || !( r == 0 || (sign < 0) == (r < 0) )) {
436 throw std::overflow_error(
437 "Numerical overflow in " +
source_name() +
" at " +
at() +
"."
449 return parse_signed_integer<T>();
481 std::string
at()
const
491 return data_pos_ < data_end_;
498 inline explicit operator bool()
const
500 return data_pos_ < data_end_;
508 return data_pos_ >= data_end_;
547 assert( data_pos_ <= data_end_ );
548 return { &buffer_[ data_pos_ ], data_end_ - data_pos_ };
564 if( data_pos_ + n >= data_end_ ) {
565 throw std::runtime_error(
566 "Invalid InputStream jump to position after buffer end."
588 void init_( std::shared_ptr<BaseInputSource> input_source );
603 void update_blocks_();
609 inline void set_current_char_()
615 assert( data_pos_ == data_end_ );
617 if( data_pos_ == data_end_ && data_pos_ > 0 && buffer_[ data_pos_ - 1 ] !=
'\n' ) {
619 buffer_[ data_pos_ ] =
'\n';
631 if( buffer_[ data_pos_ ] ==
'\r' ) {
632 buffer_[ data_pos_ ] =
'\n';
637 if( data_pos_ + 1 < data_end_ && buffer_[ data_pos_ + 1 ] ==
'\n' ) {
643 current_ = buffer_[ data_pos_ ];
654 std::unique_ptr<InputReader> input_reader_ =
nullptr;
655 std::string source_name_;
680 inline size_t InputStream::parse_unsigned_integer<size_t>()
682 return parse_unsigned_integer_size_t_();
688 #endif // include guard