StringBuffer.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2004 Vintela, Inc. All rights reserved.
00003 * Copyright (C) 2005 Novell, Inc. All rights reserved.
00004 *
00005 * Redistribution and use in source and binary forms, with or without
00006 * modification, are permitted provided that the following conditions are met:
00007 *
00008 *  - Redistributions of source code must retain the above copyright notice,
00009 *    this list of conditions and the following disclaimer.
00010 *
00011 *  - Redistributions in binary form must reproduce the above copyright notice,
00012 *    this list of conditions and the following disclaimer in the documentation
00013 *    and/or other materials provided with the distribution.
00014 *
00015 *  - Neither the name of Vintela, Inc., Novell, Inc., nor the names of its
00016 *    contributors may be used to endorse or promote products derived from this
00017 *    software without specific prior written permission.
00018 *
00019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc., Novell, Inc., OR THE 
00023 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00024 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
00025 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
00026 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
00027 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
00028 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
00029 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 *******************************************************************************/
00031 
00032 
00038 #include "blocxx/BLOCXX_config.h"
00039 #include "blocxx/StringBuffer.hpp"
00040 #include "blocxx/Char16.hpp"
00041 
00042 #include <cstring>
00043 #include <cstdio>
00044 #include <cctype>
00045 #if defined(BLOCXX_HAVE_ISTREAM) && defined(BLOCXX_HAVE_OSTREAM)
00046 #include <istream>
00047 #include <ostream>
00048 #else
00049 #include <iostream>
00050 #endif
00051 #include <algorithm> // for std::swap
00052 #include <cfloat> // for DBL_MANT_DIG
00053 
00054 namespace BLOCXX_NAMESPACE
00055 {
00056 
00057 #if defined(BLOCXX_AIX)
00058 const size_t StringBuffer::BLOCXX_DEFAULT_ALLOCATION_UNIT = 128;
00059 #endif // BLOCXX_AIX
00060 
00061 StringBuffer::StringBuffer(size_t allocSize) :
00062    m_len(0),
00063    m_allocated(allocSize > 0 ? allocSize : BLOCXX_DEFAULT_ALLOCATION_UNIT),
00064    m_bfr(new char[m_allocated])
00065 {
00066    m_bfr[0] = 0;
00067 }
00069 StringBuffer::StringBuffer(const char* arg) :
00070    m_len(strlen(arg)),
00071    m_allocated(m_len + BLOCXX_DEFAULT_ALLOCATION_UNIT),
00072    m_bfr(new char[m_allocated])
00073 {
00074    ::strcpy(m_bfr, arg);
00075 }
00077 StringBuffer::StringBuffer(const String& arg) :
00078    m_len(arg.length()),
00079    m_allocated(m_len + BLOCXX_DEFAULT_ALLOCATION_UNIT),
00080    m_bfr(new char[m_allocated])
00081 {
00082    ::strcpy(m_bfr, arg.c_str());
00083 }
00085 StringBuffer::StringBuffer(const StringBuffer& arg) :
00086    m_len(arg.m_len), m_allocated(arg.m_allocated),
00087    m_bfr(new char[arg.m_allocated])
00088 {
00089    ::memmove(m_bfr, arg.m_bfr, arg.m_len + 1);
00090 }
00092 StringBuffer&
00093 StringBuffer::operator= (const String& arg)
00094 {
00095    StringBuffer(arg).swap(*this);
00096    return *this;
00097 }
00099 StringBuffer&
00100 StringBuffer::operator= (const char* str)
00101 {
00102    StringBuffer(str).swap(*this);
00103    return *this;
00104 }
00106 StringBuffer&
00107 StringBuffer::operator =(const StringBuffer& arg)
00108 {
00109    StringBuffer(arg).swap(*this);
00110    return *this;
00111 }
00113 void
00114 StringBuffer::swap(StringBuffer& x)
00115 {
00116    std::swap(m_len, x.m_len);
00117    std::swap(m_allocated, x.m_allocated);
00118    std::swap(m_bfr, x.m_bfr);
00119 }
00121 void
00122 StringBuffer::reset()
00123 {
00124    m_len = 0;
00125    m_bfr[0] = '\0';
00126 }
00127 
00129 void
00130 StringBuffer::truncate(size_t index)
00131 {
00132    if (index < m_len)
00133    {
00134       m_bfr[index] = '\0';
00135       m_len = index;
00136    }
00137 }
00138 
00140 char
00141 StringBuffer::operator[] (size_t ndx) const
00142 {
00143    return (ndx > m_len) ? 0 : m_bfr[ndx];
00144 }
00146 // This operator must write "TRUE"/"FALSE" to support the CIMValue toXML
00147 StringBuffer&
00148 StringBuffer::operator += (Bool v)
00149 {
00150    return append(v.toString());
00151 }
00153 #if defined(BLOCXX_WIN32)
00154 #define snprintf _snprintf // stupid windoze...
00155 #endif
00156 
00157 StringBuffer&
00158 StringBuffer::operator += (UInt8 v)
00159 {
00160    char bfr[6];
00161    ::snprintf(bfr, sizeof(bfr), "%u", UInt32(v));
00162    return append(bfr);
00163 }
00165 StringBuffer&
00166 StringBuffer::operator += (Int8 v)
00167 {
00168    char bfr[6];
00169    ::snprintf(bfr, sizeof(bfr), "%d", Int32(v));
00170    return append(bfr);
00171 }
00173 StringBuffer&
00174 StringBuffer::operator += (UInt16 v)
00175 {
00176    char bfr[16];
00177    ::snprintf(bfr, sizeof(bfr), "%u", UInt32(v));
00178    return append(bfr);
00179 }
00181 StringBuffer&
00182 StringBuffer::operator += (Int16 v)
00183 {
00184    char bfr[16];
00185    ::snprintf(bfr, sizeof(bfr), "%d", Int32(v));
00186    return append(bfr);
00187 }
00189 StringBuffer&
00190 StringBuffer::operator += (UInt32 v)
00191 {
00192    char bfr[16];
00193    ::snprintf(bfr, sizeof(bfr), "%u", v);
00194    return append(bfr);
00195 }
00197 StringBuffer&
00198 StringBuffer::operator += (Int32 v)
00199 {
00200    char bfr[16];
00201    ::snprintf(bfr, sizeof(bfr), "%d", v);
00202    return append(bfr);
00203 }
00205 StringBuffer&
00206 StringBuffer::operator += (UInt64 v)
00207 {
00208    char bfr[28];
00209 #if BLOCXX_SIZEOF_LONG_INT == 8
00210    ::snprintf(bfr, sizeof(bfr), "%lu", v);
00211 #else
00212    ::snprintf(bfr, sizeof(bfr), "%llu", v);
00213 #endif
00214    return append(bfr);
00215 }
00217 StringBuffer&
00218 StringBuffer::operator += (Int64 v)
00219 {
00220    char bfr[28];
00221 #if BLOCXX_SIZEOF_LONG_INT == 8
00222    ::snprintf(bfr, sizeof(bfr), "%ld", v);
00223 #else
00224    ::snprintf(bfr, sizeof(bfr), "%lld", v);
00225 #endif
00226    return append(bfr);
00227 }
00229 // decimal digits = ceiling((bits)*ln(2)/ln(10))
00230 StringBuffer&
00231 StringBuffer::operator += (Real32 v)
00232 {
00233    char bfr[128];
00234 #if FLT_RADIX == 2
00235 #if defined(BLOCXX_REAL32_IS_FLOAT)
00236    ::snprintf(bfr, sizeof(bfr), "%.*g", FLT_MANT_DIG * 3 / 10 + 1, static_cast<double>(v));
00237 #elif defined(BLOCXX_REAL32_IS_DOUBLE)
00238    ::snprintf(bfr, sizeof(bfr), "%.*g", DBL_MANT_DIG * 3 / 10 + 1, v);
00239 #endif
00240 #else
00241 #error "The formula for computing the number of digits of precision for a floating point needs to be implmented. It's ceiling(bits * log(FLT_RADIX) / log(10))"
00242 #endif
00243    return append(bfr);
00244 }
00246 StringBuffer&
00247 StringBuffer::operator += (Real64 v)
00248 {
00249    char bfr[32];
00250 #if FLT_RADIX == 2
00251 #if defined(BLOCXX_REAL64_IS_DOUBLE)
00252    ::snprintf(bfr, sizeof(bfr), "%.*g", DBL_MANT_DIG * 3 / 10 + 1, v);
00253 #elif defined(BLOCXX_REAL64_IS_LONG_DOUBLE)
00254    ::snprintf(bfr, sizeof(bfr), "%.*Lg", LDBL_MANT_DIG * 3 / 10 + 1, v);
00255 #endif
00256 #else
00257 #error "The formula for computing the number of digits of precision for a floating point needs to be implmented. It's ceiling(bits * log(FLT_RADIX) / log(10))"
00258 #endif
00259    return append(bfr);
00260 }
00261 #if defined(BLOCXX_WIN32)
00262 #undef snprintf
00263 #endif
00264 
00265 StringBuffer&
00266 StringBuffer::append(const char* str, const size_t len)
00267 {
00268    checkAvail(len+1);
00269    ::strncpy(m_bfr+m_len, str, len);
00270    m_len += len;
00271    m_bfr[m_len] = '\0';
00272    return *this;
00273 }
00275 bool
00276 StringBuffer::equals(const char* arg) const
00277 {
00278    return ::strcmp(arg, m_bfr) == 0;
00279 }
00280 
00282 bool
00283 StringBuffer::equals(const StringBuffer& arg) const
00284 {
00285    return ::strcmp(arg.m_bfr, m_bfr) == 0;
00286 }
00287 
00289 bool
00290 StringBuffer::endsWith(char ch) const
00291 {
00292    return (m_len && m_bfr[m_len-1] == ch);
00293 }
00294 
00296 bool
00297 StringBuffer::startsWith(char ch) const
00298 {
00299    return (m_len && m_bfr[0] == ch);
00300 }
00301 
00303 void
00304 StringBuffer::chop()
00305 {
00306    if (m_len)
00307    {
00308       truncate(m_len-1);
00309    }
00310 }
00311 
00313 void
00314 StringBuffer::trim()
00315 {
00316    if (m_len)
00317    {
00318       while (m_len && isspace(m_bfr[m_len-1]))
00319       {
00320          m_bfr[--m_len] = 0;
00321       }
00322 
00323       if (m_len)
00324       {
00325          char *p = m_bfr;
00326          while (*p && isspace(*p))
00327          {
00328             ++p;
00329          }
00330 
00331          if (*p && p > m_bfr)
00332          {
00333             m_len -= (p - m_bfr);
00334             memmove(m_bfr, p, m_len+1);
00335          }
00336       }
00337    }
00338 }
00339       
00341 // Get one line from an input stream. This StringBuffer object will be
00342 // reset (cleared) before an attempt is made to retrieve the line.
00343 const char*
00344 StringBuffer::getLine(std::istream& is, bool resetBuffer)
00345 {
00346    if (resetBuffer)
00347    {
00348       reset();
00349    }
00350 
00351    if (is)
00352    {
00353       size_t count = 0;
00354       std::streambuf *sb = is.rdbuf();
00355       
00356       while (1)
00357       {
00358          int ch = sb->sbumpc();
00359          if (ch == EOF)
00360          {
00361             is.setstate(count == 0
00362                ? (std::ios::failbit | std::ios::eofbit) : std::ios::eofbit);
00363             break;
00364          }
00365          
00366          ++count;
00367          
00368          if (ch == '\n')
00369          {
00370             break;
00371          }
00372 
00373          append(static_cast<char>(ch));
00374       }
00375    }
00376 
00377    const char* p = ::strchr(m_bfr, '\r');
00378    if (p)
00379    {
00380       truncate(size_t(p-m_bfr));
00381    }
00382 
00383    return m_bfr;
00384 }
00385 
00387 std::ostream& operator<<(std::ostream& ostr, const StringBuffer& b)
00388 {
00389    ostr.write(b.c_str(), b.length());
00390    return ostr;
00391 }
00392 
00394 bool operator==(const StringBuffer& x, const StringBuffer& y)
00395 {
00396    return x.equals(y);
00397 }
00398 
00400 bool operator!=(const StringBuffer& x, const StringBuffer& y)
00401 {
00402    return !(x == y);
00403 }
00404 
00406 bool operator==(const StringBuffer& x, const String& y)
00407 {
00408    return x.equals(y.c_str());
00409 }
00410 
00412 bool operator!=(const StringBuffer& x, const String& y)
00413 {
00414    return !(x == y);
00415 }
00416 
00418 bool operator==(const String& x, const StringBuffer& y)
00419 {
00420    return x.equals(y.c_str());
00421 }
00422 
00424 bool operator!=(const String& x, const StringBuffer& y)
00425 {
00426    return !(x == y);
00427 }
00428 
00429 } // end namespace BLOCXX_NAMESPACE
00430 

Generated on Fri Jun 16 15:39:09 2006 for blocxx by  doxygen 1.4.6