Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // Stream buffer classes -*- C++ -*-
  2.  
  3. // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
  4. //
  5. // This file is part of the GNU ISO C++ Library.  This library is free
  6. // software; you can redistribute it and/or modify it under the
  7. // terms of the GNU General Public License as published by the
  8. // Free Software Foundation; either version 2, or (at your option)
  9. // any later version.
  10.  
  11. // This library is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. // GNU General Public License for more details.
  15.  
  16. // You should have received a copy of the GNU General Public License along
  17. // with this library; see the file COPYING.  If not, write to the Free
  18. // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  19. // USA.
  20.  
  21. // As a special exception, you may use this file as part of a free software
  22. // library without restriction.  Specifically, if other files instantiate
  23. // templates or use macros or inline functions from this file, or you compile
  24. // this file and link it with other files to produce an executable, this
  25. // file does not by itself cause the resulting executable to be covered by
  26. // the GNU General Public License.  This exception does not however
  27. // invalidate any other reasons why the executable file might be covered by
  28. // the GNU General Public License.
  29.  
  30. //
  31. // ISO C++ 14882: 27.5  Stream buffers
  32. //
  33.  
  34. #ifndef _CPP_STREAMBUF
  35. #define _CPP_STREAMBUF  1
  36.  
  37. #pragma GCC system_header
  38.  
  39. #include <bits/c++config.h>
  40. #include <bits/std_iosfwd.h>
  41. #include <bits/std_cstdio.h>    // For SEEK_SET, SEEK_CUR, SEEK_END
  42. #include <bits/localefwd.h>
  43. #include <bits/ios_base.h>
  44.  
  45. namespace std
  46. {
  47.   template<typename _CharT, typename _Traits>
  48.     streamsize
  49.     __copy_streambufs(basic_ios<_CharT, _Traits>& _ios,
  50.                       basic_streambuf<_CharT, _Traits>* __sbin,
  51.                       basic_streambuf<_CharT, _Traits>* __sbout);
  52.  
  53.   // 27.5.2 Template class basic_streambuf<_CharT, _Traits>
  54.   template<typename _CharT, typename _Traits>
  55.     class basic_streambuf
  56.     {
  57.     public:
  58.       // Types:
  59.       typedef _CharT                                    char_type;
  60.       typedef _Traits                                   traits_type;
  61.       typedef typename traits_type::int_type            int_type;
  62.       typedef typename traits_type::pos_type            pos_type;
  63.       typedef typename traits_type::off_type            off_type;
  64.  
  65.       // Non-standard Types:
  66.       typedef ctype<char_type>                          __ctype_type;
  67.       typedef basic_streambuf<char_type, traits_type>   __streambuf_type;
  68.      
  69.       friend class basic_ios<char_type, traits_type>;
  70.       friend class basic_istream<char_type, traits_type>;
  71.       friend class basic_ostream<char_type, traits_type>;
  72.       friend class istreambuf_iterator<char_type, traits_type>;
  73.       friend class ostreambuf_iterator<char_type, traits_type>;
  74.  
  75.       friend streamsize
  76.       __copy_streambufs<>(basic_ios<char_type, traits_type>& __ios,
  77.                           __streambuf_type* __sbin,__streambuf_type* __sbout);
  78.      
  79.     protected:
  80.  
  81.       // Pointer to the beginning of internally-allocated
  82.       // space. Filebuf manually allocates/deallocates this, whereas
  83.       // stringstreams attempt to use the built-in intelligence of the
  84.       // string class. If you are managing memory, set this. If not,
  85.       // leave it NULL.
  86.       char_type*                _M_buf;        
  87.  
  88.       // Actual size of allocated internal buffer, in bytes.
  89.       int_type                  _M_buf_size;
  90.  
  91.       // Optimal or preferred size of internal buffer, in bytes.
  92.       int_type                  _M_buf_size_opt;
  93.  
  94.       // True iff _M_in_* and _M_out_* buffers should always point to
  95.       // the same place.  True for fstreams, false for sstreams.
  96.       bool                      _M_buf_unified;
  97.  
  98.        // This is based on _IO_FILE, just reordered to be more
  99.       // consistent, and is intended to be the most minimal abstraction
  100.       // for an internal buffer.
  101.       // get == input == read
  102.       // put == output == write
  103.       char_type*                _M_in_beg;      // Start of get area.
  104.       char_type*                _M_in_cur;      // Current read area.
  105.       char_type*                _M_in_end;      // End of get area.
  106.       char_type*                _M_out_beg;     // Start of put area.
  107.       char_type*                _M_out_cur;     // Current put area.
  108.       char_type*                _M_out_end;     // End of put area.
  109.  
  110.       // Place to stash in || out || in | out settings for current streambuf.
  111.       ios_base::openmode        _M_mode;       
  112.  
  113.       // Current locale setting.
  114.       locale                    _M_buf_locale; 
  115.  
  116.       // True iff locale is initialized.
  117.       bool                      _M_buf_locale_init;
  118.  
  119.       // Necessary bits for putback buffer management. Only used in
  120.       // the basic_filebuf class, as necessary for the standard
  121.       // requirements. The only basic_streambuf member function that
  122.       // needs access to these data members is in_avail...
  123.       // NB: pbacks of over one character are not currently supported.
  124.       int_type                  _M_pback_size;
  125.       char_type*                _M_pback;
  126.       char_type*                _M_pback_cur_save;
  127.       char_type*                _M_pback_end_save;
  128.       bool                      _M_pback_init;
  129.  
  130.       // Initializes pback buffers, and moves normal buffers to safety.
  131.       // Assumptions:
  132.       // _M_in_cur has already been moved back
  133.       void
  134.       _M_pback_create()
  135.       {
  136.         if (!_M_pback_init)
  137.           {
  138.             int_type __dist = _M_in_end - _M_in_cur;
  139.             int_type __len = min(_M_pback_size, __dist);
  140.             traits_type::copy(_M_pback, _M_in_cur, __len);
  141.             _M_pback_cur_save = _M_in_cur;
  142.             _M_pback_end_save = _M_in_end;
  143.             this->setg(_M_pback, _M_pback, _M_pback + __len);
  144.             _M_pback_init = true;
  145.           }
  146.       }
  147.  
  148.       // Deactivates pback buffer contents, and restores normal buffer.
  149.       // Assumptions:
  150.       // The pback buffer has only moved forward.
  151.       void
  152.       _M_pback_destroy()
  153.       {
  154.         if (_M_pback_init)
  155.           {
  156.             // Length _M_in_cur moved in the pback buffer.
  157.             int_type __off_cur = _M_in_cur - _M_pback;
  158.            
  159.             // For in | out buffers, the end can be pushed back...
  160.             int_type __off_end = 0;
  161.             int_type __pback_len = _M_in_end - _M_pback;
  162.             int_type __save_len = _M_pback_end_save - _M_buf;
  163.             if (__pback_len > __save_len)
  164.               __off_end = __pback_len - __save_len;
  165.  
  166.             this->setg(_M_buf, _M_pback_cur_save + __off_cur,
  167.                        _M_pback_end_save + __off_end);
  168.             _M_pback_cur_save = NULL;
  169.             _M_pback_end_save = NULL;
  170.             _M_pback_init = false;
  171.           }
  172.       }
  173.  
  174.       // Correctly sets the _M_in_cur pointer, and bumps the
  175.       // _M_out_cur pointer as well if necessary.
  176.       void
  177.       _M_in_cur_move(off_type __n) // argument needs to be +-
  178.       {
  179.         bool __testout = _M_out_cur;
  180.         _M_in_cur += __n;
  181.         if (__testout && _M_buf_unified)
  182.           _M_out_cur += __n;
  183.       }
  184.  
  185.       // Correctly sets the _M_out_cur pointer, and bumps the
  186.       // appropriate _M_*_end pointers as well. Necessary for the
  187.       // un-tied stringbufs, in in|out mode.
  188.       // Invariant:
  189.       // __n + _M_out_[cur, end] <= _M_buf + _M_buf_size
  190.       // Assuming all _M_*_[beg, cur, end] pointers are operating on
  191.       // the same range:
  192.       // _M_buf <= _M_*_ <= _M_buf + _M_buf_size
  193.       void
  194.       _M_out_cur_move(off_type __n) // argument needs to be +-
  195.       {
  196.         bool __testin = _M_in_cur;
  197.  
  198.         _M_out_cur += __n;
  199.         if (__testin && _M_buf_unified)
  200.           _M_in_cur += __n;
  201.         if (_M_out_cur > _M_out_end)
  202.           {
  203.             _M_out_end = _M_out_cur;
  204.             // NB: in | out buffers drag the _M_in_end pointer along...
  205.             if (__testin)
  206.               _M_in_end += __n;
  207.           }
  208.       }
  209.  
  210.       // Return the size of the output buffer.  This depends on the
  211.       // buffer in use: allocated buffers have a stored size in
  212.       // _M_buf_size and setbuf() buffers don't.
  213.       off_type
  214.       _M_out_buf_size()
  215.       {
  216.         off_type __ret = 0;
  217.         if (_M_out_cur)
  218.           {
  219.             // Using allocated buffer.
  220.             if (_M_out_beg == _M_buf)
  221.               __ret = _M_out_beg + _M_buf_size - _M_out_cur;
  222.             // Using non-allocated buffer.
  223.             else
  224.               __ret = _M_out_end - _M_out_cur;
  225.           }
  226.         return __ret;
  227.       }
  228.  
  229.       // These three functions are used to clarify internal buffer
  230.       // maintenance. After an overflow, or after a seekoff call that
  231.       // started at beg or end, or possibly when the stream becomes
  232.       // unbuffered, and a myrid other obscure corner cases, the
  233.       // internal buffer does not truly reflect the contents of the
  234.       // external buffer. At this point, for whatever reason, it is in
  235.       // an indeterminate state.
  236.       void
  237.       _M_set_indeterminate(void)
  238.       {
  239.         if (_M_mode & ios_base::in)
  240.           this->setg(_M_buf, _M_buf, _M_buf);
  241.         if (_M_mode & ios_base::out)
  242.           this->setp(_M_buf, _M_buf);
  243.       }
  244.  
  245.       void
  246.       _M_set_determinate(off_type __off)
  247.       {
  248.         bool __testin = _M_mode & ios_base::in;
  249.         bool __testout = _M_mode & ios_base::out;
  250.         if (__testin)
  251.           this->setg(_M_buf, _M_buf, _M_buf + __off);
  252.         if (__testout)
  253.           this->setp(_M_buf, _M_buf + __off);
  254.       }
  255.  
  256.       bool
  257.       _M_is_indeterminate(void)
  258.       {
  259.         bool __ret = false;
  260.         // Don't return true if unbuffered.
  261.         if (_M_buf)
  262.           {
  263.             if (_M_mode & ios_base::in)
  264.               __ret = _M_in_beg == _M_in_cur && _M_in_cur == _M_in_end;
  265.             if (_M_mode & ios_base::out)
  266.               __ret = _M_out_beg == _M_out_cur && _M_out_cur == _M_out_end;
  267.           }
  268.         return __ret;
  269.       }
  270.  
  271.   public:
  272.       virtual
  273.       ~basic_streambuf()
  274.       {
  275.         _M_buf_unified = false;
  276.         _M_buf_size = 0;
  277.         _M_buf_size_opt = 0;
  278.         _M_mode = ios_base::openmode(0);
  279.         _M_buf_locale_init = false;
  280.       }
  281.  
  282.       // Locales:
  283.       locale
  284.       pubimbue(const locale &__loc)
  285.       {
  286.         locale __tmp(this->getloc());
  287.         this->imbue(__loc);
  288.         return __tmp;
  289.       }
  290.  
  291.       locale  
  292.       getloc() const
  293.       {
  294.         if (_M_buf_locale_init)
  295.           return _M_buf_locale;
  296.         else
  297.           return locale();
  298.       }
  299.  
  300.       // Buffer and positioning:
  301.       __streambuf_type*
  302.       pubsetbuf(char_type* __s, streamsize __n)
  303.       { return this->setbuf(__s, __n); }
  304.  
  305.       pos_type
  306.       pubseekoff(off_type __off, ios_base::seekdir __way,
  307.                  ios_base::openmode __mode = ios_base::in | ios_base::out)
  308.       { return this->seekoff(__off, __way, __mode); }
  309.  
  310.       pos_type
  311.       pubseekpos(pos_type __sp,
  312.                  ios_base::openmode __mode = ios_base::in | ios_base::out)
  313.       { return this->seekpos(__sp, __mode); }
  314.  
  315.       int
  316.       pubsync() { return this->sync(); }
  317.  
  318.       // Get and put areas:
  319.       // Get area:
  320.       streamsize
  321.       in_avail()
  322.       {
  323.         streamsize __ret;
  324.         if (_M_in_cur && _M_in_cur < _M_in_end)
  325.           {
  326.             if (_M_pback_init)
  327.               {
  328.                 int_type __save_len =  _M_pback_end_save - _M_pback_cur_save;
  329.                 int_type __pback_len = _M_in_cur - _M_pback;
  330.                 __ret = __save_len - __pback_len;
  331.               }
  332.             else
  333.               __ret = this->egptr() - this->gptr();
  334.           }
  335.         else
  336.           __ret = this->showmanyc();
  337.         return __ret;
  338.       }
  339.  
  340.       int_type
  341.       snextc()
  342.       {
  343.         int_type __eof = traits_type::eof();
  344.         return (this->sbumpc() == __eof ? __eof : this->sgetc());
  345.       }
  346.  
  347.       int_type
  348.       sbumpc();
  349.  
  350.       int_type
  351.       sgetc()
  352.       {
  353.         int_type __ret;
  354.         if (_M_in_cur && _M_in_cur < _M_in_end)
  355.           __ret = traits_type::to_int_type(*(this->gptr()));
  356.         else
  357.           __ret = this->underflow();
  358.         return __ret;
  359.       }
  360.  
  361.       streamsize
  362.       sgetn(char_type* __s, streamsize __n)
  363.       { return this->xsgetn(__s, __n); }
  364.  
  365.       // Putback:
  366.       int_type
  367.       sputbackc(char_type __c);
  368.  
  369.       int_type
  370.       sungetc();
  371.  
  372.       // Put area:
  373.       int_type
  374.       sputc(char_type __c);
  375.  
  376.       streamsize
  377.       sputn(const char_type* __s, streamsize __n)
  378.       { return this->xsputn(__s, __n); }
  379.  
  380.     protected:
  381.       basic_streambuf()
  382.       : _M_buf(NULL), _M_buf_size(0),
  383.       _M_buf_size_opt(static_cast<int_type>(BUFSIZ)), _M_buf_unified(false),
  384.       _M_in_beg(0), _M_in_cur(0), _M_in_end(0), _M_out_beg(0), _M_out_cur(0),
  385.       _M_out_end(0), _M_mode(ios_base::openmode(0)), _M_buf_locale(locale()),
  386.       _M_buf_locale_init(false), _M_pback_size(1), _M_pback(NULL),
  387.       _M_pback_cur_save(NULL), _M_pback_end_save(NULL), _M_pback_init(false)
  388.       { }
  389.  
  390.       // Get area:
  391.       char_type*
  392.       eback() const { return _M_in_beg; }
  393.  
  394.       char_type*
  395.       gptr()  const { return _M_in_cur;  }
  396.  
  397.       char_type*
  398.       egptr() const { return _M_in_end; }
  399.  
  400.       void
  401.       gbump(int __n) { _M_in_cur += __n; }
  402.  
  403.       void
  404.       setg(char_type* __gbeg, char_type* __gnext, char_type* __gend)
  405.       {
  406.         _M_in_beg = __gbeg;
  407.         _M_in_cur = __gnext;
  408.         _M_in_end = __gend;
  409.         if (!(_M_mode & ios_base::in) && __gbeg && __gnext && __gend)
  410.           _M_mode = _M_mode | ios_base::in;
  411.       }
  412.  
  413.       // Put area:
  414.       char_type*
  415.       pbase() const { return _M_out_beg; }
  416.  
  417.       char_type*
  418.       pptr() const { return _M_out_cur; }
  419.  
  420.       char_type*
  421.       epptr() const { return _M_out_end; }
  422.  
  423.       void
  424.       pbump(int __n) { _M_out_cur += __n; }
  425.  
  426.       void
  427.       setp(char_type* __pbeg, char_type* __pend)
  428.       {
  429.         _M_out_beg = _M_out_cur = __pbeg;
  430.         _M_out_end = __pend;
  431.         if (!(_M_mode & ios_base::out) && __pbeg && __pend)
  432.           _M_mode = _M_mode | ios_base::out;
  433.       }
  434.  
  435.       // Virtual functions:
  436.       // Locales:
  437.       virtual void
  438.       imbue(const locale& __loc)
  439.       {
  440.         _M_buf_locale_init = true;
  441.         if (_M_buf_locale != __loc)
  442.           _M_buf_locale = __loc;
  443.       }
  444.  
  445.       // Buffer management and positioning:
  446.       virtual basic_streambuf<char_type,_Traits>*
  447.       setbuf(char_type*, streamsize)
  448.       { return this; }
  449.      
  450.       virtual pos_type
  451.       seekoff(off_type, ios_base::seekdir,
  452.               ios_base::openmode /*__mode*/ = ios_base::in | ios_base::out)
  453.       { return pos_type(off_type(-1)); }
  454.  
  455.       virtual pos_type
  456.       seekpos(pos_type,
  457.               ios_base::openmode /*__mode*/ = ios_base::in | ios_base::out)
  458.       { return pos_type(off_type(-1)); }
  459.  
  460.       virtual int
  461.       sync() { return 0; }
  462.  
  463.       // Get area:
  464.       virtual streamsize
  465.       showmanyc() { return 0; }
  466.  
  467.       virtual streamsize
  468.       xsgetn(char_type* __s, streamsize __n);
  469.  
  470.       virtual int_type
  471.       underflow()
  472.       { return traits_type::eof(); }
  473.  
  474.       virtual int_type
  475.       uflow()
  476.       {
  477.         int_type __ret = traits_type::eof();
  478.         bool __testeof = this->underflow() == __ret;
  479.         bool __testpending = _M_in_cur && _M_in_cur < _M_in_end;
  480.         if (!__testeof && __testpending)
  481.           {
  482.             __ret = traits_type::to_int_type(*_M_in_cur);
  483.             ++_M_in_cur;
  484.             if (_M_buf_unified && _M_mode & ios_base::out)
  485.               ++_M_out_cur;
  486.           }
  487.         return __ret;    
  488.       }
  489.  
  490.       // Putback:
  491.       virtual int_type
  492.       pbackfail(int_type /* __c */  = traits_type::eof())
  493.       { return traits_type::eof(); }
  494.  
  495.       // Put area:
  496.       virtual streamsize
  497.       xsputn(const char_type* __s, streamsize __n);
  498.  
  499.       virtual int_type
  500.       overflow(int_type /* __c */ = traits_type::eof())
  501.       { return traits_type::eof(); }
  502.  
  503. #ifdef _GLIBCPP_DEPRECATED
  504.     public:
  505.       void
  506.       stossc()
  507.       {
  508.         if (_M_in_cur < _M_in_end)
  509.           ++_M_in_cur;
  510.         else
  511.           this->uflow();
  512.       }
  513. #endif
  514.  
  515. #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
  516.     private:
  517.       basic_streambuf(const __streambuf_type&);
  518.  
  519.       __streambuf_type&
  520.       operator=(const __streambuf_type&);
  521. #endif
  522.     };
  523.  
  524. } // namespace std
  525.  
  526. #ifdef _GLIBCPP_NO_TEMPLATE_EXPORT
  527. # define export
  528. #ifdef  _GLIBCPP_FULLY_COMPLIANT_HEADERS
  529. #include <bits/streambuf.tcc>
  530. #endif
  531. #endif
  532.  
  533. #endif  /* _CPP_STREAMBUF */
  534.  
  535.