• Main Page
  • Classes
  • Files
  • File List

CStreamBuffer.cpp

00001 /*
00002  * synergy -- mouse and keyboard sharing utility
00003  * Copyright (C) 2012 Bolton Software Ltd.
00004  * Copyright (C) 2002 Chris Schoeneman
00005  * 
00006  * This package is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * found in the file COPYING that should have accompanied this file.
00009  * 
00010  * This package is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017  */
00018 
00019 #include "CStreamBuffer.h"
00020 
00021 //
00022 // CStreamBuffer
00023 //
00024 
00025 const UInt32            CStreamBuffer::kChunkSize = 4096;
00026 
00027 CStreamBuffer::CStreamBuffer() :
00028     m_size(0),
00029     m_headUsed(0)
00030 {
00031     // do nothing
00032 }
00033 
00034 CStreamBuffer::~CStreamBuffer()
00035 {
00036     // do nothing
00037 }
00038 
00039 const void*
00040 CStreamBuffer::peek(UInt32 n)
00041 {
00042     assert(n <= m_size);
00043 
00044     // if requesting no data then return NULL so we don't try to access
00045     // an empty list.
00046     if (n == 0) {
00047         return NULL;
00048     }
00049 
00050     // reserve space in first chunk
00051     ChunkList::iterator head = m_chunks.begin();
00052     head->reserve(n + m_headUsed);
00053 
00054     // consolidate chunks into the first chunk until it has n bytes
00055     ChunkList::iterator scan = head;
00056     ++scan;
00057     while (head->size() - m_headUsed < n && scan != m_chunks.end()) {
00058         head->insert(head->end(), scan->begin(), scan->end());
00059         scan = m_chunks.erase(scan);
00060     }
00061 
00062     return reinterpret_cast<const void*>(&(head->begin()[m_headUsed]));
00063 }
00064 
00065 void
00066 CStreamBuffer::pop(UInt32 n)
00067 {
00068     // discard all chunks if n is greater than or equal to m_size
00069     if (n >= m_size) {
00070         m_size     = 0;
00071         m_headUsed = 0;
00072         m_chunks.clear();
00073         return;
00074     }
00075 
00076     // update size
00077     m_size -= n;
00078 
00079     // discard chunks until more than n bytes would've been discarded
00080     ChunkList::iterator scan = m_chunks.begin();
00081     assert(scan != m_chunks.end());
00082     while (scan->size() - m_headUsed <= n) {
00083         n         -= (UInt32)scan->size() - m_headUsed;
00084         m_headUsed = 0;
00085         scan       = m_chunks.erase(scan);
00086         assert(scan != m_chunks.end());
00087     }
00088 
00089     // remove left over bytes from the head chunk
00090     if (n > 0) {
00091         m_headUsed += n;
00092     }
00093 }
00094 
00095 void
00096 CStreamBuffer::write(const void* vdata, UInt32 n)
00097 {
00098     assert(vdata != NULL);
00099 
00100     // ignore if no data, otherwise update size
00101     if (n == 0) {
00102         return;
00103     }
00104     m_size += n;
00105 
00106     // cast data to bytes
00107     const UInt8* data = reinterpret_cast<const UInt8*>(vdata);
00108 
00109     // point to last chunk if it has space, otherwise append an empty chunk
00110     ChunkList::iterator scan = m_chunks.end();
00111     if (scan != m_chunks.begin()) {
00112         --scan;
00113         if (scan->size() >= kChunkSize) {
00114             ++scan;
00115         }
00116     }
00117     if (scan == m_chunks.end()) {
00118         scan = m_chunks.insert(scan, Chunk());
00119     }
00120 
00121     // append data in chunks
00122     while (n > 0) {
00123         // choose number of bytes for next chunk
00124         assert(scan->size() <= kChunkSize);
00125         UInt32 count = kChunkSize - (UInt32)scan->size();
00126         if (count > n)
00127             count = n;
00128 
00129         // transfer data
00130         scan->insert(scan->end(), data, data + count);
00131         n    -= count;
00132         data += count;
00133 
00134         // append another empty chunk if we're not done yet
00135         if (n > 0) {
00136             ++scan;
00137             scan = m_chunks.insert(scan, Chunk());
00138         }
00139     }
00140 }
00141 
00142 UInt32
00143 CStreamBuffer::getSize() const
00144 {
00145     return m_size;
00146 }

Generated on Sat May 25 2013 00:00:04 for Synergy by  doxygen 1.7.1