text: // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
  // (C) Copyright 2003-2007 Jonathan Turkanis
  // Distributed under the Boost Software License, Version 1.0. (See accompanying
  // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
  
  // See http://www.boost.org/libs/iostreams for documentation.
  
  //
  // Contains wrappers for standard file buffers, together
  // with convenience typedefs:
  //      - basic_file_source
  //      - basic_file_sink
  //      - basic_file
  //
  
  #ifndef BOOST_IOSTREAMS_FILE_HPP_INCLUDED
  #define BOOST_IOSTREAMS_FILE_HPP_INCLUDED
  
  #if defined(_MSC_VER) && (_MSC_VER >= 1020)
  # pragma once
  #endif
  
  #include <boost/iostreams/detail/config/wide_streams.hpp>
  #ifndef BOOST_IOSTREAMS_NO_LOCALE
  # include <locale>
  #endif
  #include <string>                               // pathnames, char_traits.
  #include <boost/iostreams/categories.hpp>
  #include <boost/iostreams/detail/ios.hpp>       // openmode, seekdir, int types.
  #include <boost/iostreams/detail/fstream.hpp>
  #include <boost/iostreams/operations.hpp>       // seek.
  #include <boost/shared_ptr.hpp>      
  
  // Must come last.
  #include <boost/iostreams/detail/config/disable_warnings.hpp>  // MSVC.
  
  namespace boost { namespace iostreams {
  
  template<typename Ch>
  class basic_file {
  public:
      typedef Ch char_type;
      struct category
          : public seekable_device_tag,
            public closable_tag,
            public localizable_tag
          { };
      basic_file( const std::string& path,
                  BOOST_IOS::openmode mode =
                      BOOST_IOS::in | BOOST_IOS::out,
                  BOOST_IOS::openmode base_mode =
                      BOOST_IOS::in | BOOST_IOS::out );
      std::streamsize read(char_type* s, std::streamsize n);
      std::streamsize write(const char_type* s, std::streamsize n);
      std::streampos seek( stream_offset off, BOOST_IOS::seekdir way, 
                           BOOST_IOS::openmode which = 
                               BOOST_IOS::in | BOOST_IOS::out );
      void open( const std::string& path,
                 BOOST_IOS::openmode mode =
                     BOOST_IOS::in | BOOST_IOS::out,
                 BOOST_IOS::openmode base_mode =
                     BOOST_IOS::in | BOOST_IOS::out );
      bool is_open() const;
      void close();
  #ifndef BOOST_IOSTREAMS_NO_LOCALE
      void imbue(const std::locale& loc) { pimpl_->file_.pubimbue(loc);  }
  #endif
  private:
      struct impl {
          impl(const std::string& path, BOOST_IOS::openmode mode)
              { file_.open(path.c_str(), mode); }
          ~impl() { if (file_.is_open()) file_.close(); }
          BOOST_IOSTREAMS_BASIC_FILEBUF(Ch) file_;
      };
      shared_ptr<impl> pimpl_;
  };
  
  typedef basic_file<char>     file;
  typedef basic_file<wchar_t>  wfile;
  
  template<typename Ch>
  struct basic_file_source : private basic_file<Ch> {
      typedef Ch char_type;
      struct category
          : input_seekable,
            device_tag,
            closable_tag
          { };
      using basic_file<Ch>::read;
      using basic_file<Ch>::seek;
      using basic_file<Ch>::is_open;
      using basic_file<Ch>::close;
      basic_file_source( const std::string& path,
                         BOOST_IOS::openmode mode = 
                             BOOST_IOS::in )
          : basic_file<Ch>(path, mode & ~BOOST_IOS::out, BOOST_IOS::in)
          { }
      void open( const std::string& path,
                 BOOST_IOS::openmode mode = BOOST_IOS::in )
      {
          basic_file<Ch>::open(path, mode & ~BOOST_IOS::out, BOOST_IOS::in);
      }
  };
  
  typedef basic_file_source<char>     file_source;
  typedef basic_file_source<wchar_t>  wfile_source;
  
  template<typename Ch>
  struct basic_file_sink : private basic_file<Ch> {
      typedef Ch char_type;
      struct category
          : output_seekable,
            device_tag,
            closable_tag
          { };
      using basic_file<Ch>::write;
      using basic_file<Ch>::seek;
      using basic_file<Ch>::is_open;
      using basic_file<Ch>::close;
      basic_file_sink( const std::string& path,
                       BOOST_IOS::openmode mode = BOOST_IOS::out )
          : basic_file<Ch>(path, mode & ~BOOST_IOS::in, BOOST_IOS::out)
          { }
      void open( const std::string& path,
                 BOOST_IOS::openmode mode = BOOST_IOS::out )
      {
          basic_file<Ch>::open(path, mode & ~BOOST_IOS::in, BOOST_IOS::out);
      }
  };
  
  typedef basic_file_sink<char>     file_sink;
  typedef basic_file_sink<wchar_t>  wfile_sink;
                                   
  //------------------Implementation of basic_file------------------------------//
  
  template<typename Ch>
  basic_file<Ch>::basic_file
      ( const std::string& path, BOOST_IOS::openmode mode, 
        BOOST_IOS::openmode base_mode )
  { 
      open(path, mode, base_mode);
  }
  
  template<typename Ch>
  inline std::streamsize basic_file<Ch>::read
      (char_type* s, std::streamsize n)
  { 
      std::streamsize result = pimpl_->file_.sgetn(s, n); 
      return result != 0 ? result : -1;
  }
  
  template<typename Ch>
  inline std::streamsize basic_file<Ch>::write
      (const char_type* s, std::streamsize n)
  { return pimpl_->file_.sputn(s, n); }
  
  template<typename Ch>
  std::streampos basic_file<Ch>::seek
      ( stream_offset off, BOOST_IOS::seekdir way, 
        BOOST_IOS::openmode )
  { return iostreams::seek(pimpl_->file_, off, way); }
  
  template<typename Ch>
  void basic_file<Ch>::open
      ( const std::string& path, BOOST_IOS::openmode mode, 
        BOOST_IOS::openmode base_mode )
  { 
      pimpl_.reset(new impl(path, mode | base_mode));
  }
  
  template<typename Ch>
  bool basic_file<Ch>::is_open() const { return pimpl_->file_.is_open(); }
  
  template<typename Ch>
  void basic_file<Ch>::close() { pimpl_->file_.close(); }
  
  //----------------------------------------------------------------------------//
  
  } } // End namespaces iostreams, boost.
  
  #include <boost/iostreams/detail/config/enable_warnings.hpp> // MSVC
  
  #endif // #ifndef BOOST_IOSTREAMS_FILE_HPP_INCLUDED
  