From 2d4125b748718e05bede5d88c41b09597b4babce Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Wed, 22 Jan 2003 16:40:56 +0000 Subject: [PATCH] this should be the definitive (excluded bugfixes) implementation of BBufferIO. Buffered write should work fine, as buffered read did. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2530 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kits/support/BufferIO.cpp | 95 +++++++++++++++++++++++++---------- 1 file changed, 69 insertions(+), 26 deletions(-) diff --git a/src/kits/support/BufferIO.cpp b/src/kits/support/BufferIO.cpp index 867bf11ee8..756d137d2c 100644 --- a/src/kits/support/BufferIO.cpp +++ b/src/kits/support/BufferIO.cpp @@ -25,13 +25,6 @@ // Description: A buffered adapter for BPositionIO objects. //------------------------------------------------------------------------------ - -/* XXX: Currently, this class implement buffered reading, - but not (yet) buffered writing. - I'm doing tests to ensure that the implementation of the buffered - writing will be correct. -*/ - // Standard Includes ----------------------------------------------------------- #include #include @@ -39,7 +32,6 @@ // System Includes ------------------------------------------------------------- #include - /*! \class BBufferIO \brief A buffered adapter for BPositionIO objects. \author m_buffer_phys) - return ReadAt(pos, buffer, size); - + { + if (m_buffer_dirty) + Flush(); + return m_stream->ReadAt(pos, buffer, size); + } + // If the data we are looking for is not in the buffer... if (size > m_buffer_used || pos < m_buffer_start - || pos > m_buffer_start + m_buffer_used) + || pos > m_buffer_start + m_buffer_used + || pos + size > m_buffer_start + m_buffer_used) { + if (m_buffer_dirty) + Flush(); // If there are pending writes, do them. + // ...cache as much as we can from the stream m_buffer_used = m_stream->ReadAt(pos, m_buffer, m_buffer_phys); @@ -150,9 +151,45 @@ BBufferIO::WriteAt(off_t pos, const void *buffer, size_t size) if (m_stream == NULL) return B_NO_INIT; - // XXX: Implement buffered write + if (buffer == NULL) + return B_BAD_VALUE; - return m_stream->WriteAt(pos, buffer, size); + // If data doesn't fit into the buffer, write it directly to the stream + if (size > m_buffer_phys) + return m_stream->WriteAt(pos, buffer, size); + + // If we have cached data in the buffer, whose offset into the stream + // is > 0, and the buffer isn't dirty, drop the data. + if (!m_buffer_dirty && m_buffer_start > pos) + { + m_buffer_start = 0; + m_buffer_used = 0; + } + + // If we want to write beyond the cached data... + if (pos > m_buffer_start + m_buffer_used + || pos < m_buffer_start) + { + ssize_t read; + off_t where = pos; + + if (pos + size <= m_buffer_phys) // Can we just cache from the beginning ? + where = 0; + + // ...cache more. + read = m_stream->ReadAt(where, m_buffer, m_buffer_phys); + if (read > 0) + { + m_buffer_used = read; + m_buffer_start = where; + } + } + memcpy(m_buffer + pos - m_buffer_start, buffer, size); + m_buffer_dirty = true; + + m_buffer_used = max_c((size + pos), m_buffer_used); + + return size; } @@ -165,14 +202,14 @@ BBufferIO::WriteAt(off_t pos, const void *buffer, size_t size) \param position The position where you want to seek. \param seek_mode Can have three values: - - \oSEEK_SET. The position passed is an offset from the beginning of the stream; + - \c SEEK_SET. The position passed is an offset from the beginning of the stream; in other words, the current position is set to position. For this mode, position should be a positive value. - - \oSEEK_CUR. The position argument is an offset from the current position; + - \c SEEK_CUR. The position argument is an offset from the current position; the value of the argument is added to the current position. - - \oSEEK_END. The position argument is an offset from the end of the stream. + - \c SEEK_END. The position argument is an offset from the end of the stream. In this mode the position argument should be negative (or zero). \return The current position as an offset in bytes @@ -222,10 +259,16 @@ BBufferIO::SetSize(off_t size) status_t BBufferIO::Flush() { - m_buffer_dirty = false; + if (!m_buffer_dirty) + return B_OK; + + // Write the cached data to the stream + status_t err = m_stream->WriteAt(m_buffer_start, m_buffer, m_buffer_used); - // XXX: Not implemented... yet - return B_ERROR; + if (err > 0) + m_buffer_dirty = false; + + return (err < 0) ? err : B_OK; }