CStreamBuffer.cpp

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

Generated on Fri Nov 6 00:18:45 2009 for synergy-plus by  doxygen 1.4.7