/** -*- C++ -*- ** ** KAI C++ Compiler ** ** Copyright (C) 1996-2001 Intel Corp. All rights reserved. **/ /** ** Lib++ : The Modena C++ Standard Library, ** Version 2.4, October 1997 ** ** Copyright (c) 1995-1997 Modena Software Inc. **/ #ifndef __KAI_ISTREAM #define __KAI_ISTREAM #include #include #include #include //#include #include #include namespace std { template class basic_istream : virtual public basic_ios { typedef basic_streambuf streambuf_type; public: typedef num_get > facet_type; typedef ctype ctype_facet_type; typedef charT char_type; typedef typename traits::int_type int_type; typedef typename traits::pos_type pos_type; typedef typename traits::off_type off_type; typedef traits traits_type; // 27.6.1.1.1 Constructor/Destructor: explicit basic_istream(streambuf_type* sb); virtual ~basic_istream(); // 27.6.1.1.2 Prefix/Suffix: class sentry { bool ok_; typedef ctype ctype_facet_type; public: explicit sentry(basic_istream& is, bool noskipws=false); operator bool () const { return ok_; } private: // Not to be defined sentry (const sentry&); sentry& operator= (const sentry&); }; friend class sentry; // 27.6.1.2 Formatted input: /* inline keywords removed by KAI */ basic_istream& operator>>(basic_istream& (*pf)(basic_istream&)); basic_istream& operator>>(basic_ios& (*pf)(basic_ios&)); basic_istream& operator>>(ios_base& (*pf)(ios_base&)); basic_istream& operator>>(bool& n); basic_istream& operator>>(short& n); basic_istream& operator>>(unsigned short& n); basic_istream& operator>>(int& n); basic_istream& operator>>(unsigned int& n); basic_istream& operator>>(long& n); basic_istream& operator>>(unsigned long& n); #if __KAI_LONG_LONG basic_istream& operator>>(__long_long& n); basic_istream& operator>>(unsigned __long_long& n); #endif /* __KAI_LONG_LONG */ basic_istream& operator>>(float& f); basic_istream& operator>>(double& f); basic_istream& operator>>(long double& f); basic_istream& operator>>(void*& p); basic_istream& operator>>(streambuf_type* sb); // 27.6.1.3 Unformatted input: streamsize gcount() const {return chcount;} int_type get(); basic_istream& get(char_type& c); basic_istream& get(char_type* s, streamsize n) {return get(s, n, widen('\n'));}; basic_istream& get(char_type*, streamsize, char_type); basic_istream& get(streambuf_type&); basic_istream& get(streambuf_type&, char_type); inline basic_istream& getline(char_type* s, streamsize n) {return getline(s, n, widen('\n'));} basic_istream& getline(char_type*, streamsize, char_type); basic_istream& ignore(streamsize n=1, int_type delim=traits::eof()); int_type peek(); basic_istream& read(char_type*, streamsize); streamsize readsome(char_type*, streamsize); basic_istream& putback(char_type); basic_istream& unget(); int sync(); pos_type tellg(); basic_istream& seekg(pos_type); basic_istream& seekg(off_type, ios_base::seekdir); // KAI change - rewrite three versions of operator>>(in,s) to all simply // call new friend function __kai_extract_c_string, which does the real work. template friend basic_istream& __kai_extract_c_string (basic_istream& in, charT2* s); template friend basic_istream& __kai_extract_char(basic_istream& in, charT2& c); private: streamsize chcount; }; template basic_istream& __kai_extract_c_string(basic_istream& in, charT2* s) { typedef basic_istream IT; charT* ssav = s; ios_base::iostate flg = ios_base::goodbit; __KAI_LOCK_STREAM(in); MSIPL_TRY { IT::sentry s_(in); if (s_) { int count = in.width() > 0 ? in.width() : numeric_limits::max(); IT::int_type ch; const IT::ctype_facet_type& ct = in.ctype_facet(); for (;0 < --count;) { // Save a spot for the nul. ch = in.rdbuf()->sbumpc(); if (ct.is(ct.space, ch)) { in.rdbuf()->sputbackc(ch); break; } if (traits::eq_int_type(ch, traits::eof())) { flg |= IT::eofbit; break; } if (traits::eq_int_type(ch, charT())) break; *ssav++ = traits::to_char_type(ch); } } } MSIPL_CATCH { flg |= IT::badbit; } in.width(0); *ssav = charT(); if (ssav == s) flg |= IT::failbit; in.setstate(flg); return in; } template basic_istream& __kai_extract_char(basic_istream& in, charT2& c) { typedef basic_istream IT; ios_base::iostate flg = ios_base::goodbit; IT::int_type ch; __KAI_LOCK_STREAM(in); MSIPL_TRY { IT::sentry s_(in); if (s_ && !traits::eq_int_type(ch = in.rdbuf()->sbumpc(), traits::eof())) c=traits::to_char_type(ch); else flg |= ios_base::failbit; } MSIPL_CATCH { flg |= IT::badbit; } if (flg != IT::goodbit) in.setstate(flg); return in; } template inline basic_istream::basic_istream(streambuf_type* sb) : chcount(0) // adr: Modena was initializing ios_base incorrectly. // See comments in about corresponding constructor for ostream. { init(sb); } template // Do not inline - this is the decider function basic_istream::~basic_istream() {} template extern basic_ostream& flush(basic_ostream& os); template extern void __kai_do_flush(basic_ostream* os); template basic_istream::sentry::sentry( basic_istream& is, bool noskipws) : ok_(false) { __KAI_LOCK_STREAM(is); is.chcount = 0; iostate flg = goodbit; MSIPL_TRY { if (is.state == ios_base::goodbit) { if (is.tiestr) __kai_do_flush(is.tiestr); if (!noskipws &&(is.fmtfl & skipws)) { traits::int_type ch; const ctype_facet_type& ct = is.ctype_facet(); do { ch = is.sb->sbumpc(); } while (!traits::eq_int_type(ch, traits::eof()) && ct.is(ct.space, ch)); if (!traits::eq_int_type(ch, traits::eof())) is.sb->sputbackc(ch); } } else flg = failbit; } MSIPL_CATCH { flg |= ios_base::badbit; } is.setstate(flg); if(!is.state) { ok_ = true; } } template basic_istream& basic_istream::operator>>(bool& n) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s(*this); if (s) num_get_facet().get(*this, 0, *this, flg, n); } MSIPL_CATCH { flg |= badbit; } if (flg != goodbit) setstate(flg); return *this; } template basic_istream& basic_istream::operator>>(short& n) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this); if (s_) { long tmp; num_get_facet().get(*this, 0, *this, flg, tmp); if ( (n = tmp) != tmp) flg |= failbit; } } MSIPL_CATCH { flg |= badbit; } if (flg!=goodbit) setstate(flg); return *this; } template basic_istream& basic_istream::operator>>(int& n) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s(*this); if (s) { long tmp; num_get_facet().get(*this, 0, *this, flg, tmp); if ( (n = tmp) != tmp) flg |= failbit; } } MSIPL_CATCH { flg |= badbit; } if (flg !=goodbit) setstate(flg); return *this; } template basic_istream& basic_istream::operator>>(long& n) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s(*this); if (s) num_get_facet().get(*this, 0, *this, flg, n); } MSIPL_CATCH { flg |= badbit; } if (flg!=goodbit) setstate(flg); return *this; } #if __KAI_LONG_LONG template basic_istream& basic_istream::operator>>(__long_long& n) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s(*this); if (s) num_get_facet().get(*this, 0, *this, flg, n); } MSIPL_CATCH { flg |= badbit; } if (flg!=goodbit) setstate(flg); return *this; } #endif /* __KAI_LONG_LONG */ template basic_istream& basic_istream::operator>>(unsigned short& n) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this); if (s_) num_get_facet().get(*this, 0, *this, flg, n); } MSIPL_CATCH { flg |= badbit; } if (flg!=goodbit) setstate(flg); return *this; } template basic_istream& basic_istream::operator>>(unsigned int& n) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this); if (s_) num_get_facet().get(*this, 0, *this, flg, n); } MSIPL_CATCH { flg |= badbit; } if (flg!=goodbit) setstate(flg); return *this; } template basic_istream& basic_istream::operator>>(unsigned long& n) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this); if (s_) num_get_facet().get(*this, 0, *this, flg, n); } MSIPL_CATCH { flg |= badbit; } if (flg!=goodbit) setstate(flg); return *this; } #if __KAI_LONG_LONG template basic_istream& basic_istream::operator>>(unsigned __long_long& n) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s(*this); if (s) num_get_facet().get(*this, 0, *this, flg, n); } MSIPL_CATCH { flg |= badbit; } if (flg!=goodbit) setstate(flg); return *this; } #endif /* __KAI_LONG_LONG */ template basic_istream& basic_istream::operator>>(float& n) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this); if (s_) num_get_facet().get(*this, 0, *this, flg, n); } MSIPL_CATCH { flg |= badbit; } if (flg!=goodbit) setstate(flg); return *this; } template basic_istream& basic_istream::operator>>(double& n) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this); if (s_) num_get_facet().get(*this, 0, *this, flg, n); } MSIPL_CATCH { flg |= badbit; } if (flg!=goodbit) setstate(flg); return *this; } template basic_istream& basic_istream::operator>>(long double& n) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this); if (s_) num_get_facet().get(*this, 0, *this, flg, n); } MSIPL_CATCH { flg |= badbit; } if (flg!=goodbit) setstate(flg); return *this; } template basic_istream& basic_istream::operator>>(void*& n) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this); if (s_) num_get_facet().get(*this, 0, *this, flg, n); } MSIPL_CATCH { flg |= badbit; } if (flg!=goodbit) setstate(flg); return *this; } template inline basic_istream& basic_istream::operator>>(basic_istream&(*pf)(basic_istream&)) { return (*pf)(*this); } template inline basic_istream& basic_istream::operator>>(basic_ios&(*pf)(basic_ios&)) { (*pf)(*this); return *this; } template inline basic_istream& basic_istream::operator>>(ios_base&(*pf)(ios_base&)) { (*pf)(*this); return *this; } template basic_istream& basic_istream::operator>>(streambuf_type* buf) { iostate flg = goodbit; int_type ch; bool res = false; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this); if (buf && s_) { while (!traits::eq_int_type(ch = sb->sbumpc(), traits::eof())) { if (traits::eq_int_type(buf->sputc(traits::to_char_type(ch)), traits::eof())) { sb->sputbackc(ch); break; } res = true; } if (traits::eq_int_type(ch, traits::eof())) flg |= eofbit; } if (!res) flg |= failbit; } MSIPL_CATCH { flg |= badbit; } if (flg!=goodbit) setstate(flg); return *this; } template basic_istream::int_type basic_istream::get() { __KAI_LOCK_STREAM(*this); // Tests ordered to reject quickly in common rejection cases. streambuf_type* sbuf = sb; if( sbuf && sbuf->gnext && sbuf->gnextgend && !state && !tiestr ) { // Fast case. chcount=1; return traits::to_int_type(*sbuf->gnext++); } else { iostate flg = goodbit; MSIPL_TRY { int_type ch; sentry s_(*this, true); if (s_) { if (traits::eq_int_type(ch=sb->sbumpc(),traits::eof())) flg|=failbit|eofbit; else { chcount=1; return ch; } } else { flg |= failbit; } } MSIPL_CATCH { flg |= badbit; } if (flg!=goodbit) setstate(flg); return traits::eof(); } } template basic_istream& basic_istream::get( char_type& c ) { __KAI_LOCK_STREAM(*this); // Tests ordered to reject quickly in common rejection cases. streambuf_type* sbuf = sb; if( sbuf && sbuf->gnext && sbuf->gnextgend && !state && !tiestr ) { // Fast case. chcount=1; c = *sbuf->gnext++; } else { iostate flg = goodbit; MSIPL_TRY { int_type ch; sentry s_(*this, true); if (s_) { if (traits::eq_int_type(ch=sb->sbumpc(),traits::eof())) flg|=failbit|eofbit; else { chcount=1; c = traits::to_char_type(ch); } } else { flg |= failbit; } } MSIPL_CATCH { flg |= badbit; } if (flg!=goodbit) setstate(flg); } return *this; } template basic_istream& basic_istream::get(char_type* s, streamsize n, char_type delim) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this, true); if (s_ && n) { int_type ch; while (--n) { if (traits::eq_int_type(ch = sb->sbumpc(), traits::eof())) { flg |= eofbit; break; } if (traits::to_char_type(ch) == delim) { sb->sputbackc(ch); break; } *s++ = traits::to_char_type(ch); chcount++; } } } MSIPL_CATCH { flg |= badbit; } *s = charT(); if (!chcount) flg |= failbit; if (flg!=goodbit) setstate(flg); return *this; } template basic_istream& basic_istream::get(streambuf_type& buf, char_type delim) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { int_type ch; sentry s_(*this, true); if (s_) { while (1) { if (traits::eq_int_type(ch = sb->sbumpc(), traits::eof())) { flg |= eofbit; break; } if (traits::eq_int_type(ch, delim) || traits::eq_int_type(buf.sputc(traits::to_char_type(ch)), traits::eof())) { sb->sputbackc(ch); break; } chcount++; } } } MSIPL_CATCH { flg |= badbit; } if (!chcount) flg |= failbit; if (flg!=goodbit) setstate(flg); return *this; } template inline basic_istream& basic_istream::get(streambuf_type& sb) { return get(sb, widen('\n')); } template basic_istream& basic_istream::getline(char_type* s, streamsize n, char_type delim) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this, true); if (s_ && n>0) { int_type ch; while (1) { if (traits::eq_int_type(ch = sb->sbumpc(), traits::eof())) { flg |= eofbit; break; } if (traits::to_char_type(ch) == delim) { chcount++; break; } if (!--n) { sb->sputbackc(ch); flg |= failbit; break; } *s++ = traits::to_char_type(ch); chcount++; } } } MSIPL_CATCH { flg |= badbit; } *s = charT(); if (!chcount) flg |= failbit; if (flg!=goodbit) setstate(flg); return *this; } template basic_istream& basic_istream::ignore(streamsize n, int_type delim) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this, true); if (s_) { int_type ch; for ( ; n>0; --n ) // Changed from while by KAI to avoid HP/UX 11 compiler bug. if (traits::eq_int_type(ch = sb->sbumpc(), traits::eof())) { flg |= eofbit; break; } else { ++chcount; if (ch == delim) break; } } } MSIPL_CATCH { flg |= badbit; } if (flg!=goodbit) setstate(flg); return *this; } template basic_istream::int_type basic_istream::peek() { iostate flg = goodbit; int_type ch = traits::eof(); __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this, true); if (s_ && traits::eq_int_type(ch = sb->sgetc(), traits::eof())) flg |= eofbit; } MSIPL_CATCH { flg |= badbit; } if (flg!=goodbit) setstate(flg); return ch; } template basic_istream& basic_istream::read(char_type* s, streamsize n) { __KAI_LOCK_STREAM(*this); // Tests ordered to reject quickly in common rejection cases. streambuf_type* sbuf = sb; if( sbuf && sbuf->gnext && n<=sbuf->gend-sbuf->gnext && !state && !tiestr && sbuf->gnextgend ) { // Fast case. traits::copy( s, sbuf->gnext, n ); sb->gnext+=n; chcount = n; } else { iostate flg = goodbit; MSIPL_TRY { sentry s_(*this, true); if (!s_ ||(chcount = sb->sgetn(s, n)) != n) flg |= failbit | eofbit; } MSIPL_CATCH { flg |= badbit; } if (flg!=goodbit) setstate(flg); } return *this; } template streamsize basic_istream::readsome(char_type* s, streamsize n) { __KAI_LOCK_STREAM(*this); // Tests ordered to reject quickly in common rejection cases. streambuf_type* sbuf = sb; if( sbuf && sbuf->gnext && n<=sbuf->gend-sbuf->gnext && !state && !tiestr && sbuf->gnextgend ) { // Fast case. traits::copy( s, sbuf->gnext, n ); sb->gnext+=n; chcount = n; } else { iostate flg = goodbit; chcount = 0; MSIPL_TRY { sentry s_(*this, true); if (s_) { // adr: Modena's implementation using sgetn was just plain wrong. // It called sgetn without checking in_avail, and thus could // lead to calling uflow, which is not permitted by any recent draft! streamsize m = sb->in_avail(); if ( m==(streamsize)-1 ) { flg |= eofbit; } else if ( m>0 ) { if ( m>n ) m=n; chcount = sb->sgetn(s, m); } } else flg |= failbit; } MSIPL_CATCH { flg |= badbit; } if (flg!=goodbit) setstate(flg); } return chcount; } template basic_istream& basic_istream::putback(char_type c) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this, true); if (!sb) flg |= badbit; else if (state) flg |= failbit; else if (traits::eq_int_type(sb->sputbackc(c), traits::eof())) flg |= badbit; } MSIPL_CATCH { flg |= badbit; } if (flg!=goodbit) setstate(flg); return *this; } template basic_istream& basic_istream::unget() { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this, true); if (!sb) flg |= badbit; else if (state) flg |= failbit; else if (traits::eq_int_type(sb->sungetc(), traits::eof())) flg |= badbit; } MSIPL_CATCH { flg |= badbit; } if (flg!=goodbit) setstate(flg); return *this; } template int basic_istream::sync() { int ret = -1; iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this, true); if (sb) if (sb->pubsync() == -1) flg |= badbit, ret = traits::eof(); else ret = 0; } MSIPL_CATCH { flg |= badbit; } if (flg!=goodbit) setstate(flg); return ret; } template inline basic_istream:: pos_type basic_istream::tellg() { __KAI_LOCK_STREAM(*this); sentry(*this, true); return (state&badbit || state&failbit) ? pos_type(-1): sb->pubseekoff(0, ios_base::cur, ios_base::in); } template inline basic_istream& basic_istream::seekg(off_type off, ios_base::seekdir dir) { __KAI_LOCK_STREAM(*this); sentry(*this, true); // KAI added ios_base::in - see Issue 136 of WG21's Library Issues list if (!(state & badbit) && !(state & failbit)) sb->pubseekoff(off, dir, ios_base::in); return *this; } template inline basic_istream& basic_istream::seekg(pos_type pos) { __KAI_LOCK_STREAM(*this); sentry(*this, true); // KAI added ios_base::in - see Issue 136 of WG21's Library Issues list if (!(state & badbit) && !(state & failbit)) sb->pubseekpos(pos, ios_base::in); return *this; } // KAI change - rewrite three versions of operator>>(in,s) to all simply // call new member function __kai_extract_c_string, which does the real work. // The new member function is inline, since it has only three call sites. template inline basic_istream& operator>>(basic_istream& in,charT* s) { return __kai_extract_c_string(in, (charT*)(s)); } template inline basic_istream& operator>>(basic_istream& in,unsigned char* s) { return __kai_extract_c_string(in, (charT*)(s)); } template inline basic_istream& operator>>(basic_istream& in,signed char* s) { return __kai_extract_c_string(in, (charT*)(s)); } // KAI change - rewrite three versions of operator>>(in,c) to all simply // call new member function __kai_extract_char, which does the real work. template inline basic_istream& operator>>(basic_istream& in,charT& c) { return __kai_extract_char(in, c); } template inline basic_istream& operator>>(basic_istream& in,unsigned char& c) { return __kai_extract_char(in, c); } template inline basic_istream& operator>>(basic_istream& in,signed char& c) { return __kai_extract_char(in, c); } typedef basic_istream > istream; #ifdef KAI_WCHAR_T typedef basic_istream > wistream; #endif // 27.6.1.2.3 Character extraction templates: template basic_istream& ws(basic_istream& is) { typedef basic_istream IT; __KAI_LOCK_STREAM(is); ios_base::fmtflags fmtflag_sav = is.setf(ios_base::skipws); IT::sentry s_(is); is.flags(fmtflag_sav); if (traits::eq_int_type(is.rdbuf()->sgetc(), traits::eof())) is.setstate(ios_base::eofbit); return is; } } // namespace std // 27.6.1.5 says that declares std::iostream #include #endif /* __KAI_ISTREAM */