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