• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

src/StringBuffer.cpp

00001 /*
00002  *   This file is part of the Standard Portable Library (SPL).
00003  *
00004  *   SPL is free software: you can redistribute it and/or modify
00005  *   it under the terms of the GNU General Public License as published by
00006  *   the Free Software Foundation, either version 3 of the License, or
00007  *   (at your option) any later version.
00008  *
00009  *   SPL 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  *   You should have received a copy of the GNU General Public License
00015  *   along with SPL.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 #ifdef _WIN32
00018 #include <spl/configwin32.h>
00019 #include <stdio.h>
00020 #else
00021 #include <spl/autoconf/config.h>
00022 #endif
00023 #include <stdio.h>
00024 #include <memory.h>
00025 #include <spl/Int32.h>
00026 #include <spl/text/StringBuffer.h>
00027 
00028 void StringBuffer::Init(int size)
00029 {
00030         m_buf = new char[size];
00031         m_used = 0;
00032         m_len = size;
00033         m_buf[0] = '\0';
00034 }
00035 
00036 StringBuffer::StringBuffer()
00037 {
00038         Init(20);
00039 }
00040 
00041 StringBuffer::StringBuffer(const char *str)
00042 {
00043         Init((int)strlen(str) + 1);
00044         Append(str);
00045 }
00046 
00047 StringBuffer::StringBuffer(int size)
00048 {
00049         Init(size);
00050 }
00051 
00052 StringBuffer::StringBuffer(const StringBuffer& sb)
00053 {
00054         Init(sb.m_len + 1);
00055         Append(sb.m_buf);
00056 }
00057 
00058 StringBuffer::~StringBuffer()
00059 {
00060         delete[] m_buf;
00061 }
00062 
00063 #ifdef BSTR
00064 StringBuffer::StringBuffer(BSTR str)
00065 {
00066         m_len = SysStringLen(str) +1;
00067 
00068         m_buf = new char[len];
00069         for (m_used = 0; m_used < m_len; m_used++)
00070         {
00071                 buf[m_used] = (char)str[m_used];
00072         }
00073         m_buf[m_used] = '\0';
00074 }
00075 #endif
00076 
00077 void StringBuffer::Trim()
00078 {
00079         ASSERT_MEM(m_buf, m_len);
00080         int x;
00081         for (x = m_used-1; x >= 0; x--)
00082         {
00083                 if (m_buf[x] != ' ')
00084                 {
00085                         break;
00086                 } 
00087                 m_buf[x] = '\0';
00088         }
00089         m_used = x + 1;
00090         if ( ' ' == m_buf[0] )
00091         {
00092                 x = 1;
00093                 while ( ' ' == m_buf[x] )
00094                 {
00095                         x++;
00096                 }
00097                 ASSERT(' ' != m_buf[x]);
00098                 memcpy(&m_buf[0], &m_buf[x], m_used - x);
00099                 m_used -= x;
00100         }
00101         m_buf[m_used] = '\0';
00102 }
00103 
00104 /*
00105  *  Append characters to the end of the buffer.  Extend
00106  *  the buffer if needed.
00107  *  Throws OutOfMemoryException
00108  */
00109 void StringBuffer::Append(const char *str)
00110 {
00111         ASSERT_MEM(m_buf, m_len);
00112 
00113         int alen = (int)strlen(str);
00114 
00115         while (alen + m_used + 1 > m_len)
00116         {
00117                 Extend();
00118         }
00119         int x;
00120         for (x = 0; x < alen; x++)
00121         {
00122                 m_buf[m_used + x] = str[x];
00123         }
00124         m_buf[m_used + x] = '\0';
00125         m_used += alen;
00126 
00127         ASSERT(m_buf[m_used] == '\0');
00128 }
00129 
00130 void StringBuffer::Fill(char ch, int len)
00131 {
00132         while ( len-- > 0 )
00133         {
00134                 Append(ch);
00135         }
00136 }
00137 
00142 void StringBuffer::Insert(int index, const char *str)
00143 {
00144         ASSERT(m_buf[m_used] == '\0');
00145         ASSERT_MEM(m_buf, m_len);
00146 
00147         int x;
00148         int alen = (int)strlen(str);
00149 
00150         ExtendTo(m_used + alen + 1);
00151         for ( x = (m_used-index)-1; x >= 0; x-- )
00152         {
00153                 m_buf[index+alen+x] = m_buf[index+x];
00154         }
00155         for (x = 0; x < alen; x++)
00156         {
00157                 m_buf[index+x] = str[x];
00158         }
00159         m_used = m_used + alen;
00160         ASSERT( m_used < m_len );
00161         m_buf[m_used] = '\0';
00162         ValidateMem();
00163 }
00164 
00165 void StringBuffer::SetCharAt(const int index, char c)
00166 {
00167         ASSERT_MEM(m_buf, m_len);
00168         ASSERT(m_buf[m_used] == '\0');
00169 
00170         ExtendTo(index);
00171         m_buf[index] = c;
00172 
00173         if (index == m_used)
00174         {
00175                 if (m_used == m_len)
00176                 {
00177                         Extend();
00178                 }
00179                 m_buf[index+1] = '\0';
00180                 m_used++;
00181         }
00182         ASSERT(m_buf[m_used] == '\0');
00183         ASSERT_MEM(m_buf, m_len);
00184 }
00185 
00186 void StringBuffer::RemoveCharAt( int idx )
00187 {
00188         ASSERT_MEM(m_buf, m_len);
00189         ASSERT(m_buf[m_used] == '\0');
00190 
00191         if ( idx >= m_used || idx < 0 )
00192         {
00193                 return;
00194         }
00195         memmove( &m_buf[idx],  &m_buf[idx+1], m_used-idx );
00196         m_used--;
00197 }
00198 
00199 StringBuffer& StringBuffer::operator =(const char *str)
00200 {
00201         ASSERT_MEM(m_buf, m_len);
00202         m_used = 0;
00203         Append(str);
00204 
00205         return *this;
00206 }
00207 
00208 StringBuffer& StringBuffer::operator =(const StringBuffer& sb )
00209 {
00210         ASSERT_MEM(m_buf, m_len);
00211         m_used = 0;
00212         Append(sb.m_buf);
00213 
00214         return *this;
00215 }
00216 
00217 bool StringBuffer::IsNumeric() const
00218 {
00219         bool sawdot = false;
00220         ASSERT(m_buf[m_used] == '\0');
00221         ASSERT_MEM(m_buf, m_len);
00222 
00223         for (int x = 0; x < m_used; x++)
00224         {
00225                 if (! isdigit(m_buf[x]))
00226                 {
00227                         if ( !sawdot && '.' == m_buf[x] )
00228                         {
00229                                 sawdot = true;
00230                         }
00231                         else
00232                         {
00233                                 return false;
00234                         }
00235                 }
00236         }
00237         return true;
00238 }
00239 
00240 int StringBuffer::ToInt() const
00241 {
00242         return Int32::Parse(m_buf);
00243 }
00244 
00245 void StringBuffer::ExtendTo(int index)
00246 {
00247         ASSERT_MEM(m_buf, m_len);
00248 
00249         if (index > m_len)
00250         {
00251                 char *newbuf;
00252 
00253                 if ((newbuf = new char[index + 1]) == NULL)
00254                 {
00255                         throw OutOfMemoryException();
00256                 }
00257                 memcpy(newbuf, m_buf, m_len);
00258                 m_len = index+1;
00259                 delete[] m_buf;
00260                 m_buf = newbuf;
00261                 ASSERT_MEM(m_buf, m_len);
00262         }
00263         //if (index > used)
00264         //{
00265         //      int x;
00266         //      for (x = used+1; x < index; x++)
00267         //      {
00268         //              buf[x] = ' ';
00269         //      }
00270         //      //buf[used] = '\0';
00271         //}
00272         ASSERT(m_buf[m_used] == '\0');
00273         ASSERT_MEM(m_buf, m_len);
00274 }
00275 
00276 void StringBuffer::Extend()
00277 {
00278         ASSERT_MEM(m_buf, m_len);
00279 
00280         int newlen = m_len*2;
00281         char *newbuf;
00282 
00283         newbuf = new char[newlen];
00284 
00285         memcpy(newbuf, m_buf, m_len);
00286         m_len = newlen;
00287         delete[] m_buf;
00288         m_buf = newbuf;
00289         ASSERT_MEM(m_buf, m_len);
00290 }
00291 
00292 int StringBuffer::IndexOf( const char *cp, const int start ) const
00293 {
00294         for ( int pos = start; pos < m_len; pos++ )
00295         {
00296                 int end;
00297                 int cppos = 1;
00298 
00299                 if ( m_buf[pos] == cp[0] )
00300                 {
00301                         for( end = pos+1; end < m_len && cp[cppos] != '\0'; end++ )
00302                         {
00303                                 if ( m_buf[end] != cp[cppos] )
00304                                 {
00305                                         break;
00306                                 }
00307                                 cppos++;
00308                         }
00309                         if ( cp[cppos] == '\0' )
00310                         {
00311                                 return pos;
00312                         }
00313                 }
00314         }
00315         return -1;
00316 }
00317 
00318 int StringBuffer::IndexOfIgnoreCase( const char *cp, const int start ) const
00319 {
00320         for ( int pos = start; pos < m_len; pos++ )
00321         {
00322                 if ( tolower(m_buf[pos]) == tolower(cp[0]) )
00323                 {
00324                         int end;
00325                         int cppos = 1;
00326                         for( end = pos+1; end < m_len && cp[cppos] != '\0'; end++ )
00327                         {
00328                                 if ( m_buf[end] != cp[cppos] && tolower(m_buf[end]) != tolower(cp[cppos]) )
00329                                 {
00330                                         break;
00331                                 }
00332                                 cppos++;
00333                         }
00334                         if ( cp[cppos] == '\0' )
00335                         {
00336                                 return pos;
00337                         }
00338                 }
00339         }
00340         return -1;
00341 }
00342 
00343 void StringBuffer::Replace( const char from, const char to )
00344 {
00345         for ( int x = 0; x < m_used; x++ )
00346         {
00347                 if ( m_buf[x] == from )
00348                 {
00349                         m_buf[x] = to;
00350                 }
00351         }
00352 }
00353 
00354 void StringBuffer::ToLower()
00355 {
00356         for (int x = 0; x < m_used; x++)
00357         {
00358                 m_buf[x] = tolower(m_buf[x]);
00359         }
00360 }
00361 
00362 void StringBuffer::ToUpper()
00363 {
00364         for (int x = 0; x < m_used; x++)
00365         {
00366                 m_buf[x] = toupper(m_buf[x]);
00367         }
00368 }
00369 
00370 StringPtr StringBuffer::ToString() const
00371 {
00372         return StringPtr( new String(m_buf) );
00373 }
00374 
00375 RefCountPtr<Array<byte> > StringBuffer::ToByteArray() const
00376 {
00377         return String(m_buf).ToByteArray();
00378 }
00379 
00380 #if defined(DEBUG)
00381 void StringBuffer::CheckMem() const
00382 {
00383         DEBUG_NOTE_MEM_ALLOCATION(m_buf);
00384 }
00385 
00386 void StringBuffer::ValidateMem() const
00387 {
00388         ASSERT_MEM(m_buf, m_len);
00389 }
00390 #endif
00391