Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // Iostreams wrapper for stdio FILE* -*- C++ -*-
  2.  
  3. // Copyright (C) 2003-2015 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. #include <bits/move.h>   // For __exchange
  39.  
  40. #ifdef _GLIBCXX_USE_WCHAR_T
  41. #include <cwchar>
  42. #endif
  43.  
  44. namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
  45. {
  46. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  47.  
  48.   /**
  49.    *  @brief Provides a layer of compatibility for C.
  50.    *  @ingroup io
  51.    *
  52.    *  This GNU extension provides extensions for working with standard
  53.    *  C FILE*'s.  It must be instantiated by the user with the type of
  54.    *  character used in the file stream, e.g., stdio_filebuf<char>.
  55.   */
  56.   template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
  57.     class stdio_sync_filebuf : public std::basic_streambuf<_CharT, _Traits>
  58.     {
  59.     public:
  60.       // Types:
  61.       typedef _CharT                                    char_type;
  62.       typedef _Traits                                   traits_type;
  63.       typedef typename traits_type::int_type            int_type;
  64.       typedef typename traits_type::pos_type            pos_type;
  65.       typedef typename traits_type::off_type            off_type;
  66.  
  67.     private:
  68.       typedef std::basic_streambuf<_CharT, _Traits> __streambuf_type;
  69.  
  70.       // Underlying stdio FILE
  71.       std::__c_file* _M_file;
  72.  
  73.       // Last character gotten. This is used when pbackfail is
  74.       // called from basic_streambuf::sungetc()
  75.       int_type _M_unget_buf;
  76.  
  77.     public:
  78.       explicit
  79.       stdio_sync_filebuf(std::__c_file* __f)
  80.       : _M_file(__f), _M_unget_buf(traits_type::eof())
  81.       { }
  82.  
  83. #if __cplusplus >= 201103L
  84.       stdio_sync_filebuf(stdio_sync_filebuf&& __fb) noexcept
  85.       : __streambuf_type(std::move(__fb)),
  86.       _M_file(__fb._M_file), _M_unget_buf(__fb._M_unget_buf)
  87.       {
  88.         __fb._M_file = nullptr;
  89.         __fb._M_unget_buf = traits_type::eof();
  90.       }
  91.  
  92.       stdio_sync_filebuf&
  93.       operator=(stdio_sync_filebuf&& __fb) noexcept
  94.       {
  95.         __streambuf_type::operator=(__fb);
  96.         _M_file = std::__exchange(__fb._M_file, nullptr);
  97.         _M_unget_buf = std::__exchange(__fb._M_unget_buf, traits_type::eof());
  98.         return *this;
  99.       }
  100.  
  101.       void
  102.       swap(stdio_sync_filebuf& __fb)
  103.       {
  104.         __streambuf_type::swap(__fb);
  105.         std::swap(_M_file, __fb._M_file);
  106.         std::swap(_M_unget_buf, __fb._M_unget_buf);
  107.       }
  108. #endif
  109.  
  110.       /**
  111.        *  @return  The underlying FILE*.
  112.        *
  113.        *  This function can be used to access the underlying C file pointer.
  114.        *  Note that there is no way for the library to track what you do
  115.        *  with the file, so be careful.
  116.        */
  117.       std::__c_file*
  118.       file() { return this->_M_file; }
  119.  
  120.     protected:
  121.       int_type
  122.       syncgetc();
  123.  
  124.       int_type
  125.       syncungetc(int_type __c);
  126.  
  127.       int_type
  128.       syncputc(int_type __c);
  129.  
  130.       virtual int_type
  131.       underflow()
  132.       {
  133.         int_type __c = this->syncgetc();
  134.         return this->syncungetc(__c);
  135.       }
  136.  
  137.       virtual int_type
  138.       uflow()
  139.       {
  140.         // Store the gotten character in case we need to unget it.
  141.         _M_unget_buf = this->syncgetc();
  142.         return _M_unget_buf;
  143.       }
  144.  
  145.       virtual int_type
  146.       pbackfail(int_type __c = traits_type::eof())
  147.       {
  148.         int_type __ret;
  149.         const int_type __eof = traits_type::eof();
  150.  
  151.         // Check if the unget or putback was requested
  152.         if (traits_type::eq_int_type(__c, __eof)) // unget
  153.           {
  154.             if (!traits_type::eq_int_type(_M_unget_buf, __eof))
  155.               __ret = this->syncungetc(_M_unget_buf);
  156.             else // buffer invalid, fail.
  157.               __ret = __eof;
  158.           }
  159.         else // putback
  160.           __ret = this->syncungetc(__c);
  161.  
  162.         // The buffered character is no longer valid, discard it.
  163.         _M_unget_buf = __eof;
  164.         return __ret;
  165.       }
  166.  
  167.       virtual std::streamsize
  168.       xsgetn(char_type* __s, std::streamsize __n);
  169.  
  170.       virtual int_type
  171.       overflow(int_type __c = traits_type::eof())
  172.       {
  173.         int_type __ret;
  174.         if (traits_type::eq_int_type(__c, traits_type::eof()))
  175.           {
  176.             if (std::fflush(_M_file))
  177.               __ret = traits_type::eof();
  178.             else
  179.               __ret = traits_type::not_eof(__c);
  180.           }
  181.         else
  182.           __ret = this->syncputc(__c);
  183.         return __ret;
  184.       }
  185.  
  186.       virtual std::streamsize
  187.       xsputn(const char_type* __s, std::streamsize __n);
  188.  
  189.       virtual int
  190.       sync()
  191.       { return std::fflush(_M_file); }
  192.  
  193.       virtual std::streampos
  194.       seekoff(std::streamoff __off, std::ios_base::seekdir __dir,
  195.               std::ios_base::openmode = std::ios_base::in | std::ios_base::out)
  196.       {
  197.         std::streampos __ret(std::streamoff(-1));
  198.         int __whence;
  199.         if (__dir == std::ios_base::beg)
  200.           __whence = SEEK_SET;
  201.         else if (__dir == std::ios_base::cur)
  202.           __whence = SEEK_CUR;
  203.         else
  204.           __whence = SEEK_END;
  205. #ifdef _GLIBCXX_USE_LFS
  206.         if (!fseeko64(_M_file, __off, __whence))
  207.           __ret = std::streampos(ftello64(_M_file));
  208. #else
  209.         if (!fseek(_M_file, __off, __whence))
  210.           __ret = std::streampos(std::ftell(_M_file));
  211. #endif
  212.         return __ret;
  213.       }
  214.  
  215.       virtual std::streampos
  216.       seekpos(std::streampos __pos,
  217.               std::ios_base::openmode __mode =
  218.               std::ios_base::in | std::ios_base::out)
  219.       { return seekoff(std::streamoff(__pos), std::ios_base::beg, __mode); }
  220.     };
  221.  
  222.   template<>
  223.     inline stdio_sync_filebuf<char>::int_type
  224.     stdio_sync_filebuf<char>::syncgetc()
  225.     { return std::getc(_M_file); }
  226.  
  227.   template<>
  228.     inline stdio_sync_filebuf<char>::int_type
  229.     stdio_sync_filebuf<char>::syncungetc(int_type __c)
  230.     { return std::ungetc(__c, _M_file); }
  231.  
  232.   template<>
  233.     inline stdio_sync_filebuf<char>::int_type
  234.     stdio_sync_filebuf<char>::syncputc(int_type __c)
  235.     { return std::putc(__c, _M_file); }
  236.  
  237.   template<>
  238.     inline std::streamsize
  239.     stdio_sync_filebuf<char>::xsgetn(char* __s, std::streamsize __n)
  240.     {
  241.       std::streamsize __ret = std::fread(__s, 1, __n, _M_file);
  242.       if (__ret > 0)
  243.         _M_unget_buf = traits_type::to_int_type(__s[__ret - 1]);
  244.       else
  245.         _M_unget_buf = traits_type::eof();
  246.       return __ret;
  247.     }
  248.  
  249.   template<>
  250.     inline std::streamsize
  251.     stdio_sync_filebuf<char>::xsputn(const char* __s, std::streamsize __n)
  252.     { return std::fwrite(__s, 1, __n, _M_file); }
  253.  
  254. #ifdef _GLIBCXX_USE_WCHAR_T
  255.   template<>
  256.     inline stdio_sync_filebuf<wchar_t>::int_type
  257.     stdio_sync_filebuf<wchar_t>::syncgetc()
  258.     { return std::getwc(_M_file); }
  259.  
  260.   template<>
  261.     inline stdio_sync_filebuf<wchar_t>::int_type
  262.     stdio_sync_filebuf<wchar_t>::syncungetc(int_type __c)
  263.     { return std::ungetwc(__c, _M_file); }
  264.  
  265.   template<>
  266.     inline stdio_sync_filebuf<wchar_t>::int_type
  267.     stdio_sync_filebuf<wchar_t>::syncputc(int_type __c)
  268.     { return std::putwc(__c, _M_file); }
  269.  
  270.   template<>
  271.     inline std::streamsize
  272.     stdio_sync_filebuf<wchar_t>::xsgetn(wchar_t* __s, std::streamsize __n)
  273.     {
  274.       std::streamsize __ret = 0;
  275.       const int_type __eof = traits_type::eof();
  276.       while (__n--)
  277.         {
  278.           int_type __c = this->syncgetc();
  279.           if (traits_type::eq_int_type(__c, __eof))
  280.             break;
  281.           __s[__ret] = traits_type::to_char_type(__c);
  282.           ++__ret;
  283.         }
  284.  
  285.       if (__ret > 0)
  286.         _M_unget_buf = traits_type::to_int_type(__s[__ret - 1]);
  287.       else
  288.         _M_unget_buf = traits_type::eof();
  289.       return __ret;
  290.     }
  291.  
  292.   template<>
  293.     inline std::streamsize
  294.     stdio_sync_filebuf<wchar_t>::xsputn(const wchar_t* __s,
  295.                                         std::streamsize __n)
  296.     {
  297.       std::streamsize __ret = 0;
  298.       const int_type __eof = traits_type::eof();
  299.       while (__n--)
  300.         {
  301.           if (traits_type::eq_int_type(this->syncputc(*__s++), __eof))
  302.             break;
  303.           ++__ret;
  304.         }
  305.       return __ret;
  306.     }
  307. #endif
  308.  
  309. #if _GLIBCXX_EXTERN_TEMPLATE
  310.   extern template class stdio_sync_filebuf<char>;
  311. #ifdef _GLIBCXX_USE_WCHAR_T
  312.   extern template class stdio_sync_filebuf<wchar_t>;
  313. #endif
  314. #endif
  315.  
  316. _GLIBCXX_END_NAMESPACE_VERSION
  317. } // namespace
  318.  
  319. #endif
  320.