/** -*- 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_OSTREAM #define __KAI_OSTREAM #include #include #include #include namespace std { template class basic_ostream : virtual public basic_ios { typedef basic_streambuf streambuf_type; typedef ostreambuf_iterator iter_type; typedef num_put > facet_type; public: 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.2.2 Constructor/destructor: explicit basic_ostream(streambuf_type* sb); virtual ~basic_ostream(); // 27.6.2.3 Prefix/suffix: class sentry { bool ok_; basic_ostream* pos; public: explicit sentry(basic_ostream& os); ~sentry(); operator bool(){return ok_;} private: sentry(const sentry&); // not to be defined sentry& operator=(const sentry&); // not to be defined }; friend class sentry; // 27.6.2.5 Formatted output: inline basic_ostream& operator<<(basic_ostream& (*pf)(basic_ostream&)); inline basic_ostream& operator<<(basic_ios& (*pf)(basic_ios&)); inline basic_ostream& operator<<(ios_base& (*pf)(ios_base&)); #if KAI_NONSTD_OSTREAM // Following two methods added by KAI for backwards compatibility with Cfront. bool opfx(); inline void osfx(); #endif /* KAI_NONSTD_OSTREAM */ basic_ostream& operator<<(bool n); inline basic_ostream& operator<<(short n); inline basic_ostream& operator<<(unsigned short n); inline basic_ostream& operator<<(int n); inline basic_ostream& operator<<(unsigned int n); basic_ostream& operator<<(long n); basic_ostream& operator<<(unsigned long n); #if __KAI_LONG_LONG basic_ostream& operator<<(__long_long n); basic_ostream& operator<<(unsigned __long_long n); #endif /* __KAI_LONG_LONG */ basic_ostream& operator<<(float f); basic_ostream& operator<<(double f); basic_ostream& operator<<(long double f); basic_ostream& operator<<(const void* p); basic_ostream& operator<<(streambuf_type* sb); // 27.6.2.6 Unformatted output: basic_ostream& put(char_type c); basic_ostream& write(const char_type* s,streamsize n); basic_ostream& flush(); //27.6.2.4 seeks: inline pos_type tellp(); inline basic_ostream& seekp(pos_type); inline basic_ostream& seekp(off_type, ios_base::seekdir); template friend inline basic_ostream& __kai_insert_char(basic_ostream&out, charT2 c); template friend inline basic_ostream& __kai_insert_c_string(basic_ostream& out, const charT2* s, __kai::streamsize_t length); template friend bool __kai_add_padding(basic_ostream& out, int n_padding); }; template bool __kai_add_padding(basic_ostream& out, int n_padding) { charT fill_char = traits::to_char_type(out.fill()); basic_ostream::streambuf_type *sbuf = out.rdbuf(); static const traits::int_type eof_val = traits::eof(); do { if (traits::eq_int_type(sbuf->sputc(fill_char), eof_val)) return false; } while(--n_padding > 0); return true; } template inline basic_ostream& __kai_insert_char(basic_ostream&out, charT c) { __KAI_LOCK_STREAM(out); ios_base::iostate flg = ios_base::goodbit; MSIPL_TRY { basic_ostream::sentry s_(out); if (s_) { streamsize fillcount = out.width()>1 ? out.width()-1 : 0; basic_ostream::streambuf_type *sbuf = out.rdbuf(); if ((out.flags() & ios_base::adjustfield)==ios_base::left) { if (traits::eq_int_type( sbuf->sputc(c), traits::eof() ) ||(fillcount > 0 && !__kai_add_padding(out, fillcount))) flg |= ios_base::failbit; } else { if ((fillcount > 0 && !__kai_add_padding(out, fillcount)) || traits::eq_int_type( sbuf->sputc(c), traits::eof() ) ) flg |= ios_base::failbit; } } } MSIPL_CATCH { flg |= ios_base::badbit; } out.width(0); if (flg!=ios_base::goodbit) out.setstate(flg); return out; } template inline basic_ostream& __kai_insert_c_string(basic_ostream& out, const charT* s, streamsize length) { __KAI_LOCK_STREAM(out); ios_base::iostate flg = ios_base::goodbit; MSIPL_TRY { basic_ostream::sentry s_(out); if (s==NULL) { flg |= ios_base::failbit; } else if (s_) { streamsize prcount = length ? length : traits::length(s); streamsize fillcount = out.width()> prcount ? out.width()-prcount : 0; if ((out.flags() & ios_base::adjustfield)==ios_base::right) { if (fillcount > 0 && !__kai_add_padding(out, fillcount)) flg |= ios_base::failbit; if (out.rdbuf()->sputn(s, prcount)!= prcount) flg |= ios_base::failbit; } else { if (out.rdbuf()->sputn(s, prcount) != prcount) flg |= ios_base::failbit; if (fillcount > 0 && !__kai_add_padding(out, fillcount)) flg |= ios_base::failbit; } } } MSIPL_CATCH { flg |= ios_base::badbit; } out.width(0); if (flg!=ios_base::goodbit) out.setstate(flg); return out; } template inline basic_ostream::basic_ostream(streambuf_type* sb) { init(sb); } template // Do not inline, this is the decider function basic_ostream::~basic_ostream() { } template inline basic_ostream::sentry::sentry(basic_ostream& os):ok_(false), pos(&os) { if (!os.state && os.tiestr) os.tiestr->flush(); if (!os.state) ok_ = true; else os.setstate(ios_base::failbit); } template inline basic_ostream::sentry::~sentry() { if (pos->fmtfl & unitbuf && pos->sb && pos->sb->pubsync() == -1) { pos->state |= badbit; if (pos->state & pos->except_flags) ios_base::throwfailure(); } } template inline basic_ostream::pos_type basic_ostream::tellp() { __KAI_LOCK_STREAM(*this); return (state & badbit || state & failbit) ? pos_type(-1) : sb->pubseekoff(0, ios_base::cur, ios_base::out); } template inline basic_ostream& basic_ostream::seekp(pos_type pos) { __KAI_LOCK_STREAM(*this); if (!(state & badbit || state & failbit)) // KAI added ios_base::out - see Issue 136 of WG21's Library Issues list sb->pubseekpos(pos, ios_base::out); return *this; } template inline basic_ostream& basic_ostream::seekp(off_type off, ios_base::seekdir dir) { __KAI_LOCK_STREAM(*this); if (!(state & badbit || state & failbit)) // KAI added ios_base::out - see Issue 136 of WG21's Library Issues list sb->pubseekoff(off, dir, ios_base::out); return *this; } template basic_ostream& basic_ostream::operator<<(bool n) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this); if (s_) { if (num_put_facet().put(*this, *this, fillch, n).failed()) flg |= failbit; } } MSIPL_CATCH { flg |= badbit; } if (flg) setstate(flg); return *this; } // KAI change - replace Modena's pathetically code-bloating // definitions for operator<< for signed/unsigned short/int // to definitions that call operator<< for signed/unsigned long. template inline basic_ostream& basic_ostream::operator<<(short n) { return operator<<((long)n); } template inline basic_ostream& basic_ostream::operator<<(unsigned short n) { return operator<<((unsigned long)n); } template inline basic_ostream& basic_ostream::operator<<(int n) { return operator<<((long)n); } template inline basic_ostream& basic_ostream::operator<<(unsigned int n) { return operator<<((unsigned long)n); } template basic_ostream& basic_ostream::operator<<(long n) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this); if (s_) { if (num_put_facet().put(*this, *this, fillch, n).failed()) flg |= failbit; } } MSIPL_CATCH { flg |= badbit; } if (flg) setstate(flg); return *this; } template basic_ostream& basic_ostream::operator<<(unsigned long n) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this); if (s_) { if (num_put_facet().put(*this, *this, fillch, n).failed()) flg |= failbit; } } MSIPL_CATCH { flg |= badbit; } if (flg) setstate(flg); return *this; } #if __KAI_LONG_LONG template basic_ostream& basic_ostream::operator<<(__long_long n) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this); if (s_) { if (num_put_facet().put(*this, *this, fillch, n).failed()) flg |= failbit; } } MSIPL_CATCH { flg |= badbit; } if (flg) setstate(flg); return *this; } template basic_ostream& basic_ostream::operator<<(unsigned __long_long n) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this); if (s_) { if (num_put_facet().put(*this, *this, fillch, n).failed()) flg |= failbit; } } MSIPL_CATCH { flg |= badbit; } if (flg) setstate(flg); return *this; } #endif /* __KAI_LONG_LONG */ template basic_ostream& basic_ostream::operator<<(float n) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this); if (s_) { if (num_put_facet().put(*this, *this, fillch, n).failed()) flg |= failbit; } } MSIPL_CATCH { flg |= badbit; } if (flg) setstate(flg); return *this; } template basic_ostream& basic_ostream::operator<<(double n) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this); if (s_) { if (num_put_facet().put(*this, *this, fillch, n).failed()) flg |= failbit; } } MSIPL_CATCH { flg |= badbit; } if (flg) setstate(flg); return *this; } template basic_ostream& basic_ostream::operator<<(long double n) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this); if (s_) { if (num_put_facet().put(*this, *this, fillch, n).failed()) flg |= failbit; } } MSIPL_CATCH { flg |= badbit; } if (flg) setstate(flg); return *this; } template basic_ostream& basic_ostream::operator<<(const void* n) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this); if (s_) { if (num_put_facet().put(*this, *this, fillch,(void*)n).failed()) flg |= failbit; } } MSIPL_CATCH { flg |= badbit; } if (flg) setstate(flg); return *this; } template inline basic_ostream& basic_ostream::operator<<(basic_ostream&(*pf)(basic_ostream&)) { return (*pf)(*this); } template inline basic_ostream& basic_ostream::operator<<(basic_ios&(*pf)(basic_ios&)) { (*pf)(*this); return *this; } template inline basic_ostream& basic_ostream::operator<<(ios_base&(*pf)(ios_base&)) { (*pf)(*this); return *this; } template basic_ostream& basic_ostream::operator<<(streambuf_type* buf) { int_type ch; streamsize count = 0; iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this); if (s_ && buf) while (!traits::eq_int_type(ch = buf->sbumpc(), traits::eof())) { if (traits::eq_int_type(sb->sputc(ch), traits::eof())) { buf->sputbackc(ch); break; } count++; } else flg |= badbit; if (!count) flg |= failbit; } MSIPL_CATCH { flg |= badbit; } if (flg) setstate(flg); return *this; } template basic_ostream& basic_ostream::put(char_type c) { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); streambuf_type* sbuf = sb; // Tests ordered to reject quickly in common rejection cases. if( sbuf && sbuf->pnext && sbuf->pnextpend && (fmtfl&unitbuf)==0 && !state && !tiestr ) { // Fast case. *sbuf->pnext++ = c; } else { MSIPL_TRY { sentry s_(*this); if (!s_ || traits::eq_int_type(sb->sputc(c), traits::eof())) flg |= badbit; } MSIPL_CATCH { flg |= badbit; } if (flg) setstate(flg); } return *this; } template basic_ostream& basic_ostream::write(const char_type* s, streamsize n) { __KAI_LOCK_STREAM(*this); streambuf_type* sbuf = sb; // Tests ordered to reject quickly in common rejection cases. if( sbuf && sbuf->pnext && n<=sbuf->pend-sbuf->pnext && (fmtfl&unitbuf)==0 && !state && !tiestr && sbuf->pnext<=sbuf->pend ) { // Fast case. traits::copy( sbuf->pnext, s, n ); sbuf->pnext +=n; } else { iostate flg = goodbit; MSIPL_TRY { sentry s_(*this); if (s_ &&(n != sb->sputn(s, n))) flg |= badbit; } MSIPL_CATCH { flg |= badbit; } if (flg) setstate(flg); } return *this; } template basic_ostream& basic_ostream::flush() { iostate flg = goodbit; __KAI_LOCK_STREAM(*this); MSIPL_TRY { sentry s_(*this); if (s_ && sb && sb->pubsync() == -1) flg |= badbit; } MSIPL_CATCH { flg |= badbit; } if (flg) setstate(flg); return *this; } // Manipulators -- Standard basic_ostream template basic_ostream& endl(basic_ostream& os) { os.put(os.widen('\n')); os.flush(); return os; } template basic_ostream& ends(basic_ostream& os) { os.put(charT()); return os; } template basic_ostream& flush(basic_ostream& os) { os.flush(); return os; } // 27.6.2.5.4 character inserters. template basic_ostream& operator<<(basic_ostream&out, charT c) { return __kai_insert_char(out,c); } template basic_ostream& operator<<(basic_ostream&out, char c){ return __kai_insert_char(out, out.widen(c)); } // partial specializations template basic_ostream& operator<<(basic_ostream&out, char c){ return __kai_insert_char(out, c); } // signed and unsigned template basic_ostream& operator<<(basic_ostream&out, signed char c){ return __kai_insert_char(out, (char)c); } template basic_ostream& operator<<(basic_ostream&out, unsigned char c){ return __kai_insert_char(out, (char)c); } template basic_ostream& operator<<(basic_ostream& out,const charT* s){ return __kai_insert_c_string(out,s); } template basic_ostream& operator<<(basic_ostream&out, const char* s){ return __kai_insert_c_string(out,(charT*)(s)); } // partial specializations template basic_ostream& operator<<(basic_ostream&out, const char* s){ return __kai_insert_c_string(out,(char*)(s)); } // signed and unsigned template basic_ostream& operator<<(basic_ostream&out, const signed char* s){ return __kai_insert_c_string(out,(char*)(s)); } template basic_ostream& operator<<(basic_ostream&out, const unsigned char* s){ return __kai_insert_c_string(out,(char*)(s)); } template void __kai_do_flush(basic_ostream* os) { os->flush(); } #if KAI_NONSTD_OSTREAM // opfx and osfx are not part of December 1996 ANSI draft, // but are widely used by existing C++ codes. template bool basic_ostream::opfx() { __KAI_LOCK_STREAM(*this); if (good()) { if (tie()) { tie()->flush(); } } return good(); } template void basic_ostream::osfx() { __KAI_LOCK_STREAM(*this); if (flags() & unitbuf) flush(); // Is it the right place to reset width ? width(0); } #endif /* KAI_NONSTD_OSTREAM */ typedef basic_ostream > ostream; #ifdef KAI_WCHAR_T typedef basic_ostream > wostream; #endif } // namespace std #endif /* __KAI_OSTREAM */