// -*- C++ -*-
/***************************************************************************
 *
 * sstream - Declarations for the Standard Library basic streams
 *
 * $Id$
 *
 ***************************************************************************
 *
 * Copyright (c) 1994-2001 Rogue Wave Software, Inc.  All Rights Reserved.
 *
 * This computer software is owned by Rogue Wave Software, Inc. and is
 * protected by U.S. copyright laws and other laws and by international
 * treaties.  This computer software is furnished by Rogue Wave Software,
 * Inc. pursuant to a written license agreement and may be used, copied,
 * transmitted, and stored only in accordance with the terms of such
 * license and with the inclusion of the above copyright notice.  This
 * computer software or any other copies thereof may not be provided or
 * otherwise made available to any other person.
 *
 * U.S. Government Restricted Rights.  This computer software is provided
 * with Restricted Rights.  Use, duplication, or disclosure by the
 * Government is subject to restrictions as set forth in subparagraph (c)
 * (1) (ii) of The Rights in Technical Data and Computer Software clause
 * at DFARS 252.227-7013 or subparagraphs (c) (1) and (2) of the
 * Commercial Computer Software--Restricted Rights at 48 CFR 52.227-19,
 * as applicable.  Manufacturer is Rogue Wave Software, Inc., 5500
 * Flatiron Parkway, Boulder, Colorado 80301 USA.
 *
 **************************************************************************/

#ifndef _RWSTD_SSTREAM_INCLUDED
#define _RWSTD_SSTREAM_INCLUDED

#ifndef _RWSTD_NO_REDUNDANT_DEFINITIONS
#  include <istream>
#  include <ostream>
#else
#  include <iosfwd>
#endif   // _RWSTD_NO_REDUNDANT_DEFINITIONS

#include <rw/_iosbase.h>
#include <rw/_defs.h>


_RWSTD_NAMESPACE_BEGIN (std)


template<class _CharT, class _Traits, class _Allocator>
class basic_stringbuf: public basic_streambuf<_CharT, _Traits>
{
    typedef basic_string<_CharT, _Traits, _Allocator> _C_string_type;

public:

    typedef _CharT                          char_type;
    typedef _Traits                         traits_type;
    typedef _Allocator                      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;

    _EXPLICIT
    basic_stringbuf (ios_base::openmode __mode = ios_base::in | ios_base::out)
        : basic_streambuf<char_type, traits_type>(__mode) {
        this->_C_own_buf (true);
    }

    _EXPLICIT
    basic_stringbuf (const _C_string_type &__str, 
                     ios_base::openmode = ios_base::in | ios_base::out);
    
    virtual ~basic_stringbuf ();
    
    _C_string_type str () const {
        return _C_strlen () == 0 ? _C_string_type ()
            : _C_string_type (this->_C_buffer, _C_strlen ());
    }
    
    void str (const _C_string_type&);
    
protected:
    
    virtual streamsize showmanyc () {
        return this->gptr () < this->egptr () ?
            streamsize (this->egptr () - this->gptr ()) : 0;
    }
    
    virtual int_type overflow (int_type = traits_type::eof ());

    virtual int_type pbackfail (int_type = traits_type::eof ());

    virtual int_type underflow ();
    
    virtual pos_type seekoff (off_type, ios_base::seekdir, ios_base::openmode =
                              ios_base::in | ios_base::out);
    
    virtual pos_type seekpos (pos_type, ios_base::openmode =
                              ios_base::in | ios_base::out);

    virtual basic_streambuf<char_type, traits_type>*
    setbuf (char_type*, streamsize);

    virtual streamsize xsputn (const char_type*, streamsize);

    //
    // non-standard convenience functions
    //
    streamsize _C_strlen () const {
        return this->_C_is_in () ? this->egptr () - this->eback ()
                                 : this->epptr () - this->pbase ();
    }

};


template<class _CharT, class _Traits, class _Allocator>
inline basic_stringbuf<_CharT, _Traits, _Allocator>::~basic_stringbuf ()
{
    typedef _RWSTD_ALLOC_TYPE (allocator_type, char_type) _ValueAlloc;

    if (this->_C_own_buf ())
        _ValueAlloc ().deallocate (this->_C_buffer, this->_C_bufsize);
}


template<class _CharT, class _Traits, class _Allocator>
class basic_istringstream: public basic_istream<_CharT, _Traits>
{
    typedef basic_string<_CharT, _Traits, _Allocator> _C_string_type;

public:
    typedef _CharT                           char_type;
    typedef _Traits                          traits_type;
    typedef _Allocator                       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;
  
    _EXPLICIT
    basic_istringstream (ios_base::openmode __mode = ios_base::in)
        : basic_istream<char_type, traits_type>(rdbuf ()),
          _C_sb (__mode | ios_base::in) { }

    _EXPLICIT
    basic_istringstream (const _C_string_type& __str, 
                         ios_base::openmode __mode = ios_base::in)
        : basic_istream<char_type, traits_type>(rdbuf ()),
          _C_sb (__str, __mode | ios_base::in) { }

    basic_stringbuf<char_type, traits_type, allocator_type> *rdbuf () const {
        // necessary to help SunPro 5.0/T9
        typedef basic_istringstream <char_type, traits_type, allocator_type>
            _SelfT;
        return &_RWSTD_CONST_CAST (_SelfT*, this)->_C_sb;
    }

    _C_string_type str () const {
        return rdbuf ()->str ();
    }

    void str (const _C_string_type& __str) {
        rdbuf ()->str (__str);
    }

private:

    basic_stringbuf<char_type, traits_type, allocator_type> _C_sb;
};


template<class _CharT, class _Traits, class _Allocator>
class basic_ostringstream: public basic_ostream<_CharT, _Traits>
{
    typedef basic_string<_CharT, _Traits, _Allocator> _C_string_type;

public:

    typedef _CharT                          char_type;
    typedef _Traits                         traits_type;
    typedef _Allocator                      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;

    // NOTE: the constructors pass the address of a yet uninitialized
    //       data member to the constructor of the base class
    _EXPLICIT
    basic_ostringstream (ios_base::openmode __mode = ios_base::out)
        : basic_ostream<char_type, traits_type> (rdbuf ()),
          _C_sb (__mode | ios_base::out) { }
        
    _EXPLICIT
    basic_ostringstream (const _C_string_type  &__str, 
                         ios_base::openmode  __mode = ios_base::out)
        : basic_ostream<char_type, traits_type>(rdbuf ()),
          _C_sb (__str, __mode | ios_base::out) { }

    basic_stringbuf<char_type, traits_type, allocator_type>* rdbuf () const {
        // necessary to help SunPro 5.0/T9
        typedef basic_ostringstream <char_type, traits_type, allocator_type>
            _SelfT;
        return &_RWSTD_CONST_CAST (_SelfT*, this)->_C_sb;
    }

    _C_string_type str () const {
        return rdbuf ()->str ();
    }

    void str (const _C_string_type &__str) {
        rdbuf ()->str (__str);
    }

private:

    basic_stringbuf<char_type, traits_type, allocator_type> _C_sb;
};


template<class _CharT, class _Traits, class _Allocator>
class basic_stringstream: public basic_iostream<_CharT, _Traits>
{
    typedef basic_string<_CharT, _Traits, _Allocator> _C_string_type;

public:

    typedef _CharT                          char_type;
    typedef _Traits                         traits_type;
    typedef _Allocator                      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;

    _EXPLICIT
    basic_stringstream (ios_base::openmode __mode =
                        ios_base::out | ios_base::in)
        : basic_iostream<char_type, traits_type>(rdbuf ()),
          _C_sb (__mode) { }

    _EXPLICIT
    basic_stringstream (const _C_string_type &__str, 
                        ios_base::openmode __mode = 
                        ios_base::out | ios_base::in)
        : basic_iostream<char_type, traits_type>(rdbuf ()),
          _C_sb (__str, __mode) { }

    basic_stringbuf<char_type, traits_type, allocator_type> *rdbuf () const {
        // necessary to help SunPro 5.0/T9
        typedef basic_stringstream <char_type, traits_type, allocator_type>
            _SelfT;
        return &_RWSTD_CONST_CAST (_SelfT*, this)->_C_sb;
    }

    _C_string_type str () const {
        return rdbuf ()->str ();
    }

    void str (const _C_string_type &__str) {
        rdbuf ()->str (__str);
    }

private:

    basic_stringbuf<char_type, traits_type, allocator_type> _C_sb;
};


_RWSTD_INSTANTIATE_3 (class _RWSTD_EXPORT
                      basic_stringbuf<char, char_traits<char>,
                                      allocator<char> >);

#ifndef _RWSTD_NO_WCHAR_T
_RWSTD_INSTANTIATE_3 (class _RWSTD_EXPORT
                      basic_stringbuf<wchar_t, char_traits<wchar_t>,
                                      allocator<wchar_t> >);
#endif   // _RWSTD_NO_WCHAR_T


_RWSTD_NAMESPACE_END   // std


#if _RWSTD_DEFINE_TEMPLATE (BASIC_STRINGBUF)
#  include <sstream.cc>
#endif


#endif   // _RWSTD_SSTREAM_INCLUDED

