diff deps/Platinum/Source/Core/PltStreamPump.cpp @ 0:3425707ddbf6

Initial import (hopefully this mercurial stuff works...)
author fraserofthenight
date Mon, 06 Jul 2009 08:06:28 -0700
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltStreamPump.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,226 @@
+/*****************************************************************
+|
+|   Platinum - Stream Pump
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltStreamPump.h"
+#include "NptUtils.h"
+
+/*----------------------------------------------------------------------
+|   PLT_StreamPump::PLT_StreamPump
++---------------------------------------------------------------------*/
+PLT_StreamPump::PLT_StreamPump(NPT_Size size) :
+    m_TotalBytesRead(0),
+    m_TotalBytesWritten(0)
+{
+    m_RingBuffer = new NPT_RingBuffer(size);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_StreamPump::~PLT_StreamPump
++---------------------------------------------------------------------*/
+PLT_StreamPump::~PLT_StreamPump()
+{
+    delete m_RingBuffer;
+}
+/*----------------------------------------------------------------------+
+|    PLT_StreamPump::PushData
++----------------------------------------------------------------------*/
+NPT_Result
+PLT_StreamPump::PushData(NPT_OutputStream& output, 
+                         NPT_Size&         bytes_written)
+{
+    NPT_Result res = NPT_ERROR_WOULD_BLOCK;
+    NPT_Size   count = 0;
+    NPT_Size   bytes_available = m_RingBuffer->GetContiguousAvailable();
+
+    bytes_written = 0;
+
+    if (bytes_available) {
+        res = output.Write(m_RingBuffer->GetReadPointer(), bytes_available, &count);
+        m_RingBuffer->MoveOut(count);
+        bytes_written += count;
+
+        // check if we wrapped around
+        bytes_available = m_RingBuffer->GetContiguousAvailable();
+        if (NPT_SUCCEEDED(res) && bytes_available) {
+            res = output.Write(m_RingBuffer->GetReadPointer(), bytes_available, &count);
+            m_RingBuffer->MoveOut(count);
+            bytes_written += count;
+        }
+    }
+
+    m_TotalBytesWritten += bytes_written;
+
+    return res;
+}
+
+/*----------------------------------------------------------------------+
+|    PLT_StreamPump::PullData
++----------------------------------------------------------------------*/
+NPT_Result
+PLT_StreamPump::PullData(NPT_InputStream& input, 
+                         NPT_Size         max_bytes_to_read)
+{
+    NPT_Result res = NPT_ERROR_WOULD_BLOCK;
+    NPT_Size   byte_space = m_RingBuffer->GetContiguousSpace();
+
+    // check that there is space left
+    // make sure we don't read more than our contiguous space
+    NPT_Size nb_to_read = (max_bytes_to_read<byte_space)?max_bytes_to_read:byte_space;
+    if (nb_to_read > 0) {
+        NPT_Size count;
+        res = input.Read(m_RingBuffer->GetWritePointer(), nb_to_read, &count);
+        m_RingBuffer->MoveIn(count);
+        max_bytes_to_read -= count;
+        m_TotalBytesRead += count;
+
+        byte_space = m_RingBuffer->GetContiguousSpace();
+        nb_to_read = (max_bytes_to_read<byte_space)?max_bytes_to_read:byte_space;
+        // if we filled our contiguous space, and we wrapped, check if there is more to read 
+        if (NPT_SUCCEEDED(res) && (nb_to_read > 0)) {
+            res = input.Read(m_RingBuffer->GetWritePointer(), nb_to_read, &count);
+            m_RingBuffer->MoveIn(count);
+            m_TotalBytesRead += count;
+        }
+    }
+
+    return res;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_PipeInputStreamPump::PLT_PipeInputStreamPump
++---------------------------------------------------------------------*/
+PLT_PipeInputStreamPump::PLT_PipeInputStreamPump(NPT_OutputStreamReference& output,
+                                                 NPT_Size                   size) : 
+    PLT_StreamPump(size),
+    m_Output(output),
+    m_LastRes(NPT_SUCCESS)
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_PipeInputStreamPump::~PLT_PipeInputStreamPump
++---------------------------------------------------------------------*/
+PLT_PipeInputStreamPump::~PLT_PipeInputStreamPump()
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_PipeInputStreamPump::Receive
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_PipeInputStreamPump::Receive(NPT_InputStream& input, 
+                                 NPT_Size         max_bytes_to_read, 
+                                 NPT_Size*        bytes_read)
+{
+    NPT_Size count;
+    NPT_Result res;
+
+    if ((m_LastRes == NPT_SUCCESS) || (m_LastRes == NPT_ERROR_WOULD_BLOCK)) {
+        // look at what we have buffered already from out input
+        // and if have less than what was asked, read more
+        NPT_Size available = m_RingBuffer->GetAvailable();
+        if (available < max_bytes_to_read) {
+            m_LastRes = PullData(input, max_bytes_to_read-available);
+        }    
+    } else if (!m_RingBuffer->GetAvailable()) {
+        // if the buffer is now empty, return the input last error
+        return m_LastRes;
+    }
+    
+    // write as much as we can on the output stream
+    res = PushData(*m_Output, count);
+
+    if (bytes_read) *bytes_read = count;
+    return res;
+}
+
+
+/*----------------------------------------------------------------------
+|   PLT_PipeOutputStreamPump::PLT_PipeOutputStreamPump
++---------------------------------------------------------------------*/
+PLT_PipeOutputStreamPump::PLT_PipeOutputStreamPump(NPT_InputStreamReference& input,
+                                                   NPT_Size                  size /* 65535 */,
+                                                   NPT_Size                  max_bytes_to_read /* = 0 */) : 
+    PLT_StreamPump(size),
+    m_Input(input),
+    m_MaxBytesToRead(max_bytes_to_read),
+    m_LastRes(NPT_SUCCESS)
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_PipeOutputStreamPump::~PLT_PipeOutputStreamPump
++---------------------------------------------------------------------*/
+PLT_PipeOutputStreamPump::~PLT_PipeOutputStreamPump()
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_PipeOutputStreamPump::Transmit
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_PipeOutputStreamPump::Transmit(NPT_OutputStream& output)
+{
+    NPT_Size count;
+    NPT_Result res;
+
+    if ((m_LastRes == NPT_SUCCESS) || (m_LastRes == NPT_ERROR_WOULD_BLOCK)) {
+        // fill the entire space by default
+        NPT_Size max_space   = m_RingBuffer->GetSpace();
+        if (max_space) {
+            NPT_Size max_to_read = max_space;
+            if (m_MaxBytesToRead != 0) {
+                // if a total maximum amount was set, make sure we don't read more
+                max_to_read = ((m_MaxBytesToRead - m_TotalBytesRead) < max_space) ? (m_MaxBytesToRead - m_TotalBytesRead) : max_space;
+            }
+
+            // any data to read
+            if (max_to_read) {
+                m_LastRes = PullData(*m_Input, max_to_read);   
+            } else {
+                m_LastRes = NPT_ERROR_EOS;
+            }
+        }    
+    } else if (!m_RingBuffer->GetAvailable()) {
+        // if the buffer is now empty, return the input last error
+        return m_LastRes;
+    }
+
+    // write as much as we can on the output stream
+    res = PushData(output, count);
+    return res;
+}
+