.. _program_listing_file__tmp_ws_src_ecl_core_ecl_streams_include_ecl_streams_text_streams_input_text_stream.hpp: Program Listing for File input_text_stream.hpp ============================================== |exhale_lsh| :ref:`Return to documentation for file ` (``/tmp/ws/src/ecl_core/ecl_streams/include/ecl/streams/text_streams/input_text_stream.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp /***************************************************************************** ** Ifdefs *****************************************************************************/ #ifndef ECL_STREAMS_INPUT_TEXT_STREAM_HPP_ #define ECL_STREAMS_INPUT_TEXT_STREAM_HPP_ /***************************************************************************** ** Includes *****************************************************************************/ #include #include #include #include #include #include #include #include #include "base_text_stream.hpp" #include "../macros.hpp" /***************************************************************************** ** Namespaces *****************************************************************************/ namespace ecl { namespace interfaces { /***************************************************************************** ** Interface [InputTextStream] *****************************************************************************/ template class ECL_PUBLIC InputTextStream { }; template class ECL_PUBLIC InputTextStream : public virtual BaseTextStream { public: /********************* ** Constructors **********************/ InputTextStream(); virtual ~InputTextStream() {} /********************* ** Streaming Operators **********************/ InputTextStream& operator >> ( char &c ); InputTextStream& operator >> ( std::string &s ); InputTextStream& operator >> ( short &i ); InputTextStream& operator >> ( int &i ); InputTextStream& operator >> ( long &i ); InputTextStream& operator >> ( unsigned char &c ); InputTextStream& operator >> ( unsigned short &i ); InputTextStream& operator >> ( unsigned int &i ); InputTextStream& operator >> ( unsigned long &i ); InputTextStream& operator >> ( float &f ); InputTextStream& operator >> ( double &d ); InputTextStream& operator >> ( long long &i ); InputTextStream& operator >> ( unsigned long long &i ); InputTextStream& operator >> ( bool &b ); /********************* ** Non-Streaming API **********************/ void enableRawCharReads(); void disableRawCharReads(); private: bool raw_char_reads; /********************* ** Private Parsers **********************/ bool skipLeadingWhiteSpace(char &c); template bool getIntegerFromStream(Number &i); template bool parseHexInteger(Number &i); template bool getFloatFromStream(Number &f); }; /***************************************************************************** ** Implementation [InputTextStream] *****************************************************************************/ template InputTextStream::InputTextStream() : raw_char_reads(false) { ecl_compile_time_concept_check(ecl::InputCharDeviceConcept); } /***************************************************************************** ** Implementation [InputTextStream][Streaming Operators] *****************************************************************************/ template InputTextStream & InputTextStream::operator >> ( char &c ) { ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open.")); if ( !raw_char_reads ) { if( skipLeadingWhiteSpace(c) ) { this->error = NoError; } else { this->error = ReadError; } } else { if ( this->io_device.read(c) == 1 ) { this->error = NoError; } else { this->error = ReadError; } } return *this; } template InputTextStream& InputTextStream::operator >> ( std::string &s ) { ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open.")); char c; if ( skipLeadingWhiteSpace(c) ) { s.clear(); do { s.push_back(c); if( this->io_device.read(c) < 1 ) { this->error = ReadError; break; } } while ( ( c != ' ' ) && ( c != '\n' ) ); this->error = NoError; } else { this->error = ReadError; } // Original method - reads a whole line (must be terminated by a \n) // static char buffer[80]; // this->io_device.read(&buffer[0],80); // s.assign(buffer); return *this; } template InputTextStream& InputTextStream::operator >> ( short &i ) { ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open.")); if ( getIntegerFromStream(i) ) { this->error = NoError; } // Real errors are handled internally in getIntegerFromStreams return *this; } template InputTextStream& InputTextStream::operator >> ( int &i ) { ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open.")); if ( getIntegerFromStream(i) ) { this->error = NoError; } // Real errors are handled internally in getIntegerFromStreams return *this; } template InputTextStream& InputTextStream::operator >> ( long &i ) { ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open.")); if ( getIntegerFromStream(i) ) { this->error = NoError; } // Real errors are handled internally in getIntegerFromStreams return *this; } template InputTextStream& InputTextStream::operator >> ( long long &i ) { ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open.")); if ( getIntegerFromStream(i) ) { this->error = NoError; } // Real errors are handled internally in getIntegerFromStreams return *this; } template InputTextStream& InputTextStream::operator >> ( unsigned char &uc ) { ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open.")); if ( getIntegerFromStream(uc) ) { this->error = NoError; } // Real errors are handled internally in getIntegerFromStreams return *this; } template InputTextStream& InputTextStream::operator >> ( unsigned short &i ) { ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open.")); if ( getIntegerFromStream(i) ) { this->error = NoError; } // Real errors are handled internally in getIntegerFromStreams return *this; } template InputTextStream& InputTextStream::operator >> ( unsigned int &i ) { ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open.")); if ( getIntegerFromStream(i) ) { this->error = NoError; } // Real errors are handled internally in getIntegerFromStreams return *this; } template InputTextStream& InputTextStream::operator >> ( unsigned long &i ) { ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open.")); if ( getIntegerFromStream(i) ) { this->error = NoError; } // Real errors are handled internally in getIntegerFromStreams return *this; } template InputTextStream& InputTextStream::operator >> ( unsigned long long &i ) { ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open.")); if ( getIntegerFromStream(i) ) { this->error = NoError; } // Real errors are handled internally in getIntegerFromStreams return *this; } template InputTextStream& InputTextStream::operator >> ( float &f ) { ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open.")); if ( getFloatFromStream(f) ) { this->error = NoError; } // Real errors are handled internally in getFloatFromStreams return *this; } template InputTextStream& InputTextStream::operator >> ( double &d ) { ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open.")); if ( getFloatFromStream(d) ) { this->error = NoError; } // Real errors are handled internally in getFloatFromStreams return *this; } template InputTextStream& InputTextStream::operator >> ( bool &b ) { ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open.")); std::string s; *this >> s; if ( this->fail() ) { // string could not be read return *this; // error already set } if ( ( s == "true" ) || ( s == "TRUE" ) || ( s == "True" ) ) { b = true; this->error = NoError; } else if ( ( s == "false" ) || ( s == "FALSE" ) || ( s == "False" ) ) { b = false; this->error = NoError; } else { this->error = ConversionError; } return *this; } /***************************************************************************** ** Implementation [InputTextStream][Non-Streaming Interface] *****************************************************************************/ template void InputTextStream::enableRawCharReads() { raw_char_reads = true; } template void InputTextStream::disableRawCharReads() { raw_char_reads = false; } /***************************************************************************** ** Implementation [InputTextStream][Private Parsers] *****************************************************************************/ template bool InputTextStream::skipLeadingWhiteSpace(char &c) { do { if( this->io_device.read(c) < 1 ) { // Fail if either there is a read error OR there is nothing in the device. this->error = ReadError; return false; } } while ( ( c == ' ' ) || ( c == '\n' ) ); return true; } template template bool InputTextStream::parseHexInteger(Number &i) { char c; static int digits[25]; static const short ceiling = numeric_limits::maximum/10; i = 0; int j = 0; while ( j < 25 ) { long n = this->io_device.read(c); if ( n < 0 ) { this->error = ReadError; return false; } else if ( n == 0 ) { break; // nothing more to read. } if ( ( c >= '0' ) && ( c <= '9') ) { digits[j] = c - '0'; } else if ( ( c >= 'a' ) && ( c <= 'f') ) { digits[j] = 10 + c - 'a'; } else if ( ( c >= 'A' ) && ( c <= 'F') ) { digits[j] = 10 + c - 'A'; } else { break; // No more valid characters to read. } ++j; } if ( j == 0 ) { this->error = ReadError; return false; } short number = 0; for ( int k = 0; k < j; ++k ) { if ( number < ceiling ) { number = 16*number + (digits[k]); } else { this->error = OutOfRangeError; return false; } } i = number; return true; } template template bool InputTextStream::getIntegerFromStream(Number &i) { static char digits[25]; // 20 is the maximum needed on a 64 bit system for a long type static const Number ceiling = ecl::numeric_limits::maximum/10; char c = ' '; Number sign_multiplier = 1; Number number; if ( !skipLeadingWhiteSpace(c) ) { return false; } if ( c == '-' ) { // Negative if ( std::numeric_limits::min() != 0 ) { sign_multiplier = -1; if ( this->io_device.read(c) < 1 ) { this->error = ReadError; return false; } } // else do nothing and continue, an error will be found at the next step. } else if ( c == '+' ) { // Positive if ( this->io_device.read(c) < 1 ) { this->error = ReadError; return false; } } else if ( c == '0' ) { long n = this->io_device.read(c); if ( ( n == 0 ) || ( c == ' ' ) || ( c == '\n' ) ) { // It's just a single zero. i = 0; return true; } else if ( n < 0 ) { this->error = ReadError; return false; } else if ( c == 'x' ) { return parseHexInteger(i); } else { // its a regular integer, just continue } } else if ( c == 'x' ) { return parseHexInteger(i); } /********************* ** Parse reg. integer **********************/ int j = 0; while ( ( c >= '0' ) && ( c <= '9') && ( j < 25 ) ) { digits[j] = c; j++; long n = this->io_device.read(c); if ( n < 0 ) { this->error = ReadError; return false; } else if ( n == 0 ) { break; } else { // n > 1 } } if ( j == 0 ) { this->error = ConversionError; return false; } number = 0; for ( int k = 0; k < j; ++k ) { if ( number < ceiling ) { number = 10*number + (digits[k] - '0'); } else { this->error = OutOfRangeError; return false; } } i = sign_multiplier*number; return true; } template template bool InputTextStream::getFloatFromStream(Number &f) { static const int bufferSize = 25; static char digits[bufferSize]; // 20 is the maximum needed on a 64 bit system for a long type char c = ' '; int integral_length = 0; int decimal_length = 0; Number sign_multiplier = 1; Number number; if ( !skipLeadingWhiteSpace(c) ) { return false; } if ( c == '-' ) { sign_multiplier = -1; if ( this->io_device.read(c) < 1 ) { this->error = ReadError; return false; } } else if ( c == '+' ) { if ( this->io_device.read(c) < 1 ) { this->error = ReadError; return false; } } number = 0; /****************************************** ** Integral part *******************************************/ while ( ( c >= '0' ) && ( c <= '9') && ( integral_length < bufferSize ) ) { digits[integral_length] = c; long n = this->io_device.read(c); if ( n < 0 ) { this->error = ReadError; return false; } else if ( n == 0 ) { break; } else { // n > 1 integral_length++; } } for ( int k = 0; k < integral_length; ++k ) { number = 10*number + (digits[k] - '0'); } if ( c == '.' ) { float frac_multiplier = 1; if ( this->io_device.read(c) < 1 ) { this->error = ReadError; return false; } /****************************************** ** Decimal part *******************************************/ while ( ( c >= '0' ) && ( c <= '9') && ( decimal_length < bufferSize ) ) { digits[decimal_length] = c; long n = this->io_device.read(c); if ( n < 0 ) { this->error = ReadError; return false; } else if ( n == 0 ) { break; } else { // n > 1 decimal_length++; } } for ( int k = 0; k < decimal_length; ++k ) { frac_multiplier *= 0.1f; number = number + frac_multiplier*(digits[k] - '0'); } } if ( (integral_length+decimal_length) == 0 ) { this->error = ConversionError; return false; } f = sign_multiplier*number; return true; } } // namespace interfaces } // namespace ecl #endif /* ECL_STREAMS_INPUT_TEXT_STREAM_HPP_ */