Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. // Iostreams wrapper for stdio FILE* -*- C++ -*-
  2.  
  3. // Copyright (C) 2003-2013 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 3, 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. // Under Section 7 of GPL version 3, you are granted additional
  17. // permissions described in the GCC Runtime Library Exception, version
  18. // 3.1, as published by the Free Software Foundation.
  19.  
  20. // You should have received a copy of the GNU General Public License and
  21. // a copy of the GCC Runtime Library Exception along with this program;
  22. // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
  23. // <http://www.gnu.org/licenses/>.
  24.  
  25. /** @file ext/stdio_sync_filebuf.h
  26.  *  This file is a GNU extension to the Standard C++ Library.
  27.  */
  28.  
  29. #ifndef _STDIO_SYNC_FILEBUF_H
  30. #define _STDIO_SYNC_FILEBUF_H 1
  31.  
  32. #pragma GCC system_header
  33.  
  34. #include <streambuf>
  35. #include <unistd.h>
  36. #include <cstdio>
  37. #include <bits/c++io.h>  // For __c_file
  38.  
  39. #ifdef _GLIBCXX_USE_WCHAR_T
  40. #include <cwchar>
  41. #endif
  42.  
  43. namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
  44. {
  45. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  46.  
  47.   /**
  48.    *  @brief Provides a layer of compatibility for C.
  49.    *  @ingroup io
  50.    *
  51.    *  This GNU extension provides extensions for working with standard
  52.    *  C FILE*'s.  It must be instantiated by the user with the type of
  53.    *  character used in the file stream, e.g., stdio_filebuf<char>.
  54.   */
  55.   template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
  56.     class stdio_sync_filebuf : public std::basic_streambuf<_CharT, _Traits>
  57.     {
  58.     public:
  59.       // Types:
  60.       typedef _CharT                                    char_type;
  61.       typedef _Traits                                   traits_type;
  62.       typedef typename traits_type::int_type            int_type;
  63.       typedef typename traits_type::pos_type            pos_type;
  64.       typedef typename traits_type::off_type            off_type;
  65.  
  66.     private:
  67.       // Underlying stdio FILE
  68.       std::__c_file* const _M_file;
  69.  
  70.       // Last character gotten. This is used when pbackfail is
  71.       // called from basic_streambuf::sungetc()
  72.       int_type _M_unget_buf;
  73.  
  74.     public:
  75.       explicit
  76.       stdio_sync_filebuf(std::__c_file* __f)
  77.       : _M_file(__f), _M_unget_buf(traits_type::eof())
  78.       { }
  79.  
  80.       /**
  81.        *  @return  The underlying FILE*.
  82.        *
  83.        *  This function can be used to access the underlying C file pointer.
  84.        *  Note that there is no way for the library to track what you do
  85.        *  with the file, so be careful.
  86.        */
  87.       std::__c_file* const
  88.       file() { return this->_M_file; }
  89.  
  90.     protected:
  91.       int_type
  92.       syncgetc();
  93.  
  94.       int_type
  95.       syncungetc(int_type __c);
  96.  
  97.       int_type
  98.       syncputc(int_type __c);
  99.  
  100.       virtual int_type
  101.       underflow()
  102.       {
  103.         int_type __c = this->syncgetc();
  104.         return this->syncungetc(__c);
  105.       }
  106.  
  107.       virtual int_type
  108.       uflow()
  109.       {
  110.         // Store the gotten character in case we need to unget it.
  111.         _M_unget_buf = this->syncgetc();
  112.         return _M_unget_buf;
  113.       }
  114.  
  115.       virtual int_type
  116.       pbackfail(int_type __c = traits_type::eof())
  117.       {
  118.         int_type __ret;
  119.         const int_type __eof = traits_type::eof();
  120.  
  121.         // Check if the unget or putback was requested
  122.         if (traits_type::eq_int_type(__c, __eof)) // unget
  123.           {
  124.             if (!traits_type::eq_int_type(_M_unget_buf, __eof))
  125.               __ret = this->syncungetc(_M_unget_buf);
  126.             else // buffer invalid, fail.
  127.               __ret = __eof;
  128.           }
  129.         else // putback
  130.           __ret = this->syncungetc(__c);
  131.  
  132.         // The buffered character is no longer valid, discard it.
  133.         _M_unget_buf = __eof;
  134.         return __ret;
  135.       }
  136.  
  137.       virtual std::streamsize
  138.       xsgetn(char_type* __s, std::streamsize __n);
  139.  
  140.       virtual int_type
  141.       overflow(int_type __c = traits_type::eof())
  142.       {
  143.         int_type __ret;
  144.         if (traits_type::eq_int_type(__c, traits_type::eof()))
  145.           {
  146.             if (std::fflush(_M_file))
  147.               __ret = traits_type::eof();
  148.             else
  149.               __ret = traits_type::not_eof(__c);
  150.           }
  151.         else
  152.           __ret = this->syncputc(__c);
  153.         return __ret;
  154.       }
  155.  
  156.       virtual std::streamsize
  157.       xsputn(const char_type* __s, std::streamsize __n);
  158.  
  159.       virtual int
  160.       sync()
  161.       { return std::fflush(_M_file); }
  162.  
  163.       virtual std::streampos
  164.       seekoff(std::streamoff __off, std::ios_base::seekdir __dir,
  165.               std::ios_base::openmode = std::ios_base::in | std::ios_base::out)
  166.       {
  167.         std::streampos __ret(std::streamoff(-1));
  168.         int __whence;
  169.         if (__dir == std::ios_base::beg)
  170.           __whence = SEEK_SET;
  171.         else if (__dir == std::ios_base::cur)
  172.           __whence = SEEK_CUR;
  173.         else
  174.           __whence = SEEK_END;
  175. #ifdef _GLIBCXX_USE_LFS
  176.         if (!fseeko64(_M_file, __off, __whence))
  177.           __ret = std::streampos(ftello64(_M_file));
  178. #else
  179.         if (!fseek(_M_file, __off, __whence))
  180.           __ret = std::streampos(std::ftell(_M_file));
  181. #endif
  182.         return __ret;
  183.       }
  184.  
  185.       virtual std::streampos
  186.       seekpos(std::streampos __pos,
  187.               std::ios_base::openmode __mode =
  188.               std::ios_base::in | std::ios_base::out)
  189.       { return seekoff(std::streamoff(__pos), std::ios_base::beg, __mode); }
  190.     };
  191.  
  192.   template<>
  193.     inline stdio_sync_filebuf<char>::int_type
  194.     stdio_sync_filebuf<char>::syncgetc()
  195.     { return std::getc(_M_file); }
  196.  
  197.   template<>
  198.     inline stdio_sync_filebuf<char>::int_type
  199.     stdio_sync_filebuf<char>::syncungetc(int_type __c)
  200.     { return std::ungetc(__c, _M_file); }
  201.  
  202.   template<>
  203.     inline stdio_sync_filebuf<char>::int_type
  204.     stdio_sync_filebuf<char>::syncputc(int_type __c)
  205.     { return std::putc(__c, _M_file); }
  206.  
  207.   template<>
  208.     inline std::streamsize
  209.     stdio_sync_filebuf<char>::xsgetn(char* __s, std::streamsize __n)
  210.     {
  211.       std::streamsize __ret = std::fread(__s, 1, __n, _M_file);
  212.       if (__ret > 0)
  213.         _M_unget_buf = traits_type::to_int_type(__s[__ret - 1]);
  214.       else
  215.         _M_unget_buf = traits_type::eof();
  216.       return __ret;
  217.     }
  218.  
  219.   template<>
  220.     inline std::streamsize
  221.     stdio_sync_filebuf<char>::xsputn(const char* __s, std::streamsize __n)
  222.     { return std::fwrite(__s, 1, __n, _M_file); }
  223.  
  224. #ifdef _GLIBCXX_USE_WCHAR_T
  225.   template<>
  226.     inline stdio_sync_filebuf<wchar_t>::int_type
  227.     stdio_sync_filebuf<wchar_t>::syncgetc()
  228.     { return std::getwc(_M_file); }
  229.  
  230.   template<>
  231.     inline stdio_sync_filebuf<wchar_t>::int_type
  232.     stdio_sync_filebuf<wchar_t>::syncungetc(int_type __c)
  233.     { return std::ungetwc(__c, _M_file); }
  234.  
  235.   template<>
  236.     inline stdio_sync_filebuf<wchar_t>::int_type
  237.     stdio_sync_filebuf<wchar_t>::syncputc(int_type __c)
  238.     { return std::putwc(__c, _M_file); }
  239.  
  240.   template<>
  241.     inline std::streamsize
  242.     stdio_sync_filebuf<wchar_t>::xsgetn(wchar_t* __s, std::streamsize __n)
  243.     {
  244.       std::streamsize __ret = 0;
  245.       const int_type __eof = traits_type::eof();
  246.       while (__n--)
  247.         {
  248.           int_type __c = this->syncgetc();
  249.           if (traits_type::eq_int_type(__c, __eof))
  250.             break;
  251.           __s[__ret] = traits_type::to_char_type(__c);
  252.           ++__ret;
  253.         }
  254.  
  255.       if (__ret > 0)
  256.         _M_unget_buf = traits_type::to_int_type(__s[__ret - 1]);
  257.       else
  258.         _M_unget_buf = traits_type::eof();
  259.       return __ret;
  260.     }
  261.  
  262.   template<>
  263.     inline std::streamsize
  264.     stdio_sync_filebuf<wchar_t>::xsputn(const wchar_t* __s,
  265.                                         std::streamsize __n)
  266.     {
  267.       std::streamsize __ret = 0;
  268.       const int_type __eof = traits_type::eof();
  269.       while (__n--)
  270.         {
  271.           if (traits_type::eq_int_type(this->syncputc(*__s++), __eof))
  272.             break;
  273.           ++__ret;
  274.         }
  275.       return __ret;
  276.     }
  277. #endif
  278.  
  279. #if _GLIBCXX_EXTERN_TEMPLATE
  280.   extern template class stdio_sync_filebuf<char>;
  281. #ifdef _GLIBCXX_USE_WCHAR_T
  282.   extern template class stdio_sync_filebuf<wchar_t>;
  283. #endif
  284. #endif
  285.  
  286. _GLIBCXX_END_NAMESPACE_VERSION
  287. } // namespace
  288.  
  289. #endif
  290.