// Purpose. Simple iostream classes // // Source: P.J. Plauger, C/C++ Users Journal, Mar 99, pp10-18 // // Three workhorse classes partition the basic functionality: // o "istream" defines all extractors for the basic types // o "ostream" defines all inserters for the basic types // o "streambuf" controls an input stream and an output stream // "streambuf" is the mechanism for performing all actual manipulations of a data stream // You derive from these 3 workhorses to make useful sets of classes. // "These classes constitute not quite the simplest set of classes I could contrive to // do something new and moderately interesting - perform input and output using just // the basic functions getchar() and putchar()." // You should override the following methods: // o overflow - output a character // o underflow - input a character // o uflow - peek at the next input character // o pbackfail - back up one character in the input stream #include #include using namespace std; class simple_filebuf : public streambuf { public: simple_filebuf() { saved = -1; } virtual ~simple_filebuf() { } protected: virtual int_type overflow( int_type ch = traits_type::eof() ) { if (traits_type::eq_int_type( traits_type::eof(), ch )) return traits_type::not_eof( ch ); else return putchar( traits_type::to_char_type(ch)) != EOF ? ch : traits_type::eof(); } virtual int_type underflow() { return pbackfail( uflow() ); } virtual int_type pbackfail( int_type ch = traits_type::eof() ) { if (0 <= saved) return traits_type::eof(); // buffer in use else if (traits_type::eq_int_type( traits_type::eof(), ch )) return traits_type::eof(); // can't just backup else { saved = (unsigned char) traits_type::to_char_type( ch ); return ch; } } virtual int_type uflow() { int_type ch = saved; if (0 <= ch) { saved = -1; // erase saved char return ch; } else return (ch = getchar()) != EOF ? ch : traits_type::eof(); } private: // simple_filebuf maintains a single-character buffer int saved; // negative => no saved character }; class simple_ifstream : public istream { public: simple_ifstream() : istream( &mybuf ) { } ~simple_ifstream() { } simple_filebuf *rdbuf() const { return (simple_filebuf*) &mybuf; } private: simple_filebuf mybuf; }; class simple_ofstream : public ostream { public: simple_ofstream() : ostream( &mybuf ) { } ~simple_ofstream() { } simple_filebuf *rdbuf() const { return (simple_filebuf*) &mybuf; } private: simple_filebuf mybuf; }; class simple_fstream : public iostream { public: simple_fstream() : iostream( &mybuf ) { } ~simple_fstream() { } simple_filebuf *rdbuf() const { return (simple_filebuf*) &mybuf; } private: simple_filebuf mybuf; }; void main( void ) { simple_ofstream ofs; ofs << "hello world" << endl; int x; simple_ifstream ifs; ifs >> x; ofs << "x = " << x << endl; simple_fstream fs; fs << "hello again" << endl; fs >> x; fs << "x = " << x << endl; } // hello world // 123 // x = 123 // hello again // 234 // x = 234