home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / stlpt453.zip / STLport-4.5.3 / stlport / stl / _sstream.c < prev    next >
C/C++ Source or Header  |  2002-02-02  |  16KB  |  544 lines

  1. /*
  2.  * Copyright (c) 1999
  3.  * Silicon Graphics Computer Systems, Inc.
  4.  *
  5.  * Copyright (c) 1999 
  6.  * Boris Fomitchev
  7.  *
  8.  * This material is provided "as is", with absolutely no warranty expressed
  9.  * or implied. Any use is at your own risk.
  10.  *
  11.  * Permission to use or copy this software for any purpose is hereby granted 
  12.  * without fee, provided the above notices are retained on all copies.
  13.  * Permission to modify the code and to distribute modified code is granted,
  14.  * provided the above notices are retained, and a notice that the code was
  15.  * modified is included with the above copyright notice.
  16.  *
  17.  */ 
  18.  
  19. #ifndef _STLP_SSTREAM_C
  20. #define _STLP_SSTREAM_C
  21.  
  22. #ifndef _STLP_SSTREAM_H
  23. # include <stl/_sstream.h>
  24. #endif
  25.  
  26. # if defined (_STLP_EXPOSE_STREAM_IMPLEMENTATION)
  27.  
  28. # if defined ( _STLP_NESTED_TYPE_PARAM_BUG )
  29. // no wint_t is supported for this mode
  30. # define __BSB_int_type__ int
  31. # define __BSB_pos_type__ streampos
  32. # else
  33. # define __BSB_int_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_stringbuf<_CharT, _Traits, _Alloc>::int_type
  34. # define __BSB_pos_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_stringbuf<_CharT, _Traits, _Alloc>::pos_type
  35. # endif
  36.  
  37. _STLP_BEGIN_NAMESPACE
  38.  
  39. //----------------------------------------------------------------------
  40. // Non-inline stringbuf member functions.
  41.  
  42. // Constructors.  Note that the base class constructor sets all of the
  43. // get and area pointers to null.
  44.  
  45. template <class _CharT, class _Traits, class _Alloc>
  46. basic_stringbuf<_CharT, _Traits, _Alloc>
  47.   ::basic_stringbuf(ios_base::openmode __mode)
  48.     : basic_streambuf<_CharT, _Traits>(), _M_mode(__mode), _M_str()
  49. {}
  50.  
  51. template <class _CharT, class _Traits, class _Alloc>
  52. basic_stringbuf<_CharT, _Traits, _Alloc>
  53.   ::basic_stringbuf(const basic_string<_CharT, _Traits, _Alloc>& __s, ios_base::openmode __mode)
  54.     : basic_streambuf<_CharT, _Traits>(), _M_mode(__mode), _M_str(__s)
  55. {
  56.   _M_set_ptrs();
  57. }
  58.  
  59. template <class _CharT, class _Traits, class _Alloc>
  60. basic_stringbuf<_CharT, _Traits, _Alloc>::~basic_stringbuf()
  61. {}
  62.  
  63. // Set the underlying string to a new value.
  64. template <class _CharT, class _Traits, class _Alloc>
  65. void 
  66. basic_stringbuf<_CharT, _Traits, _Alloc>::str(const basic_string<_CharT, _Traits, _Alloc>& __s)
  67. {
  68.   _M_str = __s;
  69.   _M_set_ptrs();
  70. }
  71.  
  72. template <class _CharT, class _Traits, class _Alloc>
  73. void 
  74. basic_stringbuf<_CharT, _Traits, _Alloc>::_M_set_ptrs() {
  75.   _CharT* __data_ptr = __CONST_CAST(_CharT*,_M_str.data());
  76.   _CharT* __data_end = __data_ptr + _M_str.size();
  77.   // The initial read position is the beginning of the string.
  78.   if (_M_mode & ios_base::in)
  79.     this->setg(__data_ptr, __data_ptr, __data_end);
  80.   
  81.   // The initial write position is the beginning of the string.
  82.   if (_M_mode & ios_base::out) {
  83.     if (_M_mode & ios_base::app)
  84.       this->setp(__data_end, __data_end);
  85.     else
  86.       this->setp(__data_ptr, __data_end);
  87.   }
  88. }
  89.  
  90. // Precondition: gptr() >= egptr().  Returns a character, if one is available.
  91. template <class _CharT, class _Traits, class _Alloc>
  92. __BSB_int_type__
  93. basic_stringbuf<_CharT, _Traits, _Alloc>::underflow()
  94. {
  95.   return this->gptr() != this->egptr()
  96.     ? _Traits::to_int_type(*this->gptr())
  97.     : _Traits::eof();
  98. }
  99.  
  100. // Precondition: gptr() >= egptr().
  101. template <class _CharT, class _Traits, class _Alloc>
  102. __BSB_int_type__
  103. basic_stringbuf<_CharT, _Traits, _Alloc>::uflow()
  104. {
  105.   if (this->gptr() != this->egptr()) {
  106.     int_type __c = _Traits::to_int_type(*this->gptr());
  107.     this->gbump(1);
  108.     return __c;
  109.   }
  110.   else
  111.     return _Traits::eof();
  112. }
  113.  
  114. template <class _CharT, class _Traits, class _Alloc>
  115. __BSB_int_type__
  116. basic_stringbuf<_CharT, _Traits, _Alloc>::pbackfail(int_type __c)
  117. {
  118.   if (this->gptr() != this->eback()) {
  119.     if (!_Traits::eq_int_type(__c, _Traits::eof())) {
  120.       if (_Traits::eq(_Traits::to_char_type(__c), this->gptr()[-1])) {
  121.         this->gbump(-1);
  122.         return __c;
  123.       }
  124.       else if (_M_mode & ios_base::out) {
  125.         this->gbump(-1);
  126.         *this->gptr() = __c;
  127.         return __c;
  128.       }
  129.       else
  130.         return _Traits::eof();
  131.     }
  132.     else {
  133.       this->gbump(-1);
  134.       return _Traits::not_eof(__c);
  135.     }
  136.   }
  137.   else
  138.     return _Traits::eof();
  139. }
  140.  
  141. template <class _CharT, class _Traits, class _Alloc>
  142. __BSB_int_type__
  143. basic_stringbuf<_CharT, _Traits, _Alloc>::overflow(int_type __c)
  144. {
  145.   // fbp : reverse order of "ifs" to pass Dietmar's test.
  146.   // Apparently, standard allows overflow with eof even for read-only streams.
  147.   if (!_Traits::eq_int_type(__c, _Traits::eof())) {
  148.     if (_M_mode & ios_base::out) {
  149.       if (!(_M_mode & ios_base::in)) {
  150.         // It's a write-only streambuf, so we can use special append buffer.
  151.         if (this->pptr() == this->epptr())
  152.           this->_M_append_buffer();
  153.       
  154.         if (this->pptr() != this->epptr()) {
  155.           *this->pptr() = _Traits::to_char_type(__c);
  156.           this->pbump(1);
  157.           return __c;
  158.         }
  159.         else
  160.           return _Traits::eof();
  161.       }
  162.  
  163.       else {
  164.         // We're not using a special append buffer, just the string itself.
  165.         if (this->pptr() == this->epptr()) {
  166.           ptrdiff_t __offset = this->gptr() - this->eback();
  167.           _M_str.push_back(_Traits::to_char_type(__c));
  168.  
  169.       _CharT* __data_ptr = __CONST_CAST(_CharT*,_M_str.data());
  170.       size_t __data_size = _M_str.size();
  171.  
  172.           this->setg(__data_ptr, __data_ptr + __offset, __data_ptr+__data_size);
  173.           this->setp(__data_ptr, __data_ptr + __data_size);
  174.           this->pbump((int)__data_size);
  175.           return __c;
  176.         }
  177.         else {
  178.           *this->pptr() = _Traits::to_char_type(__c);
  179.           this->pbump(1);
  180.           return __c;
  181.         }
  182.       }
  183.     }
  184.     else                          // Overflow always fails if it's read-only 
  185.       return _Traits::eof();
  186.   }
  187.   else                        // __c is EOF, so we don't have to do anything
  188.     return _Traits::not_eof(__c);
  189. }
  190.  
  191. template <class _CharT, class _Traits, class _Alloc>
  192. streamsize 
  193. basic_stringbuf<_CharT, _Traits, _Alloc>::xsputn(const char_type* __s,
  194.                                                  streamsize __n)
  195. {
  196.   streamsize __nwritten = 0;
  197.  
  198.   if ((_M_mode & ios_base::out) && __n > 0) {
  199.     // If the put pointer is somewhere in the middle of the string,
  200.     // then overwrite instead of append.
  201.     if (this->pbase() == _M_str.data() ) {
  202.       ptrdiff_t __avail = _M_str.data() + _M_str.size() - this->pptr();
  203.       if (__avail > __n) {
  204.         _Traits::copy(this->pptr(), __s, __n);
  205.         this->pbump((int)__n);
  206.         return __n;
  207.       }
  208.       else {
  209.         _Traits::copy(this->pptr(), __s, __avail);
  210.         __nwritten += __avail;
  211.         __n -= __avail;
  212.         __s += __avail;
  213.         this->setp(_M_Buf, _M_Buf + __STATIC_CAST(int,_S_BufSiz));
  214.       }
  215.     }
  216.  
  217.     // At this point we know we're appending.
  218.     if (_M_mode & ios_base::in) {
  219.       ptrdiff_t __get_offset = this->gptr() - this->eback();
  220.       _M_str.append(__s, __s + __n);
  221.       
  222.       _CharT* __data_ptr = __CONST_CAST(_CharT*,_M_str.data());
  223.       size_t __data_size = _M_str.size();
  224.  
  225.       this->setg(__data_ptr, __data_ptr + __get_offset, __data_ptr+__data_size);
  226.       this->setp(__data_ptr, __data_ptr + __data_size);
  227.       this->pbump((int)__data_size);
  228.     }
  229.     else {
  230.       _M_append_buffer();
  231.       _M_str.append(__s, __s + __n);
  232.     }
  233.  
  234.     __nwritten += __n;
  235.   }
  236.  
  237.   return __nwritten;
  238. }
  239.  
  240. template <class _CharT, class _Traits, class _Alloc>
  241. streamsize 
  242. basic_stringbuf<_CharT, _Traits, _Alloc>::_M_xsputnc(char_type __c,
  243.                                                      streamsize __n)
  244. {
  245.   streamsize __nwritten = 0;
  246.  
  247.   if ((_M_mode & ios_base::out) && __n > 0) {
  248.     // If the put pointer is somewhere in the middle of the string,
  249.     // then overwrite instead of append.
  250.     if (this->pbase() == _M_str.data()) {
  251.       ptrdiff_t __avail = _M_str.data() + _M_str.size() - this->pptr();
  252.       if (__avail > __n) {
  253.         _Traits::assign(this->pptr(), __n, __c);
  254.         this->pbump((int)__n);
  255.         return __n;
  256.       }
  257.       else {
  258.         _Traits::assign(this->pptr(), __avail, __c);
  259.         __nwritten += __avail;
  260.         __n -= __avail;
  261.         this->setp(_M_Buf, _M_Buf + __STATIC_CAST(int,_S_BufSiz));
  262.       }
  263.     }
  264.  
  265.     // At this point we know we're appending.
  266.     if (this->_M_mode & ios_base::in) {
  267.       ptrdiff_t __get_offset = this->gptr() - this->eback();
  268.       _M_str.append(__n, __c);
  269.  
  270.       _CharT* __data_ptr = __CONST_CAST(_CharT*,_M_str.data());
  271.       size_t __data_size = _M_str.size();
  272.  
  273.       this->setg(__data_ptr, __data_ptr + __get_offset, __data_ptr+__data_size);
  274.       this->setp(__data_ptr, __data_ptr + __data_size);
  275.       this->pbump((int)__data_size);
  276.  
  277.     }
  278.     else {
  279.       _M_append_buffer();
  280.       _M_str.append(__n, __c);      
  281.     }
  282.  
  283.     __nwritten += __n;
  284.   }
  285.  
  286.   return __nwritten;
  287. }
  288.  
  289. // According to the C++ standard the effects of setbuf are implementation
  290. // defined, except that setbuf(0, 0) has no effect.  In this implementation,
  291. // setbuf(<anything>, n), for n > 0, calls reserve(n) on the underlying
  292. // string.
  293. template <class _CharT, class _Traits, class _Alloc>
  294. basic_streambuf<_CharT, _Traits>*
  295. basic_stringbuf<_CharT, _Traits, _Alloc>::setbuf(_CharT*, streamsize __n)
  296. {
  297.   if (__n > 0) {
  298.     bool __do_get_area = false;
  299.     bool __do_put_area = false;
  300.     ptrdiff_t __offg = 0;
  301.     ptrdiff_t __offp = 0;
  302.  
  303.     if (this->pbase() == _M_str.data()) {
  304.       __do_put_area = true;
  305.       __offp = this->pptr() - this->pbase();
  306.     }
  307.  
  308.     if (this->eback() == _M_str.data()) {
  309.       __do_get_area = true;
  310.       __offg = this->gptr() - this->eback();
  311.     }
  312.  
  313.     if ((_M_mode & ios_base::out) && !(_M_mode & ios_base::in))
  314.       _M_append_buffer();
  315.  
  316.     _M_str.reserve(__n);
  317.  
  318.     _CharT* __data_ptr = __CONST_CAST(_CharT*,_M_str.data());
  319.     size_t __data_size = _M_str.size();
  320.  
  321.     if (__do_get_area) {
  322.       this->setg(__data_ptr, __data_ptr + __offg, __data_ptr+__data_size);
  323.     }
  324.  
  325.     if (__do_put_area) {
  326.       this->setp(__data_ptr, __data_ptr+__data_size);
  327.       this->pbump((int)__offp);
  328.     }
  329.   }
  330.  
  331.   return this;
  332. }
  333.  
  334. template <class _CharT, class _Traits, class _Alloc>
  335. __BSB_pos_type__
  336. basic_stringbuf<_CharT, _Traits, _Alloc>::seekoff(off_type __off, 
  337.             ios_base::seekdir __dir,
  338.             ios_base::openmode __mode)
  339. {
  340.   bool __in  = false;
  341.   bool __out = false;
  342.   
  343.   if ((__mode & (ios_base::in | ios_base::out)) == (ios_base::in | ios_base::out) ) {
  344.     if (__dir == ios_base::beg || __dir == ios_base::end)
  345.       __in = __out = true;
  346.   }
  347.   else if (__mode & ios_base::in)
  348.     __in = true;
  349.   else if (__mode & ios_base::out)
  350.     __out = true;
  351.  
  352.   if (!__in && !__out)
  353.     return pos_type(off_type(-1));
  354.   else if ((__in  && (!(_M_mode & ios_base::in) || this->gptr() == 0)) ||
  355.            (__out && (!(_M_mode & ios_base::out) || this->pptr() == 0)))
  356.     return pos_type(off_type(-1));
  357.  
  358.   if ((_M_mode & ios_base::out) && !(_M_mode & ios_base::in))
  359.     _M_append_buffer();
  360.  
  361.   streamoff __newoff;
  362.   switch(__dir) {
  363.   case ios_base::beg:
  364.     __newoff = 0;
  365.     break;
  366.   case ios_base::end:
  367.     __newoff = _M_str.size();
  368.     break;
  369.   case ios_base::cur:
  370.     __newoff = __in ? this->gptr() - this->eback() 
  371.                     : this->pptr() - this->pbase();
  372.     break;
  373.   default:
  374.     return pos_type(off_type(-1));
  375.   }
  376.  
  377.   __off += __newoff;
  378.  
  379.   if (__in) {
  380.     ptrdiff_t __n = this->egptr() - this->eback();
  381.  
  382.     if (__off < 0 || __off > __n)
  383.       return pos_type(off_type(-1));
  384.     else
  385.       this->setg(this->eback(), this->eback() + __off, this->eback() + __n);
  386.   }
  387.  
  388.   if (__out) {
  389.     ptrdiff_t __n = this->epptr() - this->pbase();
  390.  
  391.     if (__off < 0 || __off > __n)
  392.       return pos_type(off_type(-1));
  393.     else {
  394.       this->setp(this->pbase(), this->pbase() + __n);
  395.       this->pbump((int)__off);
  396.     }
  397.   }
  398.  
  399.   return pos_type(__off);
  400. }
  401.  
  402. template <class _CharT, class _Traits, class _Alloc>
  403. __BSB_pos_type__
  404. basic_stringbuf<_CharT, _Traits, _Alloc>
  405.   ::seekpos(pos_type __pos, ios_base::openmode __mode)
  406. {
  407.   bool __in  = (__mode & ios_base::in) != 0;
  408.   bool __out = (__mode & ios_base::out) != 0;
  409.  
  410.   if ((__in  && (!(_M_mode & ios_base::in) || this->gptr() == 0)) ||
  411.       (__out && (!(_M_mode & ios_base::out) || this->pptr() == 0)))
  412.     return pos_type(off_type(-1));
  413.  
  414.   const off_type __n = __pos - pos_type(off_type(0));
  415.   if ((_M_mode & ios_base::out) && !(_M_mode & ios_base::in))
  416.     _M_append_buffer();
  417.  
  418.   if (__in) {
  419.     if (__n < 0 || __n > this->egptr() - this->eback())
  420.       return pos_type(off_type(-1));
  421.     this->setg(this->eback(), this->eback() + __n, this->egptr());
  422.   }
  423.  
  424.   if (__out) {
  425.     if (__n < 0 || size_t(__n) > _M_str.size())
  426.       return pos_type(off_type(-1));
  427.  
  428.     _CharT* __data_ptr = __CONST_CAST(_CharT*,_M_str.data());
  429.     size_t __data_size = _M_str.size();
  430.     
  431.     this->setp(__data_ptr, __data_ptr+__data_size);
  432.     this->pbump((int)__n);
  433.   }
  434.  
  435.   return __pos;
  436. }
  437.  
  438. // This is declared as a const member function because it is 
  439. // called by basic_stringbuf<>::str().  Precondition: this is a
  440. // write-only stringbuf.  We can't use an output buffer for read-
  441. // write stringbufs.  Postcondition: pptr is reset to the beginning
  442. // of the buffer.
  443. template <class _CharT, class _Traits, class _Alloc>
  444. void basic_stringbuf<_CharT, _Traits, _Alloc>::_M_append_buffer() const
  445.  
  446. {
  447.   // Do we have a buffer to append?
  448.   if (this->pbase() == this->_M_Buf && this->pptr() != this->_M_Buf) {
  449.     basic_stringbuf<_CharT, _Traits, _Alloc>* __this = __CONST_CAST(_Self*,this);
  450.     __this->_M_str.append((const _CharT*)this->pbase(), (const _CharT*)this->pptr());
  451.     __this->setp(__CONST_CAST(_CharT*,_M_Buf),
  452.                  __CONST_CAST(_CharT*,_M_Buf + __STATIC_CAST(int,_S_BufSiz)));
  453.   }
  454.  
  455.   // Have we run off the end of the string?
  456.   else if (this->pptr() == this->epptr()) {
  457.     basic_stringbuf<_CharT, _Traits, _Alloc>* __this = __CONST_CAST(_Self*,this);
  458.     __this->setp(__CONST_CAST(_CharT*,_M_Buf),
  459.                  __CONST_CAST(_CharT*,_M_Buf + __STATIC_CAST(int,_S_BufSiz)));
  460.   }
  461. }
  462.  
  463. //----------------------------------------------------------------------
  464. // Non-inline istringstream member functions.
  465.  
  466. template <class _CharT, class _Traits, class _Alloc>
  467. basic_istringstream<_CharT, _Traits, _Alloc>
  468.   ::basic_istringstream(ios_base::openmode __mode)
  469.     : basic_istream<_CharT, _Traits>(0),
  470.       _M_buf(__mode | ios_base::in)
  471. {
  472.   this->init(&_M_buf);
  473. }
  474.  
  475. template <class _CharT, class _Traits, class _Alloc>
  476. basic_istringstream<_CharT, _Traits, _Alloc>
  477.   ::basic_istringstream(const _String& __str,ios_base::openmode __mode)
  478.     : basic_istream<_CharT, _Traits>(0),
  479.       _M_buf(__str, __mode | ios_base::in)
  480. {
  481.   this->init(&_M_buf);
  482. }
  483.  
  484. template <class _CharT, class _Traits, class _Alloc>
  485. basic_istringstream<_CharT, _Traits, _Alloc>::~basic_istringstream()
  486. {}
  487.  
  488. //----------------------------------------------------------------------
  489. // Non-inline ostringstream member functions.
  490.  
  491. template <class _CharT, class _Traits, class _Alloc>
  492. basic_ostringstream<_CharT, _Traits, _Alloc>
  493.   ::basic_ostringstream(ios_base::openmode __mode)
  494.     : basic_ostream<_CharT, _Traits>(0),
  495.       _M_buf(__mode | ios_base::out)
  496. {
  497.   this->init(&_M_buf);
  498. }
  499.   
  500. template <class _CharT, class _Traits, class _Alloc>
  501. basic_ostringstream<_CharT, _Traits, _Alloc>
  502.   ::basic_ostringstream(const _String& __str, ios_base::openmode __mode)
  503.     : basic_ostream<_CharT, _Traits>(0),
  504.       _M_buf(__str, __mode | ios_base::out)
  505. {
  506.   this->init(&_M_buf);
  507. }
  508.  
  509. template <class _CharT, class _Traits, class _Alloc>
  510. basic_ostringstream<_CharT, _Traits, _Alloc>::~basic_ostringstream()
  511. {}
  512.  
  513. //----------------------------------------------------------------------
  514. // Non-inline stringstream member functions.
  515.  
  516. template <class _CharT, class _Traits, class _Alloc>
  517. basic_stringstream<_CharT, _Traits, _Alloc>
  518.   ::basic_stringstream(ios_base::openmode __mode)
  519.     : basic_iostream<_CharT, _Traits>(0), _M_buf(__mode)
  520. {
  521.    this->init(&_M_buf);
  522. }
  523.  
  524. template <class _CharT, class _Traits, class _Alloc>
  525. basic_stringstream<_CharT, _Traits, _Alloc>
  526.   ::basic_stringstream(const _String& __str, ios_base::openmode __mode)
  527.     : basic_iostream<_CharT, _Traits>(0), _M_buf(__str, __mode)
  528. {
  529.   this->init(&_M_buf);
  530. }
  531.  
  532. template <class _CharT, class _Traits, class _Alloc>
  533. basic_stringstream<_CharT, _Traits, _Alloc>::~basic_stringstream()
  534. {}
  535.  
  536. _STLP_END_NAMESPACE
  537.  
  538. # undef __BSB_int_type__
  539. # undef __BSB_pos_type__
  540.  
  541. # endif /* EXPOSE */
  542.  
  543. #endif /* _STLP_SSTREAM_C */
  544.