#include #include // [27.7.1] template class basic_stringbuf /** * @brief The actual work of input and output (for std::string). * * This class associates either or both of its input and output sequences * with a sequence of characters, which can be initialized from, or made * available as, a char_type *. (Paraphrased from [27.7.1]/1.) * * For this class, open modes (of type @c ios_base::openmode) have * @c in set if the input sequence can be read, and @c out set if the * output sequence can be written. */ //using namespace std; using std::ios_base; template class basic_arraybuf : public std::basic_streambuf<_CharT, _Traits> { public: // Types: typedef _CharT char_type; typedef _Traits traits_type; // _GLIBCXX_RESOLVE_LIB_DEFECTS // 251. basic_stringbuf missing allocator_type typedef _Alloc allocator_type; typedef typename _Traits::int_type int_type; typedef typename _Traits::pos_type pos_type; typedef typename _Traits::off_type off_type; typedef std::basic_streambuf __streambuf_type; typedef char_type * __array_type; typedef typename _Traits::pos_type __size_type; protected: /// Place to stash in || out || in | out settings for current arraybuf. ios_base::openmode _M_mode; // Data Members: __array_type _M_array; __size_type _M_array_size; public: // Constructors: /** * @brief Starts with an empty array buffer. * @param mode Whether the buffer can read, or write, or both. * * The default constructor initializes the parent class using its * own default ctor. */ explicit basic_arraybuf(ios_base::openmode __mode = ios_base::in | ios_base::out) : __streambuf_type(), _M_mode(__mode) { _M_array = new char_type[0]; } /** * @brief Starts with an existing array buffer. * @param str A array to copy as a starting buffer. * @param mode Whether the buffer can read, or write, or both. * * This constructor initializes the parent class using its * own default ctor. */ explicit basic_arraybuf(const __array_type& __str, const __size_type __strlen, ios_base::openmode __mode = ios_base::in | ios_base::out) : __streambuf_type(), _M_mode(), _M_array(__str, __strlen) { _M_array = new char_type[__strlen + 1]; memcpy(_M_array, __str, __strlen); _M_arraybuf_init(__mode); } // Get and set: /** * @brief Copying out the array buffer. * @return A copy of one of the underlying sequences. * * "If the buffer is only created in input mode, the underlying * character sequence is equal to the input sequence; otherwise, it * is equal to the output sequence." [27.7.1.2]/1 */ __array_type data() { return _M_array; } void data(const __array_type& __s, const __size_type __l) { _M_array = __s; _M_array_size = __l; _M_arraybuf_init(_M_mode); } /* __array_type __ret; */ /* if (this->pptr()) */ /* { */ /* // The current egptr() may not be the actual array end. */ /* if (this->pptr() > this->egptr()) */ /* __ret = __array_type(this->pbase(), this->pptr()); */ /* else */ /* __ret = __array_type(this->pbase(), this->egptr()); */ /* } */ /* else */ /* __ret = _M_array; */ /* return __ret; */ /* } */ protected: // Common initialization code goes here. void _M_arraybuf_init(ios_base::openmode __mode) { _M_mode = __mode; __size_type __len = 0; if (_M_mode & (ios_base::ate | ios_base::app)) __len = _M_array_size; //_M_sync(const_cast(_M_array), 0, __len); } virtual std::streamsize showmanyc() { std::streamsize __ret = -1; if (_M_mode & ios_base::in) { _M_update_egptr(); __ret = this->egptr() - this->gptr(); } return __ret; } virtual int_type underflow(); virtual int_type pbackfail(int_type __c = traits_type::eof()); virtual int_type overflow(int_type __c = traits_type::eof()); /** * @brief Manipulates the buffer. * @param s Pointer to a buffer area. * @param n Size of @a s. * @return @c this * * If no buffer has already been created, and both @a s and @a n are * non-zero, then @c s is used as a buffer; see * http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#2 * for more. */ virtual __streambuf_type* setbuf(char_type* __s, std::streamsize __n) { if (__s && __n >= 0) { // This is implementation-defined behavior, and assumes // that an external char_type array of length __n exists // and has been pre-allocated. If this is not the case, // things will quickly blow up. // Step 1: Destroy the current internal array. delete _M_array; _M_array_size = 0; // Step 2: Use the external array. _M_sync(__s, __n, 0); } return this; } virtual pos_type seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode = ios_base::in | ios_base::out); virtual pos_type seekpos(pos_type __sp, ios_base::openmode __mode = ios_base::in | ios_base::out); // Internal function for correctly updating the internal buffer // for a particular _M_string, due to initialization or re-sizing // of an existing _M_string. void _M_sync(char_type* __base, __size_type __i, __size_type __o); // Internal function for correctly updating egptr() to the actual // array end. void _M_update_egptr() { const bool __testin = _M_mode & ios_base::in; if (this->pptr() && this->pptr() > this->egptr()) if (__testin) this->setg(this->eback(), this->gptr(), this->pptr()); else this->setg(this->pptr(), this->pptr(), this->pptr()); } }; // [27.7.2] Template class basic_iarraystream /** * @brief Controlling input for std::array. * * This class supports reading from objects of type std::basic_array, * using the inherited functions from std::basic_istream. To control * the associated sequence, an instance of std::basic_arraybuf is used, * which this page refers to as @c sb. */ template class basic_iarraystream : public std::basic_istream<_CharT, _Traits> { public: // Types: typedef _CharT char_type; typedef _Traits traits_type; // _GLIBCXX_RESOLVE_LIB_DEFECTS // 251. basic_arraybuf missing allocator_type typedef _Alloc allocator_type; typedef typename _Traits::int_type int_type; typedef typename _Traits::pos_type pos_type; typedef typename _Traits::off_type off_type; // Non-standard types: typedef char_type * __array_type; typedef basic_arraybuf<_CharT, _Traits, _Alloc> __arraybuf_type; typedef std::basic_istream __istream_type; typedef typename _Traits::pos_type __size_type; private: __arraybuf_type _M_arraybuf; public: // Constructors: /** * @brief Default constructor starts with an empty array buffer. * @param mode Whether the buffer can read, or write, or both. * * @c ios_base::in is automatically included in @a mode. * * Initializes @c sb using @c mode|in, and passes @c &sb to the base * class initializer. Does not allocate any buffer. * * That's a lie. We initialize the base class with NULL, because the * array class does its own memory management. */ explicit basic_iarraystream(ios_base::openmode __mode = ios_base::in) : __istream_type(), _M_arraybuf(__mode | ios_base::in) { this->init(&_M_arraybuf); } /** * @brief Starts with an existing array buffer. * @param str A array to copy as a starting buffer. * @param mode Whether the buffer can read, or write, or both. * * @c ios_base::in is automatically included in @a mode. * * Initializes @c sb using @a str and @c mode|in, and passes @c &sb * to the base class initializer. * * That's a lie. We initialize the base class with NULL, because the * array class does its own memory management. */ explicit basic_iarraystream(const __array_type& __str, const __size_type __strlen, ios_base::openmode __mode = ios_base::in) : __istream_type(), _M_arraybuf(__str, __strlen, __mode | ios_base::in) { this->init(&_M_arraybuf); } /** * @brief The destructor does nothing. * * The buffer is deallocated by the arraybuf object, not the * formatting stream. */ ~basic_iarraystream() { } // Members: /** * @brief Accessing the underlying buffer. * @return The current basic_arraybuf buffer. * * This hides both signatures of std::basic_ios::rdbuf(). */ __arraybuf_type* rdbuf() const { return const_cast<__arraybuf_type*>(&_M_arraybuf); } /** * @brief Copying out the array buffer. * @return @c rdbuf()->str() */ __array_type data() const { return _M_arraybuf.data(); } void data(const __array_type& __s, const __size_type __l) { return _M_arraybuf.data(__s, __l); } }; // [27.7.3] Template class basic_oarraystream /** * @brief Controlling output for std::array. * * This class supports writing to objects of type std::basic_array, * using the inherited functions from std::basic_ostream. To control * the associated sequence, an instance of std::basic_arraybuf is used, * which this page refers to as @c sb. */ template class basic_oarraystream : public std::basic_ostream<_CharT, _Traits> { public: // Types: typedef _CharT char_type; typedef _Traits traits_type; // _GLIBCXX_RESOLVE_LIB_DEFECTS // 251. basic_arraybuf missing allocator_type typedef _Alloc allocator_type; typedef typename traits_type::int_type int_type; typedef typename traits_type::pos_type pos_type; typedef typename traits_type::off_type off_type; // Non-standard types: typedef char_type * __array_type; typedef basic_arraybuf<_CharT, _Traits, _Alloc> __arraybuf_type; typedef std::basic_ostream __ostream_type; typedef typename _Traits::pos_type __size_type; private: __arraybuf_type _M_arraybuf; public: // Constructors/destructor: /** * @brief Default constructor starts with an empty array buffer. * @param mode Whether the buffer can read, or write, or both. * * @c ios_base::out is automatically included in @a mode. * * Initializes @c sb using @c mode|out, and passes @c &sb to the base * class initializer. Does not allocate any buffer. * * That's a lie. We initialize the base class with NULL, because the * array class does its own memory management. */ explicit basic_oarraystream(ios_base::openmode __mode = ios_base::out) : __ostream_type(), _M_arraybuf(__mode | ios_base::out) { this->init(&_M_arraybuf); } /** * @brief Starts with an existing array buffer. * @param str A array to copy as a starting buffer. * @param mode Whether the buffer can read, or write, or both. * * @c ios_base::out is automatically included in @a mode. * * Initializes @c sb using @a str and @c mode|out, and passes @c &sb * to the base class initializer. * * That's a lie. We initialize the base class with NULL, because the * array class does its own memory management. */ explicit basic_oarraystream(const __array_type& __str, const __size_type __strlen, ios_base::openmode __mode = ios_base::out) : __ostream_type(), _M_arraybuf(__str, __strlen, __mode | ios_base::out) { this->init(&_M_arraybuf); } /** * @brief The destructor does nothing. * * The buffer is deallocated by the arraybuf object, not the * formatting stream. */ ~basic_oarraystream() { } // Members: /** * @brief Accessing the underlying buffer. * @return The current basic_arraybuf buffer. * * This hides both signatures of std::basic_ios::rdbuf(). */ __arraybuf_type* rdbuf() const { return const_cast<__arraybuf_type*>(&_M_arraybuf); } /** * @brief Copying out the array buffer. * @return @c rdbuf()->data() */ __array_type data() const { return _M_arraybuf.data(); } /** * @brief Setting a new buffer. * @param s The array to use as a new sequence. * * Calls @c rdbuf()->str(s). */ void data(const __array_type& __s, const __size_type __l) { _M_arraybuf.data(__s, __l); } }; // [27.7.4] Template class basic_arraystream /** * @brief Controlling input and output for std::array. * * This class supports reading from and writing to objects of type * std::basic_array, using the inherited functions from * std::basic_iostream. To control the associated sequence, an instance * of std::basic_arraybuf is used, which this page refers to as @c sb. */ template class basic_arraystream : public std::basic_iostream<_CharT, _Traits> { public: // Types: typedef _CharT char_type; typedef _Traits traits_type; // _GLIBCXX_RESOLVE_LIB_DEFECTS // 251. basic_arraybuf missing allocator_type typedef _Alloc allocator_type; typedef typename traits_type::int_type int_type; typedef typename traits_type::pos_type pos_type; typedef typename traits_type::off_type off_type; // Non-standard Types: typedef char_type * __array_type; typedef basic_arraybuf<_CharT, _Traits, _Alloc> __arraybuf_type; typedef std::basic_iostream __iostream_type; typedef typename _Traits::pos_type __size_type; private: __arraybuf_type _M_arraybuf; public: // Constructors/destructors /** * @brief Default constructor starts with an empty array buffer. * @param mode Whether the buffer can read, or write, or both. * * Initializes @c sb using @c mode, and passes @c &sb to the base * class initializer. Does not allocate any buffer. * * That's a lie. We initialize the base class with NULL, because the * array class does its own memory management. */ explicit basic_arraystream(ios_base::openmode __m = ios_base::out | ios_base::in) : __iostream_type(), _M_arraybuf(__m) { this->init(&_M_arraybuf); } /** * @brief Starts with an existing array buffer. * @param str A array to copy as a starting buffer. * @param mode Whether the buffer can read, or write, or both. * * Initializes @c sb using @a str and @c mode, and passes @c &sb * to the base class initializer. * * That's a lie. We initialize the base class with NULL, because the * array class does its own memory management. */ explicit basic_arraystream(const __array_type& __str, const __size_type __strlen, ios_base::openmode __m = ios_base::out | ios_base::in) : __iostream_type(), _M_arraybuf(__str, __strlen, __m) { this->init(&_M_arraybuf); } /** * @brief The destructor does nothing. * * The buffer is deallocated by the arraybuf object, not the * formatting stream. */ ~basic_arraystream() { } // Members: /** * @brief Accessing the underlying buffer. * @return The current basic_arraybuf buffer. * * This hides both signatures of std::basic_ios::rdbuf(). */ __arraybuf_type* rdbuf() const { return const_cast<__arraybuf_type*>(&_M_arraybuf); } /** * @brief Copying out the array buffer. * @return @c rdbuf()->data() */ __array_type data() const { return _M_arraybuf.data(); } /** * @brief Setting a new buffer. * @param s The array to use as a new sequence. * * Calls @c rdbuf()->str(s). */ void str(const __array_type& __s, const __size_type __l) { _M_arraybuf.str(__s, __l); } }; #include "mstream.tcc"