file_descriptor.cpp

来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 287 行

CPP
287
字号
// (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.// Inspired by fdstream.hpp, (C) Copyright Nicolai M. Josuttis 2001,// available at http://www.josuttis.com/cppcode/fdstream.html.// Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp>// knows that we are building the library (possibly exporting code), rather// than using it (possibly importing code).#define BOOST_IOSTREAMS_SOURCE#include <cassert>#include <cerrno>#include <cstdio>                                 // SEEK_SET, etc.#include <boost/config.hpp>                       // BOOST_JOIN#include <boost/iostreams/detail/error.hpp>#include <boost/iostreams/detail/config/dyn_link.hpp>#include <boost/iostreams/detail/config/rtl.hpp>  // BOOST_IOSTREAMS_FD_XXX#include <boost/iostreams/detail/config/windows_posix.hpp>#include <boost/iostreams/detail/ios.hpp>         // openmodes, failure.#include <boost/iostreams/device/file_descriptor.hpp>#include <boost/integer_traits.hpp>    // OS-specific headers for low-level i/o.#include <fcntl.h>       // file opening flags.#include <sys/stat.h>    // file access permissions.#ifdef BOOST_IOSTREAMS_WINDOWS# include <io.h>         // low-level file i/o.# define WINDOWS_LEAN_AND_MEAN# include <windows.h># ifndef INVALID_SET_FILE_POINTER#  define INVALID_SET_FILE_POINTER ((DWORD)-1)# endif#else# include <sys/types.h>  // mode_t.# include <unistd.h>     // low-level file i/o.#endifnamespace boost { namespace iostreams {//------------------Implementation of file_descriptor-------------------------//file_descriptor::file_descriptor() : pimpl_(new impl) { }file_descriptor::file_descriptor(handle_type fd, bool close_on_exit)    : pimpl_(new impl(fd, close_on_exit))    { }#ifdef BOOST_IOSTREAMS_WINDOWS    file_descriptor::file_descriptor(int fd, bool close_on_exit)        : pimpl_(new impl(int_to_handle(fd), close_on_exit))        { }#endiffile_descriptor::file_descriptor( const char* path,                                  BOOST_IOS::openmode mode,                                  BOOST_IOS::openmode base_mode )    : pimpl_(new impl){ open(std::string(path), mode, base_mode); }file_descriptor::file_descriptor( const std::string& path,                                  BOOST_IOS::openmode mode,                                  BOOST_IOS::openmode base_mode )    : pimpl_(new impl){ open(path, mode, base_mode); }void file_descriptor::open    ( const std::string& path, BOOST_IOS::openmode m,      BOOST_IOS::openmode base ){    using namespace std;    m |= base;#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//    DWORD dwDesiredAccess;    DWORD dwCreationDisposition;    if ( (m & (BOOST_IOS::in | BOOST_IOS::out))             ==         (BOOST_IOS::in | BOOST_IOS::out) )    {        if (m & BOOST_IOS::app)            throw BOOST_IOSTREAMS_FAILURE("bad open mode");        dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;        dwCreationDisposition =            (m & BOOST_IOS::trunc) ?                OPEN_ALWAYS :                OPEN_EXISTING;    } else if (m & BOOST_IOS::in) {        if (m & (BOOST_IOS::app |BOOST_IOS::trunc))            throw BOOST_IOSTREAMS_FAILURE("bad open mode");        dwDesiredAccess = GENERIC_READ;        dwCreationDisposition = OPEN_EXISTING;    } else if (m & BOOST_IOS::out) {        dwDesiredAccess = GENERIC_WRITE;        dwCreationDisposition = OPEN_ALWAYS;        if (m & BOOST_IOS::app)            pimpl_->flags_ |= impl::append;    } else {        throw BOOST_IOSTREAMS_FAILURE("bad open mode");    }    HANDLE handle =        ::CreateFileA( path.c_str(),                       dwDesiredAccess,                       FILE_SHARE_READ | FILE_SHARE_WRITE,                       NULL,                   // lpSecurityAttributes                       dwCreationDisposition,                       FILE_ATTRIBUTE_NORMAL,                       NULL );                 // hTemplateFile    if (handle != INVALID_HANDLE_VALUE) {        pimpl_->handle_ = handle;        pimpl_->flags_ |= impl::close_on_exit;    } else {        pimpl_->flags_ = 0;        throw BOOST_IOSTREAMS_FAILURE("bad open");    }#else // #ifdef BOOST_IOSTREAMS_WINDOWS //------------------------------------//        // Calculate oflag argument to open.    int oflag = 0;    if ( (m & (BOOST_IOS::in | BOOST_IOS::out))             ==         (BOOST_IOS::in | BOOST_IOS::out) )    {        assert(!(m & BOOST_IOS::app));        oflag |= O_RDWR;    } else if (m & BOOST_IOS::in) {        assert(!(m & (BOOST_IOS::app |BOOST_IOS::trunc)));        oflag |= O_RDONLY;    } else if (m & BOOST_IOS::out) {        oflag |= O_WRONLY;        m |= BOOST_IOS::trunc;        if (m & BOOST_IOS::app)            oflag |= O_APPEND;    }    if (m & BOOST_IOS::trunc)        oflag |= O_CREAT;    #ifdef _LARGEFILE64_SOURCE        oflag |= O_LARGEFILE;    #endif        // Calculate pmode argument to open.    mode_t pmode = S_IRUSR | S_IWUSR |                   S_IRGRP | S_IWGRP |                   S_IROTH | S_IWOTH;        // Open file.    int fd = BOOST_IOSTREAMS_FD_OPEN(path.c_str(), oflag, pmode);    if (fd == -1) {        throw BOOST_IOSTREAMS_FAILURE("bad open");    } else {        pimpl_->handle_ = fd;        pimpl_->flags_ = impl::close_on_exit;    }#endif // #ifndef BOOST_IOSTREAMS_WINDOWS //----------------------------------//}void file_descriptor::open    ( const char* path, BOOST_IOS::openmode m,      BOOST_IOS::openmode base ){ open(std::string(path), m, base); }std::streamsize file_descriptor::read(char_type* s, std::streamsize n){#ifdef BOOST_IOSTREAMS_WINDOWS    DWORD result;    if (!::ReadFile(pimpl_->handle_, s, n, &result, NULL))        throw detail::bad_read();    return result == 0 ? -1 : static_cast<std::streamsize>(result);#else // #ifdef BOOST_IOSTREAMS_WINDOWS    errno = 0;    std::streamsize result = BOOST_IOSTREAMS_FD_READ(pimpl_->handle_, s, n);    if (errno != 0)        throw detail::bad_read();    return result == 0 ? -1 : result;#endif // #ifdef BOOST_IOSTREAMS_WINDOWS}std::streamsize file_descriptor::write(const char_type* s, std::streamsize n){#ifdef BOOST_IOSTREAMS_WINDOWS    if (pimpl_->flags_ & impl::append) {        DWORD const dwResult =            ::SetFilePointer(pimpl_->handle_, 0, NULL, FILE_END);        if ( dwResult == INVALID_SET_FILE_POINTER &&             ::GetLastError() != NO_ERROR )        {            throw detail::bad_seek();        }    }    DWORD ignore;    if (!::WriteFile(pimpl_->handle_, s, n, &ignore, NULL))        throw detail::bad_write();    return n;#else // #ifdef BOOST_IOSTREAMS_WINDOWS    int amt = BOOST_IOSTREAMS_FD_WRITE(pimpl_->handle_, s, n);    if (amt < n)        throw detail::bad_write(); // Handles blocking fd's only.    return n;#endif // #ifdef BOOST_IOSTREAMS_WINDOWS}std::streampos file_descriptor::seek    (stream_offset off, BOOST_IOS::seekdir way){    using namespace std;#ifdef BOOST_IOSTREAMS_WINDOWS    LONG lDistanceToMove = static_cast<LONG>(off & 0xffffffff);    LONG lDistanceToMoveHigh = static_cast<LONG>(off >> 32);    DWORD dwResultLow =        ::SetFilePointer( pimpl_->handle_,                          lDistanceToMove,                          &lDistanceToMoveHigh,                          way == BOOST_IOS::beg ?                              FILE_BEGIN :                              way == BOOST_IOS::cur ?                                FILE_CURRENT :                                FILE_END );    if ( dwResultLow == INVALID_SET_FILE_POINTER &&         ::GetLastError() != NO_ERROR )    {        throw detail::bad_seek();    } else {       return offset_to_position(   	              (stream_offset(lDistanceToMoveHigh) << 32) + dwResultLow              );    }#else // #ifdef BOOST_IOSTREAMS_WINDOWS    if ( off > integer_traits<BOOST_IOSTREAMS_FD_OFFSET>::const_max ||         off < integer_traits<BOOST_IOSTREAMS_FD_OFFSET>::const_min )    {        throw BOOST_IOSTREAMS_FAILURE("bad offset");    }    stream_offset result =        BOOST_IOSTREAMS_FD_SEEK(            pimpl_->handle_,            static_cast<BOOST_IOSTREAMS_FD_OFFSET>(off),            ( way == BOOST_IOS::beg ?                  SEEK_SET :                  way == BOOST_IOS::cur ?                      SEEK_CUR :                      SEEK_END )         );    if (result == -1)        throw detail::bad_seek();    return offset_to_position(result);#endif // #ifdef BOOST_IOSTREAMS_WINDOWS}void file_descriptor::close() { close_impl(*pimpl_); }void file_descriptor::close_impl(impl& i){#ifdef BOOST_IOSTREAMS_WINDOWS    if (i.handle_ != reinterpret_cast<handle_type>(-1)) {        if (!::CloseHandle(i.handle_))            throw BOOST_IOSTREAMS_FAILURE("bad close");        i.handle_ = reinterpret_cast<handle_type>(-1);        i.flags_ = 0;        return;    }#else // #ifdef BOOST_IOSTREAMS_WINDOWS    if (i.handle_ != -1) {        if (BOOST_IOSTREAMS_FD_CLOSE(i.handle_) == -1)            throw BOOST_IOSTREAMS_FAILURE("bad close");        i.handle_ = -1;        i.flags_ = 0;    }#endif // #ifdef BOOST_IOSTREAMS_WINDOWS}#ifdef BOOST_IOSTREAMS_WINDOWSfile_descriptor::handle_type file_descriptor::int_to_handle(int fd){    return reinterpret_cast<handle_type>(_get_osfhandle(fd));}#endif} } // End namespaces iostreams, boost.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?