Logo
~Sockets~
~Examples~
~Contact~


CircularBuffer.cpp

Go to the documentation of this file.
00001 
00005 /*
00006 Copyright (C) 2004-2007  Anders Hedstrom
00007 
00008 This library is made available under the terms of the GNU GPL.
00009 
00010 If you would like to use this library in a closed-source application,
00011 a separate license agreement is available. For information about 
00012 the closed-source license agreement for the C++ sockets library,
00013 please visit http://www.alhem.net/Sockets/license.html and/or
00014 email license@alhem.net.
00015 
00016 This program is free software; you can redistribute it and/or
00017 modify it under the terms of the GNU General Public License
00018 as published by the Free Software Foundation; either version 2
00019 of the License, or (at your option) any later version.
00020 
00021 This program is distributed in the hope that it will be useful,
00022 but WITHOUT ANY WARRANTY; without even the implied warranty of
00023 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024 GNU General Public License for more details.
00025 
00026 You should have received a copy of the GNU General Public License
00027 along with this program; if not, write to the Free Software
00028 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00029 */
00030 #ifdef _WIN32
00031 #pragma warning(disable:4786)
00032 #endif
00033 #include "CircularBuffer.h"
00034 #include <string.h>
00035 
00036 #include "Socket.h"
00037 #include "SocketHandler.h"
00038 
00039 #ifdef SOCKETS_NAMESPACE
00040 namespace SOCKETS_NAMESPACE {
00041 #endif
00042 
00043 
00044 CircularBuffer::CircularBuffer(Socket& owner,size_t size)
00045 :m_owner(owner)
00046 ,buf(new char[2 * size])
00047 ,m_max(size)
00048 ,m_q(0)
00049 ,m_b(0)
00050 ,m_t(0)
00051 ,m_count(0)
00052 {
00053 }
00054 
00055 
00056 CircularBuffer::~CircularBuffer()
00057 {
00058         delete[] buf;
00059 }
00060 
00061 
00062 bool CircularBuffer::Write(const char *s,size_t l)
00063 {
00064         if (m_q + l > m_max)
00065         {
00066                 m_owner.Handler().LogError(&m_owner, "CircularBuffer::Write", -1, "write buffer overflow");
00067                 return false; // overflow
00068         }
00069         m_count += (unsigned long)l;
00070         if (m_t + l > m_max) // block crosses circular border
00071         {
00072                 size_t l1 = m_max - m_t; // size left until circular border crossing
00073                 // always copy full block to buffer(buf) + top pointer(m_t)
00074                 // because we have doubled the buffer size for performance reasons
00075                 memcpy(buf + m_t, s, l);
00076                 memcpy(buf, s + l1, l - l1);
00077                 m_t = l - l1;
00078                 m_q += l;
00079         }
00080         else
00081         {
00082                 memcpy(buf + m_t, s, l);
00083                 memcpy(buf + m_max + m_t, s, l);
00084                 m_t += l;
00085                 if (m_t >= m_max)
00086                         m_t -= m_max;
00087                 m_q += l;
00088         }
00089         return true;
00090 }
00091 
00092 
00093 bool CircularBuffer::Read(char *s,size_t l)
00094 {
00095         if (l > m_q)
00096         {
00097                 m_owner.Handler().LogError(&m_owner, s ? "CircularBuffer::Read" : "CircularBuffer::Write", -1, "attempt to read beyond buffer");
00098                 return false; // not enough chars
00099         }
00100         if (m_b + l > m_max) // block crosses circular border
00101         {
00102                 size_t l1 = m_max - m_b;
00103                 if (s)
00104                 {
00105                         memcpy(s, buf + m_b, l1);
00106                         memcpy(s + l1, buf, l - l1);
00107                 }
00108                 m_b = l - l1;
00109                 m_q -= l;
00110         }
00111         else
00112         {
00113                 if (s)
00114                 {
00115                         memcpy(s, buf + m_b, l);
00116                 }
00117                 m_b += l;
00118                 if (m_b >= m_max)
00119                         m_b -= m_max;
00120                 m_q -= l;
00121         }
00122         if (!m_q)
00123         {
00124                 m_b = m_t = 0;
00125         }
00126         return true;
00127 }
00128 
00129 
00130 bool CircularBuffer::Remove(size_t l)
00131 {
00132         return Read(NULL, l);
00133 }
00134 
00135 
00136 size_t CircularBuffer::GetLength()
00137 {
00138         return m_q;
00139 }
00140 
00141 
00142 const char *CircularBuffer::GetStart()
00143 {
00144         return buf + m_b;
00145 }
00146 
00147 
00148 size_t CircularBuffer::GetL()
00149 {
00150         return (m_b + m_q > m_max) ? m_max - m_b : m_q;
00151 }
00152 
00153 
00154 size_t CircularBuffer::Space()
00155 {
00156         return m_max - m_q;
00157 }
00158 
00159 
00160 unsigned long CircularBuffer::ByteCounter(bool clear)
00161 {
00162         if (clear)
00163         {
00164                 unsigned long x = m_count;
00165                 m_count = 0;
00166                 return x;
00167         }
00168         return m_count;
00169 }
00170 
00171 
00172 Socket& CircularBuffer::GetOwner() const 
00173 { 
00174         return m_owner; 
00175 }
00176 
00177 
00178 std::string CircularBuffer::ReadString(size_t l)
00179 {
00180         char *sz = new char[l + 1];
00181         if (!Read(sz, l)) // failed, debug printout in Read() method
00182         {
00183                 delete[] sz;
00184                 return "";
00185         }
00186         sz[l] = 0;
00187         std::string tmp = sz;
00188         delete[] sz;
00189         return tmp;
00190 }
00191 
00192 
00193 #ifdef SOCKETS_NAMESPACE
00194 }
00195 #endif
00196 
Page, code, and content Copyright (C) 2007 by Anders Hedström
Generated for C++ Sockets by  doxygen 1.4.4