diff third_party/boost/process/detail/systembuf.hpp @ 0:add35537fdbb tip

Initial import
author irh <ian.r.hobson@gmail.com>
date Thu, 25 Aug 2011 11:05:55 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/third_party/boost/process/detail/systembuf.hpp	Thu Aug 25 11:05:55 2011 +0100
@@ -0,0 +1,228 @@
+//
+// Boost.Process
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
+// Copyright (c) 2009 Boris Schaeling
+// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
+//
+// 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)
+//
+
+/**
+ * \file boost/process/detail/systembuf.hpp
+ *
+ * Includes the declaration of the systembuf class.
+ */
+
+#ifndef BOOST_PROCESS_DETAIL_SYSTEMBUF_HPP
+#define BOOST_PROCESS_DETAIL_SYSTEMBUF_HPP
+
+#include <boost/process/config.hpp>
+
+#if defined(BOOST_POSIX_API)
+#   include <sys/types.h>
+#   include <unistd.h>
+#elif defined(BOOST_WINDOWS_API)
+#   include <windows.h>
+#else
+#   error "Unsupported platform."
+#endif
+
+#include <boost/noncopyable.hpp>
+#include <boost/scoped_array.hpp>
+#include <boost/assert.hpp>
+#include <streambuf>
+#include <cstddef>
+
+namespace boost {
+namespace process {
+
+class postream;
+
+namespace detail {
+
+/**
+ * std::streambuf implementation for handles.
+ *
+ * systembuf provides a std::streambuf implementation for handles.
+ * Contrarywise to the handle class, this class does \b not take
+ * ownership of the native handle; this should be taken care of
+ * somewhere else.
+ *
+ * This class follows the expected semantics of a std::streambuf object.
+ * However, it is not copyable to avoid introducing inconsistences with
+ * the on-disk file and the in-memory buffers.
+ */
+class systembuf : public std::streambuf, public boost::noncopyable
+{
+    friend class boost::process::postream;
+
+public:
+#if defined(BOOST_PROCESS_DOXYGEN)
+    /**
+     * Opaque name for the native handle type.
+     */
+    typedef NativeHandleType handle_type;
+#elif defined(BOOST_POSIX_API)
+    typedef int handle_type;
+#elif defined(BOOST_WINDOWS_API)
+    typedef HANDLE handle_type;
+#endif
+
+    /**
+     * Constructs a new systembuf for the given handle.
+     *
+     * This constructor creates a new systembuf object that reads or
+     * writes data from/to the \a h native handle. This handle
+     * is \b not owned by the created systembuf object; the code
+     * should take care of it externally.
+     *
+     * This class buffers input and output; the buffer size may be
+     * tuned through the \a bufsize parameter, which defaults to 8192
+     * bytes.
+     *
+     * \see pistream and postream
+     */
+    explicit systembuf(handle_type h, std::size_t bufsize = 8192)
+        : handle_(h),
+          bufsize_(bufsize),
+          read_buf_(new char[bufsize]),
+          write_buf_(new char[bufsize])
+    {
+#if defined(BOOST_POSIX_API)
+        BOOST_ASSERT(handle_ >= 0);
+#elif defined(BOOST_WINDOWS_API)
+        BOOST_ASSERT(handle_ != INVALID_HANDLE_VALUE);
+#endif
+        BOOST_ASSERT(bufsize_ > 0);
+        setp(write_buf_.get(), write_buf_.get() + bufsize_);
+    }
+
+protected:
+    /**
+     * Reads new data from the native handle.
+     *
+     * This operation is called by input methods when there is no more
+     * data in the input buffer. The function fills the buffer with new
+     * data, if available.
+     *
+     * \pre All input positions are exhausted (gptr() >= egptr()).
+     * \post The input buffer has new data, if available.
+     * \returns traits_type::eof() if a read error occurrs or there are
+     *          no more data to be read. Otherwise returns
+     *          traits_type::to_int_type(*gptr()).
+     */
+    virtual int_type underflow()
+    {
+        BOOST_ASSERT(gptr() >= egptr());
+
+        bool ok;
+#if defined(BOOST_POSIX_API)
+        ssize_t cnt = read(handle_, read_buf_.get(), bufsize_);
+        ok = (cnt != -1 && cnt != 0);
+#elif defined(BOOST_WINDOWS_API)
+        DWORD cnt;
+        BOOL res = ReadFile(handle_, read_buf_.get(), bufsize_, &cnt, NULL);
+        ok = (res && cnt > 0);
+#endif
+
+        if (!ok)
+            return traits_type::eof();
+        else
+        {
+            setg(read_buf_.get(), read_buf_.get(), read_buf_.get() + cnt);
+            return traits_type::to_int_type(*gptr());
+        }
+    }
+
+    /**
+     * Makes room in the write buffer for additional data.
+     *
+     * This operation is called by output methods when there is no more
+     * space in the output buffer to hold a new element. The function
+     * first flushes the buffer's contents to disk and then clears it to
+     * leave room for more characters. The given \a c character is
+     * stored at the beginning of the new space.
+     *
+     * \pre All output positions are exhausted (pptr() >= epptr()).
+     * \post The output buffer has more space if no errors occurred
+     *       during the write to disk.
+     * \post *(pptr() - 1) is \a c.
+     * \returns traits_type::eof() if a write error occurrs. Otherwise
+     *          returns traits_type::not_eof(c).
+     */
+    virtual int_type overflow(int c)
+    {
+        BOOST_ASSERT(pptr() >= epptr());
+
+        if (sync() == -1)
+            return traits_type::eof();
+
+        if (!traits_type::eq_int_type(c, traits_type::eof()))
+        {
+            traits_type::assign(*pptr(), static_cast<traits_type::char_type>(
+                c));
+            pbump(1);
+        }
+
+        return traits_type::not_eof(c);
+    }
+
+    /**
+     * Flushes the output buffer to disk.
+     *
+     * Synchronizes the systembuf buffers with the contents of the file
+     * associated to this object through the native handle. The output buffer
+     * is flushed to disk and cleared to leave new room for more data.
+     *
+     * \returns 0 on success, -1 if an error occurred.
+     */
+    virtual int sync()
+    {
+#if defined(BOOST_POSIX_API)
+        ssize_t cnt = pptr() - pbase();
+        bool ok = (write(handle_, pbase(), cnt) == cnt);
+        if (ok)
+            pbump(static_cast<int>(-cnt));
+        return ok ? 0 : -1;
+#elif defined(BOOST_WINDOWS_API)
+        long cnt = pptr() - pbase();
+        DWORD rcnt;
+        BOOL res = WriteFile(handle_, pbase(), cnt, &rcnt, NULL);
+        bool ok = (res && static_cast<long>(rcnt) == cnt);
+        if (ok)
+            pbump(-cnt);
+        return ok ? 0 : -1;
+#endif
+    }
+
+private:
+    /**
+     * Native handle used by the systembuf object.
+     */
+    handle_type handle_;
+
+    /**
+     * Internal buffer size used during read and write operations.
+     */
+    std::size_t bufsize_;
+
+    /**
+     * Internal buffer used during read operations.
+     */
+    boost::scoped_array<char> read_buf_;
+
+    /**
+     * Internal buffer used during write operations.
+     */
+    boost::scoped_array<char> write_buf_;
+};
+
+}
+}
+}
+
+#endif