• Main Page
  • Classes
  • Files
  • File List
  • File Members

Beesnest/DcBuffer.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright 2007 Erez Bibi (erezbibi@users.sourceforge.net)
00003 This file is part of Beesnest.
00004 
00005 Beesnest is free software; you can redistribute it and/or modify
00006 it under the terms of the GNU General Public License as published by
00007 the Free Software Foundation; either version 2 of the License, or
00008 (at your option) any later version.
00009 
00010 Beesnest 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 Beesnest; if not, write to the Free Software
00017 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018 */
00019 
00020 /**
00021  * CdcBuffer.cpp: implementation of the CdcBuffer class.
00022  * for documentation see the header file.
00023  */
00024 
00025 #include "DcBuffer.h"
00026 
00027 CdcBuffer::CdcBuffer()
00028 : aBuffer (NULL), nSize (0), nGrow (DEFAULT_SIZE), nDataSize (0),
00029     pRefCount (new int (1)), pMutex (new CdcMutex ())
00030 { }
00031 
00032 
00033 CdcBuffer::CdcBuffer (unsigned int size, int grow) throw (CdcException)
00034 : aBuffer (NULL), nSize (0), nGrow (grow), nDataSize (0),
00035     pRefCount (new int (1)), pMutex (new CdcMutex ())
00036 {
00037     PreperRoom (size);
00038 }
00039 
00040 
00041 void CdcBuffer::PreperRoom (int size) throw (CdcException)
00042 {
00043     bool ref_copy = false;
00044     bool increase_space = false;
00045     /* Lock the object. */
00046     pMutex->Lock ();
00047     /* Check if need to create another object because Copy On Write. */
00048     if (*pRefCount > 1)
00049     {
00050         --(*pRefCount);
00051         pRefCount = new int (1);
00052         ref_copy = true;
00053     }
00054     /* Check if need to increase the space in the buffer. */
00055     if (nSize < nDataSize + size)
00056     {
00057         increase_space = true;
00058         /* Find how many 'grow' units need to add. */
00059         if (nGrow < 1) nGrow = DEFAULT_SIZE;
00060         int factor = (((nDataSize + size) - nSize) / nGrow) + 1;
00061         nSize += factor * nGrow;
00062     }
00063     /* If one of the conditions are true. */
00064     if (increase_space || ref_copy)
00065     {
00066         /* allocate new space. */
00067         t_buff_unit* temp = new t_buff_unit [nSize];
00068         if (temp == NULL)
00069         {   /* This "complected" section is in case of allocation error. */
00070             pMutex->Unlock ();
00071             if (ref_copy == true)
00072             {
00073                 aBuffer = NULL;
00074                 pMutex = NULL;
00075             }
00076             throw (CdcException ("Out of memory!"));
00077         }
00078         /* Copy the first part of the buffer. */
00079         memcpy (temp, aBuffer, nDataSize);
00080         /* Delete old buffer if no other object points to it. */
00081         if (!ref_copy && aBuffer != NULL)
00082             delete aBuffer;
00083         /* Point to new buffer. */
00084         aBuffer = temp;
00085     }
00086     /* Unlock the object and make a new Mutex if needed. */
00087     pMutex->Unlock ();
00088     if (ref_copy)
00089         pMutex = new CdcMutex ();
00090 }
00091 
00092 
00093 void CdcBuffer::Attach (const CdcBuffer& buff)
00094 {
00095     /* Lock the object. */
00096     buff.pMutex->Lock ();
00097     /* Copy values. */
00098     aBuffer = buff.aBuffer;
00099     pRefCount = buff.pRefCount;
00100     nDataSize = buff.nDataSize;
00101     nSize = buff.nSize;
00102     nGrow = buff.nGrow;
00103     pMutex = buff.pMutex;
00104     /* Increase reference. */
00105     (*pRefCount)++;
00106     /* Unlock object. */
00107     buff.pMutex->Unlock ();
00108 }
00109 
00110 
00111 void CdcBuffer::Detach ()
00112 {
00113     /* Lock the object. */
00114     pMutex->Lock ();
00115     /* Decrease reference counter and delete buffer if needed. */
00116     if (--(*pRefCount) == 0)
00117     {
00118         if (aBuffer != NULL)
00119         {
00120             delete aBuffer;
00121             aBuffer = NULL;
00122         }
00123         if (pRefCount != NULL)
00124         {
00125             delete pRefCount;
00126             pRefCount = NULL;
00127         }
00128         /* Deletion of the Mutex will unlock it. */
00129         delete pMutex;
00130     }
00131     else
00132         pMutex->Unlock ();
00133 }
00134 
00135 
00136 const CdcBuffer& CdcBuffer::operator = (const CdcBuffer& buff)
00137 {
00138     if (aBuffer != buff.aBuffer)
00139     {
00140         Detach ();
00141         Attach (buff);
00142     }
00143 
00144     return *this;
00145 }
00146 
00147 
00148 t_buff_unit CdcBuffer::operator[] (int index) const throw (CdcException)
00149 {
00150     if (index < 0 || index >= nDataSize)
00151         throw (CdcException ("Index out of bounds!"));
00152 
00153     return aBuffer [index];
00154 }
00155 
00156 
00157 CdcBuffer& CdcBuffer::Append (const t_buff_unit data) throw (CdcException)
00158 {
00159     PreperRoom (1);
00160     aBuffer [nDataSize++] = data;
00161     return *this;
00162 }
00163 
00164 CdcBuffer& CdcBuffer::Append (CdcString& data) throw (CdcException)
00165 {
00166     PreperRoom (data.GetLength ());
00167     memcpy (aBuffer + nDataSize, data.GetBuffer (),
00168         data.GetLength ());
00169     nDataSize += data.GetLength ();
00170     return *this;
00171 }
00172 
00173 CdcBuffer& CdcBuffer::Append (const CdcBuffer& data) throw (CdcException)
00174 {
00175     PreperRoom (data.nDataSize);
00176     memcpy (aBuffer + nDataSize, data.aBuffer, data.nDataSize);
00177     nDataSize += data.nDataSize;
00178     return *this;
00179 }
00180 
00181 CdcBuffer& CdcBuffer::Append (int data) throw (CdcException)
00182 {
00183     char temp [15];
00184     sprintf (temp, "%d", data);
00185     Append (temp);
00186     return *this;
00187 }
00188 
00189 CdcBuffer& CdcBuffer::Append (const t_buff_unit* data,
00190                               int length) throw (CdcException)
00191 {
00192     if (length < 0)
00193         length = strlen (data);
00194 
00195     PreperRoom (length);
00196     memcpy (aBuffer + nDataSize, data, length);
00197     nDataSize += length;
00198     return *this;
00199 }
00200 
00201 
00202 int CdcBuffer::GetSize () const
00203 {
00204     return nSize;
00205 }
00206 
00207 int CdcBuffer::GetDataSize () const
00208 {
00209     return nDataSize;
00210 }
00211 
00212 t_buff_unit* CdcBuffer::GetPointer () const
00213 {
00214     return aBuffer;
00215 }
00216 
00217 /* This function works with the brute-force algorithm for now... */
00218 int CdcBuffer::Find (const char* str, int start, int stop) const
00219 {
00220     if (str == NULL) return -1;
00221     if (start >= nDataSize) return -1;
00222     if (stop == 0) stop = nDataSize;
00223     char* pbuf = aBuffer + start;
00224     int str_leng = strlen (str), i;
00225 
00226     while (pbuf - aBuffer <= stop - str_leng)
00227     {
00228         i = 0;
00229         while (pbuf[i] == str[i])
00230             if (++i == str_leng)
00231                 return pbuf - aBuffer;
00232         pbuf++;
00233     }
00234 
00235     return -1;
00236 }
00237 
00238 
00239 int CdcBuffer::Find (char chr, int start, int stop) const
00240 {
00241     if (start >= nDataSize) return -1;
00242     if (stop == 0) stop = nDataSize;
00243     char* pbuf = aBuffer + start;
00244 
00245     while (pbuf - aBuffer < stop)
00246         if (*pbuf == chr)
00247             return pbuf - aBuffer;
00248         else
00249             ++pbuf;
00250 
00251     return -1;
00252 }
00253 
00254 
00255 int CdcBuffer::ReplaceAll (const char* strold, const char* strnew,
00256                            int stroldlen, int strnewlen,
00257                            int start, int stop)
00258 {
00259     if (strold == NULL) return 0;
00260     int count = 1;
00261     int list [100]; /* cannot make more then 100 replaces. */
00262     /* Deal with the lengths of strings. */
00263     if (stroldlen < 0)
00264         stroldlen = strlen (strold);
00265     if (strnewlen < 0)
00266         strnewlen = strlen (strnew);
00267     /* Make list of place to replace (temp is for string without NULL). */
00268     CdcString temp (strold, stroldlen);
00269     list[0] = Find (temp, start, stop);
00270     if (list[0] == -1) return 0;
00271     while ((list[count] = Find (temp, list [count - 1] + 1, stop)) != -1)
00272     {
00273         ++count;
00274         if (count == 100) return 0;
00275     }
00276     /* Find how much to enlarge the buffer. We want to call PreperRoom
00277         even if size-gap is zero or negetive.*/
00278     int i, size_gap = (strnewlen - stroldlen);
00279     PreperRoom (size_gap * count);
00280     /* Move the parts we want to save to make room to the new strings. */
00281     for (i = 0; i < count; ++i)
00282         memmove (aBuffer + list[i] + (size_gap * i) + strnewlen,
00283                  aBuffer + list[i] + (size_gap * i) + stroldlen,
00284                  nDataSize - (list[i] + stroldlen));
00285     /* Copy the new string to the new rooms. */
00286     for (i = 0; i < count; ++i)
00287         memcpy (aBuffer + list[i] + (size_gap * i),
00288                 strnew, strnewlen);
00289 
00290     nDataSize += (size_gap * count);
00291     return count;
00292 }
00293 
00294 
00295 int CdcBuffer::ReplaceAll (char old_chr, char new_chr)
00296 {
00297     /* Copy the buffer if there is more then one reference. */
00298     PreperRoom (0);
00299     int place = -1, count = 0;
00300 
00301     while ((place = Find (old_chr, place + 1)) != -1)
00302     {
00303         aBuffer [place] = new_chr;
00304         ++ count;
00305     }
00306 
00307     return count;
00308 }
00309 
00310 
00311 bool CdcBuffer::IsWhiteSpaces (int start, int stop)
00312 {
00313     if (start >= nDataSize) return false;
00314     if (stop == 0) stop = nDataSize;
00315     if (stop < start) return false;
00316 
00317     for (int i = start; i < stop; ++i)
00318         if (isspace (aBuffer[i]) == false)
00319             return false;   /* found non white space. */
00320     return true;            /* Go to end of scan area. */
00321 }

Generated on Mon Oct 11 2010 16:23:23 for Beesnest by  doxygen 1.7.2