00001
00011
00012
00013
00014
00015 #ifndef ECL_STREAMS_INPUT_TEXT_STREAM_HPP_
00016 #define ECL_STREAMS_INPUT_TEXT_STREAM_HPP_
00017
00018
00019
00020
00021
00022 #include <iostream>
00023 #include <limits>
00024 #include <string>
00025 #include <ecl/config/macros.hpp>
00026 #include <ecl/config/portable_types.hpp>
00027 #include <ecl/exceptions/standard_exception.hpp>
00028 #include <ecl/concepts/devices.hpp>
00029 #include <ecl/type_traits/numeric_limits.hpp>
00030 #include "base_text_stream.hpp"
00031 #include "../macros.hpp"
00032
00033
00034
00035
00036
00037 namespace ecl {
00038 namespace interfaces {
00039
00040
00041
00042
00043
00056 template <typename Device, bool InputDevice = true >
00057 class ECL_PUBLIC InputTextStream {
00058 };
00059
00086 template <typename Device>
00087 class ECL_PUBLIC InputTextStream<Device,true> : public virtual BaseTextStream<Device> {
00088 public:
00089
00090
00091
00092 InputTextStream();
00093 virtual ~InputTextStream() {}
00094
00095
00096
00097
00098 InputTextStream<Device>& operator >> ( char &c ) ecl_assert_throw_decl(ecl::StandardException);
00099 InputTextStream<Device>& operator >> ( std::string &s ) ecl_assert_throw_decl(ecl::StandardException);
00100 InputTextStream<Device>& operator >> ( short &i ) ecl_assert_throw_decl(ecl::StandardException);
00101 InputTextStream<Device>& operator >> ( int &i ) ecl_assert_throw_decl(ecl::StandardException);
00102 InputTextStream<Device>& operator >> ( long &i ) ecl_assert_throw_decl(ecl::StandardException);
00103 InputTextStream<Device>& operator >> ( unsigned char &c ) ecl_assert_throw_decl(ecl::StandardException);
00104 InputTextStream<Device>& operator >> ( unsigned short &i ) ecl_assert_throw_decl(ecl::StandardException);
00105 InputTextStream<Device>& operator >> ( unsigned int &i ) ecl_assert_throw_decl(ecl::StandardException);
00106 InputTextStream<Device>& operator >> ( unsigned long &i ) ecl_assert_throw_decl(ecl::StandardException);
00107 InputTextStream<Device>& operator >> ( float &f ) ecl_assert_throw_decl(ecl::StandardException);
00108 InputTextStream<Device>& operator >> ( double &d ) ecl_assert_throw_decl(ecl::StandardException);
00109 InputTextStream<Device>& operator >> ( long long &i ) ecl_assert_throw_decl(ecl::StandardException);
00110 InputTextStream<Device>& operator >> ( unsigned long long &i ) ecl_assert_throw_decl(ecl::StandardException);
00111 InputTextStream<Device>& operator >> ( bool &b ) ecl_assert_throw_decl(ecl::StandardException);
00112
00113
00114
00115
00116 void enableRawCharReads();
00117 void disableRawCharReads();
00118
00119 private:
00120 bool raw_char_reads;
00121
00122
00123
00124
00125 bool skipLeadingWhiteSpace(char &c);
00126 template <typename Number>
00127 bool getIntegerFromStream(Number &i);
00128 template <typename Number>
00129 bool parseHexInteger(Number &i);
00130 template <typename Number>
00131 bool getFloatFromStream(Number &f);
00132 };
00133
00134
00135
00136
00147 template <typename Device>
00148 InputTextStream<Device,true>::InputTextStream() : raw_char_reads(false) {
00149 ecl_compile_time_concept_check(ecl::InputCharDeviceConcept<Device>);
00150 }
00151
00152
00153
00154
00165 template <typename Device>
00166 InputTextStream<Device> & InputTextStream<Device,true>::operator >> ( char &c ) ecl_assert_throw_decl(ecl::StandardException) {
00167
00168 ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open."));
00169
00170 if ( !raw_char_reads ) {
00171 if( skipLeadingWhiteSpace(c) ) {
00172 this->error = NoError;
00173 } else {
00174 this->error = ReadError;
00175 }
00176 } else {
00177 if ( this->io_device.read(c) == 1 ) {
00178 this->error = NoError;
00179 } else {
00180 this->error = ReadError;
00181 }
00182 }
00183 return *this;
00184 }
00185
00197 template <typename Device>
00198 InputTextStream<Device>& InputTextStream<Device,true>::operator >> ( std::string &s ) ecl_assert_throw_decl(ecl::StandardException) {
00199
00200 ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open."));
00201
00202 char c;
00203 if ( skipLeadingWhiteSpace(c) ) {
00204 s.clear();
00205 do {
00206 s.push_back(c);
00207 if( this->io_device.read(c) < 1 ) {
00208 this->error = ReadError;
00209 break;
00210 }
00211 } while ( ( c != ' ' ) && ( c != '\n' ) );
00212 this->error = NoError;
00213 } else {
00214 this->error = ReadError;
00215 }
00216
00217
00218
00219
00220
00221 return *this;
00222 }
00223
00232 template <typename Device>
00233 InputTextStream<Device>& InputTextStream<Device,true>::operator >> ( short &i ) ecl_assert_throw_decl(ecl::StandardException) {
00234
00235 ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open."));
00236
00237 if ( getIntegerFromStream(i) ) {
00238 this->error = NoError;
00239 }
00240
00241 return *this;
00242 }
00243
00252 template <typename Device>
00253 InputTextStream<Device>& InputTextStream<Device,true>::operator >> ( int &i ) ecl_assert_throw_decl(ecl::StandardException) {
00254
00255 ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open."));
00256 if ( getIntegerFromStream(i) ) {
00257 this->error = NoError;
00258 }
00259 return *this;
00260 }
00261
00270 template <typename Device>
00271 InputTextStream<Device>& InputTextStream<Device,true>::operator >> ( long &i ) ecl_assert_throw_decl(ecl::StandardException) {
00272
00273 ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open."));
00274 if ( getIntegerFromStream(i) ) {
00275 this->error = NoError;
00276 }
00277 return *this;
00278 }
00287 template <typename Device>
00288 InputTextStream<Device>& InputTextStream<Device,true>::operator >> ( long long &i ) ecl_assert_throw_decl(ecl::StandardException) {
00289
00290 ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open."));
00291 if ( getIntegerFromStream(i) ) {
00292 this->error = NoError;
00293 }
00294 return *this;
00295 }
00306 template <typename Device>
00307 InputTextStream<Device>& InputTextStream<Device,true>::operator >> ( unsigned char &uc ) ecl_assert_throw_decl(ecl::StandardException) {
00308
00309 ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open."));
00310 if ( getIntegerFromStream(uc) ) {
00311 this->error = NoError;
00312 }
00313 return *this;
00314 }
00315
00324 template <typename Device>
00325 InputTextStream<Device>& InputTextStream<Device,true>::operator >> ( unsigned short &i ) ecl_assert_throw_decl(ecl::StandardException) {
00326
00327 ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open."));
00328 if ( getIntegerFromStream(i) ) {
00329 this->error = NoError;
00330 }
00331 return *this;
00332 }
00333
00342 template <typename Device>
00343 InputTextStream<Device>& InputTextStream<Device,true>::operator >> ( unsigned int &i ) ecl_assert_throw_decl(ecl::StandardException) {
00344
00345 ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open."));
00346 if ( getIntegerFromStream(i) ) {
00347 this->error = NoError;
00348 }
00349 return *this;
00350 }
00351
00360 template <typename Device>
00361 InputTextStream<Device>& InputTextStream<Device,true>::operator >> ( unsigned long &i ) ecl_assert_throw_decl(ecl::StandardException) {
00362
00363 ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open."));
00364 if ( getIntegerFromStream(i) ) {
00365 this->error = NoError;
00366 }
00367 return *this;
00368 }
00369
00378 template <typename Device>
00379 InputTextStream<Device>& InputTextStream<Device,true>::operator >> ( unsigned long long &i ) ecl_assert_throw_decl(ecl::StandardException) {
00380
00381 ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open."));
00382 if ( getIntegerFromStream(i) ) {
00383 this->error = NoError;
00384 }
00385 return *this;
00386 }
00387
00388
00397 template <typename Device>
00398 InputTextStream<Device>& InputTextStream<Device,true>::operator >> ( float &f ) ecl_assert_throw_decl(ecl::StandardException) {
00399
00400 ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open."));
00401 if ( getFloatFromStream(f) ) {
00402 this->error = NoError;
00403 }
00404 return *this;
00405 }
00406
00415 template <typename Device>
00416 InputTextStream<Device>& InputTextStream<Device,true>::operator >> ( double &d ) ecl_assert_throw_decl(ecl::StandardException) {
00417
00418 ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open."));
00419 if ( getFloatFromStream(d) ) {
00420 this->error = NoError;
00421 }
00422 return *this;
00423 }
00424
00435 template <typename Device>
00436 InputTextStream<Device>& InputTextStream<Device,true>::operator >> ( bool &b ) ecl_assert_throw_decl(ecl::StandardException)
00437 {
00438 ecl_assert_throw(this->io_device.open(),ecl::StandardException(LOC,OpenError,"The underlying stream device is not open."));
00439 std::string s;
00440 *this >> s;
00441
00442 if ( this->fail() ) {
00443 return *this;
00444 }
00445
00446 if ( ( s == "true" ) || ( s == "TRUE" ) || ( s == "True" ) ) {
00447 b = true;
00448 this->error = NoError;
00449 } else if ( ( s == "false" ) || ( s == "FALSE" ) || ( s == "False" ) ) {
00450 b = false;
00451 this->error = NoError;
00452 } else {
00453 this->error = ConversionError;
00454 }
00455 return *this;
00456 }
00457
00458
00459
00460
00461
00474 template <typename Device>
00475 void InputTextStream<Device,true>::enableRawCharReads() { raw_char_reads = true; }
00476
00485 template <typename Device>
00486 void InputTextStream<Device,true>::disableRawCharReads() { raw_char_reads = false; }
00487
00488
00489
00490
00491
00492
00502 template <typename Device>
00503 bool InputTextStream<Device,true>::skipLeadingWhiteSpace(char &c)
00504 {
00505 do {
00506 if( this->io_device.read(c) < 1 ) {
00507 this->error = ReadError;
00508 return false;
00509 }
00510 } while ( ( c == ' ' ) || ( c == '\n' ) );
00511 return true;
00512 }
00513
00518 template <typename Device>
00519 template <typename Number>
00520 bool InputTextStream<Device,true>::parseHexInteger(Number &i)
00521 {
00522 char c;
00523 static int digits[25];
00524 static const short ceiling = numeric_limits<short>::maximum/10;
00525
00526 i = 0;
00527 int j = 0;
00528 while ( j < 25 ) {
00529 long n = this->io_device.read(c);
00530 if ( n < 0 ) {
00531 this->error = ReadError;
00532 return false;
00533 } else if ( n == 0 ) {
00534 break;
00535 }
00536 if ( ( c >= '0' ) && ( c <= '9') ) {
00537 digits[j] = c - '0';
00538 } else if ( ( c >= 'a' ) && ( c <= 'f') ) {
00539 digits[j] = 10 + c - 'a';
00540 } else if ( ( c >= 'A' ) && ( c <= 'F') ) {
00541 digits[j] = 10 + c - 'A';
00542 } else {
00543 break;
00544 }
00545 ++j;
00546 }
00547 if ( j == 0 ) {
00548 this->error = ReadError;
00549 return false;
00550 }
00551
00552 short number = 0;
00553 for ( int k = 0; k < j; ++k ) {
00554 if ( number < ceiling ) {
00555 number = 16*number + (digits[k]);
00556 } else {
00557 this->error = OutOfRangeError;
00558 return false;
00559 }
00560 }
00561 i = number;
00562 return true;
00563 }
00564
00570 template <typename Device>
00571 template <typename Number>
00572 bool InputTextStream<Device,true>::getIntegerFromStream(Number &i) {
00573
00574 static char digits[25];
00575 static const Number ceiling = ecl::numeric_limits<Number>::maximum/10;
00576 char c = ' ';
00577 Number sign_multiplier = 1;
00578 Number number;
00579
00580 if ( !skipLeadingWhiteSpace(c) ) { return false; }
00581
00582 if ( c == '-' ) {
00583 if ( std::numeric_limits<Number>::min() != 0 ) {
00584 sign_multiplier = -1;
00585 if ( this->io_device.read(c) < 1 ) {
00586 this->error = ReadError;
00587 return false;
00588 }
00589 }
00590 } else if ( c == '+' ) {
00591 if ( this->io_device.read(c) < 1 ) {
00592 this->error = ReadError;
00593 return false;
00594 }
00595 } else if ( c == '0' ) {
00596 long n = this->io_device.read(c);
00597 if ( ( n == 0 ) || ( c == ' ' ) || ( c == '\n' ) ) {
00598 i = 0;
00599 return true;
00600 } else if ( n < 0 ) {
00601 this->error = ReadError;
00602 return false;
00603 } else if ( c == 'x' ) {
00604 return parseHexInteger(i);
00605 } else {
00606
00607 }
00608 } else if ( c == 'x' ) {
00609 return parseHexInteger(i);
00610 }
00611
00612
00613
00614
00615 int j = 0;
00616 while ( ( c >= '0' ) && ( c <= '9') && ( j < 25 ) ) {
00617 digits[j] = c;
00618 j++;
00619 long n = this->io_device.read(c);
00620 if ( n < 0 ) {
00621 this->error = ReadError;
00622 return false;
00623 } else if ( n == 0 ) {
00624 break;
00625 } else {
00626 }
00627 }
00628 if ( j == 0 ) {
00629 this->error = ConversionError;
00630 return false;
00631 }
00632 number = 0;
00633 for ( int k = 0; k < j; ++k )
00634 {
00635 if ( number < ceiling )
00636 {
00637 number = 10*number + (digits[k] - '0');
00638 } else {
00639 this->error = OutOfRangeError;
00640 return false;
00641 }
00642 }
00643 i = sign_multiplier*number;
00644
00645 return true;
00646 }
00647
00648 template <typename Device>
00649 template <typename Number>
00650 bool InputTextStream<Device,true>::getFloatFromStream(Number &f) {
00651 static const int bufferSize = 25;
00652 static char digits[bufferSize];
00653 char c = ' ';
00654 int integral_length = 0;
00655 int decimal_length = 0;
00656 Number sign_multiplier = 1;
00657 Number number;
00658
00659 if ( !skipLeadingWhiteSpace(c) ) { return false; }
00660
00661 if ( c == '-' ) {
00662 sign_multiplier = -1;
00663 if ( this->io_device.read(c) < 1 ) { this->error = ReadError; return false; }
00664 } else if ( c == '+' ) {
00665 if ( this->io_device.read(c) < 1 ) { this->error = ReadError; return false; }
00666 }
00667 number = 0;
00668
00669
00670
00671 while ( ( c >= '0' ) && ( c <= '9') && ( integral_length < bufferSize ) ) {
00672 digits[integral_length] = c;
00673 long n = this->io_device.read(c);
00674 if ( n < 0 ) {
00675 this->error = ReadError; return false;
00676 } else if ( n == 0 ) {
00677 break;
00678 } else {
00679 integral_length++;
00680 }
00681 }
00682 for ( int k = 0; k < integral_length; ++k ) {
00683 number = 10*number + (digits[k] - '0');
00684 }
00685
00686 if ( c == '.' ) {
00687 float frac_multiplier = 1;
00688 if ( this->io_device.read(c) < 1 ) { this->error = ReadError; return false; }
00689
00690
00691
00692 while ( ( c >= '0' ) && ( c <= '9') && ( decimal_length < bufferSize ) ) {
00693 digits[decimal_length] = c;
00694 long n = this->io_device.read(c);
00695 if ( n < 0 ) {
00696 this->error = ReadError; return false;
00697 } else if ( n == 0 ) {
00698 break;
00699 } else {
00700 decimal_length++;
00701 }
00702 }
00703 for ( int k = 0; k < decimal_length; ++k ) {
00704 frac_multiplier *= 0.1f;
00705 number = number + frac_multiplier*(digits[k] - '0');
00706 }
00707 }
00708
00709 if ( (integral_length+decimal_length) == 0 ) {
00710 this->error = ConversionError;
00711 return false;
00712 }
00713
00714 f = sign_multiplier*number;
00715
00716 return true;
00717 }
00718
00719 }
00720 }
00721
00722 #endif