Home | History | Annotate | Download | only in bits
      1 // String based streams -*- C++ -*-
      2 
      3 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
      4 // 2006, 2007, 2008, 2009, 2010, 2011
      5 // Free Software Foundation, Inc.
      6 //
      7 // This file is part of the GNU ISO C++ Library.  This library is free
      8 // software; you can redistribute it and/or modify it under the
      9 // terms of the GNU General Public License as published by the
     10 // Free Software Foundation; either version 3, or (at your option)
     11 // any later version.
     12 
     13 // This library is distributed in the hope that it will be useful,
     14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16 // GNU General Public License for more details.
     17 
     18 // Under Section 7 of GPL version 3, you are granted additional
     19 // permissions described in the GCC Runtime Library Exception, version
     20 // 3.1, as published by the Free Software Foundation.
     21 
     22 // You should have received a copy of the GNU General Public License and
     23 // a copy of the GCC Runtime Library Exception along with this program;
     24 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     25 // <http://www.gnu.org/licenses/>.
     26 
     27 /** @file bits/sstream.tcc
     28  *  This is an internal header file, included by other library headers.
     29  *  Do not attempt to use it directly. @headername{sstream}
     30  */
     31 
     32 //
     33 // ISO C++ 14882: 27.7  String-based streams
     34 //
     35 
     36 #ifndef _SSTREAM_TCC
     37 #define _SSTREAM_TCC 1
     38 
     39 #pragma GCC system_header
     40 
     41 namespace std _GLIBCXX_VISIBILITY(default)
     42 {
     43 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     44 
     45   template <class _CharT, class _Traits, class _Alloc>
     46     typename basic_stringbuf<_CharT, _Traits, _Alloc>::int_type
     47     basic_stringbuf<_CharT, _Traits, _Alloc>::
     48     pbackfail(int_type __c)
     49     {
     50       int_type __ret = traits_type::eof();
     51       if (this->eback() < this->gptr())
     52 	{
     53 	  // Try to put back __c into input sequence in one of three ways.
     54 	  // Order these tests done in is unspecified by the standard.
     55 	  const bool __testeof = traits_type::eq_int_type(__c, __ret);
     56 	  if (!__testeof)
     57 	    {
     58 	      const bool __testeq = traits_type::eq(traits_type::
     59 						    to_char_type(__c),
     60 						    this->gptr()[-1]);	  
     61 	      const bool __testout = this->_M_mode & ios_base::out;
     62 	      if (__testeq || __testout)
     63 		{
     64 		  this->gbump(-1);
     65 		  if (!__testeq)
     66 		    *this->gptr() = traits_type::to_char_type(__c);
     67 		  __ret = __c;
     68 		}
     69 	    }
     70 	  else
     71 	    {
     72 	      this->gbump(-1);
     73 	      __ret = traits_type::not_eof(__c);
     74 	    }
     75 	}
     76       return __ret;
     77     }
     78 
     79   template <class _CharT, class _Traits, class _Alloc>
     80     typename basic_stringbuf<_CharT, _Traits, _Alloc>::int_type
     81     basic_stringbuf<_CharT, _Traits, _Alloc>::
     82     overflow(int_type __c)
     83     {
     84       const bool __testout = this->_M_mode & ios_base::out;
     85       if (__builtin_expect(!__testout, false))
     86 	return traits_type::eof();
     87 
     88       const bool __testeof = traits_type::eq_int_type(__c, traits_type::eof());
     89       if (__builtin_expect(__testeof, false))
     90 	return traits_type::not_eof(__c);
     91 
     92       const __size_type __capacity = _M_string.capacity();
     93       const __size_type __max_size = _M_string.max_size();
     94       const bool __testput = this->pptr() < this->epptr();
     95       if (__builtin_expect(!__testput && __capacity == __max_size, false))
     96 	return traits_type::eof();
     97 
     98       // Try to append __c into output sequence in one of two ways.
     99       // Order these tests done in is unspecified by the standard.
    100       const char_type __conv = traits_type::to_char_type(__c);
    101       if (!__testput)
    102 	{
    103 	  // NB: Start ostringstream buffers at 512 chars.  This is an
    104 	  // experimental value (pronounced "arbitrary" in some of the
    105 	  // hipper English-speaking countries), and can be changed to
    106 	  // suit particular needs.
    107 	  //
    108 	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
    109 	  // 169. Bad efficiency of overflow() mandated
    110 	  // 432. stringbuf::overflow() makes only one write position
    111 	  //      available
    112 	  const __size_type __opt_len = std::max(__size_type(2 * __capacity),
    113 						 __size_type(512));
    114 	  const __size_type __len = std::min(__opt_len, __max_size);
    115 	  __string_type __tmp;
    116 	  __tmp.reserve(__len);
    117 	  if (this->pbase())
    118 	    __tmp.assign(this->pbase(), this->epptr() - this->pbase());
    119 	  __tmp.push_back(__conv);
    120 	  _M_string.swap(__tmp);
    121 	  _M_sync(const_cast<char_type*>(_M_string.data()),
    122 		  this->gptr() - this->eback(), this->pptr() - this->pbase());
    123 	}
    124       else
    125 	*this->pptr() = __conv;
    126       this->pbump(1);
    127       return __c;
    128     }
    129 
    130   template <class _CharT, class _Traits, class _Alloc>
    131     typename basic_stringbuf<_CharT, _Traits, _Alloc>::int_type
    132     basic_stringbuf<_CharT, _Traits, _Alloc>::
    133     underflow()
    134     {
    135       int_type __ret = traits_type::eof();
    136       const bool __testin = this->_M_mode & ios_base::in;
    137       if (__testin)
    138 	{
    139 	  // Update egptr() to match the actual string end.
    140 	  _M_update_egptr();
    141 
    142 	  if (this->gptr() < this->egptr())
    143 	    __ret = traits_type::to_int_type(*this->gptr());
    144 	}
    145       return __ret;
    146     }
    147 
    148   template <class _CharT, class _Traits, class _Alloc>
    149     typename basic_stringbuf<_CharT, _Traits, _Alloc>::pos_type
    150     basic_stringbuf<_CharT, _Traits, _Alloc>::
    151     seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode)
    152     {
    153       pos_type __ret =  pos_type(off_type(-1));
    154       bool __testin = (ios_base::in & this->_M_mode & __mode) != 0;
    155       bool __testout = (ios_base::out & this->_M_mode & __mode) != 0;
    156       const bool __testboth = __testin && __testout && __way != ios_base::cur;
    157       __testin &= !(__mode & ios_base::out);
    158       __testout &= !(__mode & ios_base::in);
    159 
    160       // _GLIBCXX_RESOLVE_LIB_DEFECTS
    161       // 453. basic_stringbuf::seekoff need not always fail for an empty stream.
    162       const char_type* __beg = __testin ? this->eback() : this->pbase();
    163       if ((__beg || !__off) && (__testin || __testout || __testboth))
    164 	{
    165 	  _M_update_egptr();
    166 
    167 	  off_type __newoffi = __off;
    168 	  off_type __newoffo = __newoffi;
    169 	  if (__way == ios_base::cur)
    170 	    {
    171 	      __newoffi += this->gptr() - __beg;
    172 	      __newoffo += this->pptr() - __beg;
    173 	    }
    174 	  else if (__way == ios_base::end)
    175 	    __newoffo = __newoffi += this->egptr() - __beg;
    176 
    177 	  if ((__testin || __testboth)
    178 	      && __newoffi >= 0
    179 	      && this->egptr() - __beg >= __newoffi)
    180 	    {
    181 	      this->setg(this->eback(), this->eback() + __newoffi,
    182 			 this->egptr());
    183 	      __ret = pos_type(__newoffi);
    184 	    }
    185 	  if ((__testout || __testboth)
    186 	      && __newoffo >= 0
    187 	      && this->egptr() - __beg >= __newoffo)
    188 	    {
    189 	      _M_pbump(this->pbase(), this->epptr(), __newoffo);
    190 	      __ret = pos_type(__newoffo);
    191 	    }
    192 	}
    193       return __ret;
    194     }
    195 
    196   template <class _CharT, class _Traits, class _Alloc>
    197     typename basic_stringbuf<_CharT, _Traits, _Alloc>::pos_type
    198     basic_stringbuf<_CharT, _Traits, _Alloc>::
    199     seekpos(pos_type __sp, ios_base::openmode __mode)
    200     {
    201       pos_type __ret =  pos_type(off_type(-1));
    202       const bool __testin = (ios_base::in & this->_M_mode & __mode) != 0;
    203       const bool __testout = (ios_base::out & this->_M_mode & __mode) != 0;
    204 
    205       const char_type* __beg = __testin ? this->eback() : this->pbase();
    206       if ((__beg || !off_type(__sp)) && (__testin || __testout))
    207 	{
    208 	  _M_update_egptr();
    209 
    210 	  const off_type __pos(__sp);
    211 	  const bool __testpos = (0 <= __pos
    212 				  && __pos <= this->egptr() - __beg);
    213 	  if (__testpos)
    214 	    {
    215 	      if (__testin)
    216 		this->setg(this->eback(), this->eback() + __pos,
    217 			   this->egptr());
    218 	      if (__testout)
    219 		_M_pbump(this->pbase(), this->epptr(), __pos);
    220 	      __ret = __sp;
    221 	    }
    222 	}
    223       return __ret;
    224     }
    225 
    226   template <class _CharT, class _Traits, class _Alloc>
    227     void
    228     basic_stringbuf<_CharT, _Traits, _Alloc>::
    229     _M_sync(char_type* __base, __size_type __i, __size_type __o)
    230     {
    231       const bool __testin = _M_mode & ios_base::in;
    232       const bool __testout = _M_mode & ios_base::out;
    233       char_type* __endg = __base + _M_string.size();
    234       char_type* __endp = __base + _M_string.capacity();
    235 
    236       if (__base != _M_string.data())
    237 	{
    238 	  // setbuf: __i == size of buffer area (_M_string.size() == 0).
    239 	  __endg += __i;
    240 	  __i = 0;
    241 	  __endp = __endg;
    242 	}
    243 
    244       if (__testin)
    245 	this->setg(__base, __base + __i, __endg);
    246       if (__testout)
    247 	{
    248 	  _M_pbump(__base, __endp, __o);
    249 	  // egptr() always tracks the string end.  When !__testin,
    250 	  // for the correct functioning of the streambuf inlines
    251 	  // the other get area pointers are identical.
    252 	  if (!__testin)
    253 	    this->setg(__endg, __endg, __endg);
    254 	}
    255     }
    256 
    257   template <class _CharT, class _Traits, class _Alloc>
    258     void
    259     basic_stringbuf<_CharT, _Traits, _Alloc>::
    260     _M_pbump(char_type* __pbeg, char_type* __pend, off_type __off)
    261     {
    262       this->setp(__pbeg, __pend);
    263       while (__off > __gnu_cxx::__numeric_traits<int>::__max)
    264 	{
    265 	  this->pbump(__gnu_cxx::__numeric_traits<int>::__max);
    266 	  __off -= __gnu_cxx::__numeric_traits<int>::__max;
    267 	}
    268       this->pbump(__off);
    269     }
    270 
    271   // Inhibit implicit instantiations for required instantiations,
    272   // which are defined via explicit instantiations elsewhere.
    273 #if _GLIBCXX_EXTERN_TEMPLATE
    274   extern template class basic_stringbuf<char>;
    275   extern template class basic_istringstream<char>;
    276   extern template class basic_ostringstream<char>;
    277   extern template class basic_stringstream<char>;
    278 
    279 #ifdef _GLIBCXX_USE_WCHAR_T
    280   extern template class basic_stringbuf<wchar_t>;
    281   extern template class basic_istringstream<wchar_t>;
    282   extern template class basic_ostringstream<wchar_t>;
    283   extern template class basic_stringstream<wchar_t>;
    284 #endif
    285 #endif
    286 
    287 _GLIBCXX_END_NAMESPACE_VERSION
    288 } // namespace std
    289 
    290 #endif
    291