Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

String.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/String.hpp"
00040 #include "blocxx/Char16.hpp"
00041 #include "blocxx/Array.hpp"
00042 #include "blocxx/StringStream.hpp"
00043 #include "blocxx/Format.hpp"
00044 #include "blocxx/BinarySerialization.hpp"
00045 #include "blocxx/Assertion.hpp"
00046 #include "blocxx/AutoPtr.hpp"
00047 #include "blocxx/Bool.hpp"
00048 #include "blocxx/UTF8Utils.hpp"
00049 #include "blocxx/ExceptionIds.hpp"
00050 #include "blocxx/COWIntrusiveCountableBase.hpp"
00051 
00052 #include <cstdio>
00053 #include <cstdlib>
00054 #include <cstring>
00055 #include <cctype>
00056 #include <cstdarg>
00057 #include <cerrno>
00058 #if defined(BLOCXX_HAVE_ISTREAM) && defined(BLOCXX_HAVE_OSTREAM)
00059 #include <istream>
00060 #include <ostream>
00061 #else
00062 #include <iostream>
00063 #endif
00064 #include <cmath> // for HUGE_VAL
00065 #include <cfloat> // for DBL_MANT_DIG
00066 
00067 #ifdef BLOCXX_WIN32
00068 #define SNPRINTF _snprintf
00069 #else
00070 #define SNPRINTF snprintf
00071 #endif
00072 
00073 namespace BLOCXX_NAMESPACE
00074 {
00075 using std::istream;
00076 using std::ostream;
00077 
00078 BLOCXX_DEFINE_EXCEPTION_WITH_ID(StringConversion);
00079 
00081 static inline int
00082 strncmpi(const char* s1, const char* s2, size_t n)
00083 {
00084    String ls1(s1, n);
00085    String ls2(s2, n);
00086    return ls1.compareToIgnoreCase(ls2);
00087 }
00088 
00089 // class invariant: m_buf points to a null-terminated sequence of characters. m_buf is m_len+1 bytes long.
00090 class String::ByteBuf : public COWIntrusiveCountableBase
00091 {
00092 public:
00093    ByteBuf(const char* s) :
00094       m_len(::strlen(s)), m_buf(new char[m_len+1])
00095    {
00096       strcpy(m_buf, s);
00097    }
00098 
00099    ByteBuf(const ByteBuf& arg)
00100       : COWIntrusiveCountableBase(arg)
00101       , m_len(arg.m_len)
00102       , m_buf(new char[m_len+1])
00103    {
00104       strcpy(m_buf, arg.m_buf);
00105    }
00106    
00107    ByteBuf(AutoPtrVec<char>& s, size_t len)
00108       : m_len(len), m_buf(s.release())
00109    {
00110    }
00111    
00112    ~ByteBuf() { delete [] m_buf; }
00113    
00114    ByteBuf& operator= (const ByteBuf& arg)
00115    {
00116       char* buf = new char[arg.m_len+1];
00117       strcpy(buf, arg.m_buf);
00118       delete [] m_buf;
00119       m_buf = buf;
00120       m_len = arg.m_len;
00121       return *this;
00122    }
00123    
00124    size_t length() const { return m_len; }
00125    char* data() const { return m_buf; }
00126    ByteBuf* clone() const { return new ByteBuf(*this); }
00127 private:
00128    size_t m_len;
00129    char* m_buf;
00130 };
00132 #if defined(BLOCXX_AIX)
00133 const size_t String::npos = ~0;
00134 #endif
00135 
00136 String::String() :
00137    m_buf(0)
00138 {
00139 }
00140 #if defined(BLOCXX_WIN32)
00141 #define snprintf _snprintf // stupid windoze...
00142 #endif
00143 
00144 String::String(Int32 val) :
00145    m_buf(NULL)
00146 {
00147    char tmpbuf[32];
00148    int len = snprintf(tmpbuf, sizeof(tmpbuf), "%d", val);
00149    AutoPtrVec<char> bfr(new char[len+1]);
00150    ::snprintf(bfr.get(), len+1, "%d", val);
00151    m_buf = new ByteBuf(bfr, len);
00152 }
00154 String::String(UInt32 val) :
00155    m_buf(NULL)
00156 {
00157    char tmpbuf[32];
00158    int len = ::snprintf(tmpbuf, sizeof(tmpbuf), "%u", val);
00159    AutoPtrVec<char> bfr(new char[len+1]);
00160    ::snprintf(bfr.get(), len+1, "%u", val);
00161    m_buf = new ByteBuf(bfr, len);
00162 }
00163 #if defined(BLOCXX_INT32_IS_INT) && defined(BLOCXX_INT64_IS_LONG_LONG)
00164 
00165 String::String(long val) :
00166    m_buf(NULL)
00167 {
00168    char tmpbuf[32];
00169    int len = snprintf(tmpbuf, sizeof(tmpbuf), "%ld", val);
00170    AutoPtrVec<char> bfr(new char[len+1]);
00171    ::snprintf(bfr.get(), len+1, "%ld", val);
00172    m_buf = new ByteBuf(bfr, len);
00173 }
00175 String::String(unsigned long val) :
00176    m_buf(NULL)
00177 {
00178    char tmpbuf[32];
00179    int len = ::snprintf(tmpbuf, sizeof(tmpbuf), "%lu", val);
00180    AutoPtrVec<char> bfr(new char[len+1]);
00181    ::snprintf(bfr.get(), len+1, "%lu", val);
00182    m_buf = new ByteBuf(bfr, len);
00183 }
00184 #endif
00185 #if defined(BLOCXX_WIN32)
00186 #undef snprintf
00187 #endif
00188 
00189 String::String(Int64 val) :
00190    m_buf(NULL)
00191 {
00192    OStringStream ss(33);
00193    ss << val;
00194    m_buf = new ByteBuf(ss.c_str());
00195 }
00197 String::String(UInt64 val) :
00198    m_buf(NULL)
00199 {
00200 #if defined(BLOCXX_INT64_IS_LONG)
00201    char tmpbuf[32];
00202    ::snprintf(tmpbuf, sizeof(tmpbuf), "%lu", val);
00203    m_buf = new ByteBuf(tmpbuf);
00204 #elif defined(BLOCXX_INT64_IS_LONG_LONG)
00205    // unfortunately not all C libraries support long long with snprintf().
00206    // but the C++ iostream library handles it.
00207    OStringStream ss;
00208    ss << val;
00209    m_buf = new ByteBuf(ss.c_str());
00210 #endif
00211 }
00213 // decimal digits = ceiling((bits)*ln(2)/ln(10))
00214 String::String(Real32 val) :
00215    m_buf(NULL)
00216 {
00217    char tmpbuf[128];
00218 #if FLT_RADIX == 2
00219 #if defined(BLOCXX_REAL32_IS_FLOAT)
00220 	::SNPRINTF(tmpbuf, sizeof(tmpbuf), "%.*g", FLT_MANT_DIG * 3 / 10 + 1, static_cast<double>(val));
00221 #elif defined(BLOCXX_REAL32_IS_DOUBLE)
00222 	::SNPRINTF(tmpbuf, sizeof(tmpbuf), "%.*g", DBL_MANT_DIG * 3 / 10 + 1, val);
00223 #endif
00224 #else
00225 #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))"
00226 #endif
00227    m_buf = new ByteBuf(tmpbuf);
00228 }
00230 String::String(Real64 val) :
00231    m_buf(NULL)
00232 {
00233    char tmpbuf[128];
00234 #if FLT_RADIX == 2
00235 #if defined(BLOCXX_REAL64_IS_DOUBLE)
00236 	::SNPRINTF(tmpbuf, sizeof(tmpbuf), "%.*g", DBL_MANT_DIG * 3 / 10 + 1, val);
00237 #elif defined(BLOCXX_REAL64_IS_LONG_DOUBLE)
00238 	::SNPRINTF(tmpbuf, sizeof(tmpbuf), "%.*Lg", LDBL_MANT_DIG * 3 / 10 + 1, val);
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    m_buf = new ByteBuf(tmpbuf);
00244 }
00246 String::String(const char* str) :
00247    m_buf(NULL)
00248 {
00249    m_buf = (NULL == str) ? 0 : new ByteBuf(str);
00250 }
00252 String::String(ETakeOwnershipFlag, char* allocatedMemory, size_t len) :
00253    m_buf(NULL)
00254 {
00255    BLOCXX_ASSERT(allocatedMemory != 0);
00256    AutoPtrVec<char> p(allocatedMemory);
00257    m_buf = new ByteBuf(p, len);
00258 }
00260 String::String(const char* str, size_t len) :
00261    m_buf(NULL)
00262 {
00263    if (NULL == str)
00264    {
00265       m_buf = 0;
00266    }
00267    else
00268    {
00269       AutoPtrVec<char> bfr(new char[len+1]);
00270       ::memcpy(bfr.get(), str, len);
00271       bfr[len] = '\0';
00272       m_buf = new ByteBuf(bfr, len);
00273    }
00274 }
00276 String::String(const String& arg) :
00277    m_buf(arg.m_buf)
00278 {
00279 }
00281 String::String(char c) :
00282    m_buf(NULL)
00283 {
00284    if (c != '\0')
00285    {
00286       char bfr[2];
00287       bfr[0] = c;
00288       bfr[1] = '\0';
00289       m_buf = new ByteBuf(bfr);
00290    }
00291    else
00292    {
00293       m_buf = 0;
00294    }
00295 }
00297 String::~String() 
00298 {
00299 }
00301 void
00302 String::swap(String& x)
00303 {
00304    m_buf.swap(x.m_buf);
00305 }
00307 char*
00308 String::allocateCString() const
00309 {
00310    size_t len = length() + 1;
00311    char* str = static_cast<char*>(malloc(len));
00312    ::strcpy(str, c_str());
00313    return str;
00314 }
00316 size_t
00317 String::length() const
00318 {
00319    return (m_buf) ? m_buf->length() : 0;
00320 }
00322 size_t
00323 String::UTF8Length() const
00324 {
00325    return UTF8Utils::charCount(c_str());
00326 }
00328 #ifdef BLOCXX_WIN32
00329 #define vsnprintf _vsnprintf // stupid windoze
00330 #endif
00331 int
00332 String::format(const char* fmt, ...)
00333 {
00334    int n, size = 64;
00335    AutoPtrVec<char> p(new char[size]);
00336    
00337    va_list ap;
00338    
00339    // Try to print in the allocated space
00340    while (true)
00341    {
00342       va_start(ap, fmt);
00343       n = vsnprintf(p.get(), size, fmt, ap);
00344       va_end(ap);                // If that worked, return the string.
00345       if (n > -1 && n < size)
00346       {
00347          m_buf = new ByteBuf(p, n);
00348          return static_cast<int>(length());
00349       }
00350       if (n > -1)    // glibc 2.1
00351          size = n+1; // precisely what is needed
00352       else           // glibc 2.0
00353          size *= 2;  // twice the old size
00354       p = new char[size];
00355    }
00356 }
00357 #ifdef BLOCXX_WIN32
00358 #undef vsnprintf // stupid windoze
00359 #endif
00360 
00361 char
00362 String::charAt(size_t ndx) const
00363 {
00364    return (m_buf) ? m_buf->data()[ndx] : '\0';
00365 }
00367 int
00368 String::compareTo(const char* arg) const
00369 {
00370    const char* lhs = "";
00371    if (m_buf)
00372    {
00373       lhs = m_buf->data();
00374    }
00375    return ::strcmp(lhs, arg);
00376 }
00378 int
00379 String::compareTo(const String& arg) const
00380 {
00381    return compareTo(arg.c_str());
00382 }
00384 int
00385 String::compareToIgnoreCase(const char* arg) const
00386 {
00387    const char* lhs = "";
00388    if (m_buf)
00389    {
00390       lhs = m_buf->data();
00391    }
00392    return UTF8Utils::compareToIgnoreCase(lhs, arg);
00393 }
00395 int
00396 String::compareToIgnoreCase(const String& arg) const
00397 {
00398    return compareToIgnoreCase(arg.c_str());
00399 }
00400 
00402 String&
00403 String::concat(const char* arg)
00404 {
00405    if (arg && *arg)
00406    {
00407       size_t len = length() + ::strlen(arg);
00408       AutoPtrVec<char> bfr(new char[len+1]);
00409       bfr[0] = 0;
00410       if (m_buf)
00411       {
00412          ::strcpy(bfr.get(), m_buf->data());
00413       }
00414       ::strcat(bfr.get(), arg);
00415       m_buf = new ByteBuf(bfr, len);
00416    }
00417    return *this;
00418 }
00419 
00421 String&
00422 String::concat(char arg)
00423 {
00424    size_t newlen = length() + 1;
00425    AutoPtrVec<char> bfr(new char[newlen+1]);
00426    bfr[0] = 0;
00427    if (m_buf)
00428    {
00429       ::strcpy(bfr.get(), m_buf->data());
00430    }
00431    *(bfr.get()+length()) = arg;
00432    *(bfr.get()+newlen) = 0;
00433    m_buf = new ByteBuf(bfr, newlen);
00434    return *this;
00435 }
00436 
00438 bool
00439 String::endsWith(char arg) const
00440 {
00441    return (m_buf
00442          && m_buf->length()
00443          && m_buf->data()[m_buf->length()-1] == arg);
00444 }
00445 
00447 bool
00448 String::endsWith(const char* arg, EIgnoreCaseFlag ignoreCase) const
00449 {
00450    if (!arg || !*arg)
00451    {
00452       return (length() == 0);
00453    }
00454 
00455    if (!m_buf)
00456    {
00457       return false;
00458    }
00459 
00460    int ndx = static_cast<int>(length() - ::strlen(arg));
00461    if (ndx < 0)
00462    {
00463       return false;
00464    }
00465 
00466    return (ignoreCase)
00467       ? (UTF8Utils::compareToIgnoreCase(m_buf->data()+ndx, arg) == 0)
00468       : (::strcmp(m_buf->data()+ndx, arg) == 0);
00469 }
00471 bool
00472 String::equals(const char* arg) const
00473 {
00474    return(compareTo(arg) == 0);
00475 }
00477 bool
00478 String::equals(const String& arg) const
00479 {
00480    return equals(arg.c_str());
00481 }
00483 bool
00484 String::equalsIgnoreCase(const char* arg) const
00485 {
00486    return(compareToIgnoreCase(arg) == 0);
00487 }
00489 bool
00490 String::equalsIgnoreCase(const String& arg) const
00491 {
00492    return equalsIgnoreCase(arg.c_str());
00493 }
00495 UInt32
00496 String::hashCode() const
00497 {
00498    UInt32 hash = 0;
00499    size_t len = length();
00500    for (size_t i = 0; i < len; i++)
00501    {
00502       // Don't need to check if m_buf is null, because if it is, len == 0,
00503       // and this loop won't be executed.
00504       const char temp = m_buf->data()[i];
00505       hash = (hash << 4) + (temp * 13);
00506       UInt32 g = hash & 0xf0000000;
00507       if (g)
00508       {
00509          hash ^= (g >> 24);
00510          hash ^= g;
00511       }
00512    }
00513    return hash;
00514 }
00516 size_t
00517 String::indexOf(char ch, size_t fromIndex) const
00518 {
00519    //if (fromIndex < 0)
00520    //{
00521    // fromIndex = 0;
00522    //}
00523    size_t cc = npos;
00524    if (fromIndex < length())
00525    {
00526       // Don't need to check m_buf for NULL, because if length() == 0,
00527       // this code won't be executed.
00528       const char* p = String::strchr(m_buf->data()+fromIndex, ch);
00529       if (p)
00530       {
00531          cc = p - m_buf->data();
00532       }
00533    }
00534    return cc;
00535 }
00537 size_t
00538 String::indexOf(const char* arg, size_t fromIndex) const
00539 {
00540    int cc = npos;
00541    if (fromIndex < length())
00542    {
00543       // Don't need to check m_buf for NULL, because if length() == 0,
00544       // this code won't be executed, but we do need to check arg.m_buf
00545       char* p(0);
00546       if (arg && *arg)
00547       {
00548          p = ::strstr(m_buf->data()+fromIndex, arg);
00549       }
00550       else
00551       {
00552          p = m_buf->data()+fromIndex;
00553       }
00554 
00555       if (p != NULL)
00556       {
00557          cc = static_cast<int>(p - m_buf->data());
00558       }
00559    }
00560    return cc;
00561 }
00563 size_t
00564 String::lastIndexOf(char ch, size_t fromIndex) const
00565 {
00566    if (fromIndex == npos)
00567    {
00568       if ((fromIndex = length()-1) == npos)
00569       {
00570          return npos;
00571       }
00572    }
00573    size_t cc = npos;
00574    if (fromIndex < length())
00575    {
00576       for (size_t i = fromIndex; i != npos; i--)
00577       {
00578          // Don't need to check m_buf for NULL, because if length() == 0,
00579          // this code won't be executed.
00580          if (m_buf->data()[i] == ch)
00581          {
00582             cc = i;
00583             break;
00584          }
00585       }
00586    }
00587    return cc;
00588 }
00590 size_t
00591 String::lastIndexOf(const char* arg, size_t fromIndex) const
00592 {
00593    if (fromIndex == npos || fromIndex >= length())
00594    {
00595       if (static_cast<int>(fromIndex = length()-1) < 0)
00596       {
00597          return npos;
00598       }
00599    }
00600 
00601    int arglen = (arg) ? ::strlen(arg) : 0;
00602    if (static_cast<int>(fromIndex -= arglen - 1) < 0)
00603    {
00604       return npos;
00605    }
00606    if (!arg)
00607    {
00608       return length() - 1;
00609    }
00610    while (fromIndex != npos)
00611    {
00612       // Don't need to check m_buf for NULL, because if length() == 0,
00613       // this code won't be executed.
00614       if (::strncmp(m_buf->data()+fromIndex, arg, arglen) == 0)
00615       {
00616          break;
00617       }
00618       fromIndex--;
00619    }
00620    return fromIndex;
00621 }
00623 bool
00624 String::startsWith(char arg) const
00625 {
00626    return (m_buf
00627          && m_buf->length()
00628          && m_buf->data()[0] == arg);
00629 }
00630 
00632 bool
00633 String::startsWith(const char* arg, EIgnoreCaseFlag ignoreCase) const
00634 {
00635    bool cc = false;
00636    if (!arg && !m_buf)
00637    {
00638       return true;
00639    }
00640    if (!*arg)
00641    {
00642       return (length() == 0);
00643    }
00644 
00645    size_t arglen = ::strlen(arg);
00646    if (arglen <= length())
00647    {
00648       // Don't need to check m_buf for NULL, because if length() == 0,
00649       // this code won't be executed.
00650       if (ignoreCase)
00651       {
00652          cc = (strncmpi(m_buf->data(), arg, arglen) == 0);
00653       }
00654       else
00655       {
00656          cc = (::strncmp(m_buf->data(), arg, arglen) == 0);
00657       }
00658    }
00659    return cc;
00660 }
00662 String
00663 String::substring(size_t beginIndex, size_t len) const
00664 {
00665    String nil;
00666    size_t count = len;
00667    size_t l = length();
00668    if (0 == l)
00669    {
00670       return nil;
00671    }
00672    if (beginIndex >= l)
00673    {
00674       return nil;
00675    }
00676    else if (0 == len)
00677    {
00678       return nil;
00679    }
00680    else if (len == npos)
00681    {
00682       count = l - beginIndex;
00683    }
00684    if (count + beginIndex > l)
00685    {
00686       count = l - beginIndex;
00687    }
00688    // Don't need to check m_buf for NULL, because if length() == 0,
00689    // this code won't be executed.
00690    return String(static_cast<const char*>(m_buf->data()+beginIndex), count);
00691 }
00693 bool
00694 String::isSpaces() const
00695 {
00696    if (!m_buf)
00697    {
00698       return true;
00699    }
00700    char* p = m_buf->data();
00701    while (isspace(*p) && *p != '\0')
00702    {
00703       p++;
00704    }
00705    return (*p == '\0');
00706 }
00708 String&
00709 String::ltrim()
00710 {
00711    if (!m_buf)
00712    {
00713       return *this;
00714    }
00715    char* s1 = m_buf->data();
00716    while (isspace(*s1) && *s1 != '\0')
00717    {
00718       s1++;
00719    }
00720    if (s1 == m_buf->data())
00721    {
00722       return *this;
00723    }
00724    *this = String(s1);
00725    return *this;
00726 }
00728 String&
00729 String::rtrim()
00730 {
00731    if (length() == 0)
00732    {
00733       return *this;
00734    }
00735    char* s1 = m_buf->data() + (length()-1);
00736    while (isspace(*s1) && s1 >= m_buf->data())
00737    {
00738       s1--;
00739    }
00740    if (s1 == (m_buf->data() + (length()-1)))
00741    {
00742       return *this;
00743    }
00744    if (s1 < m_buf->data())
00745    {
00746       *this = String();
00747       return *this;
00748    }
00749    size_t len = (s1 - m_buf->data()) + 1;
00750    *this = String(m_buf->data(), len);
00751    return *this;
00752 }
00754 String&
00755 String::trim()
00756 {
00757    if (length() == 0)
00758    {
00759       return *this;
00760    }
00761    char* s1 = m_buf->data();
00762    while (isspace(*s1) && *s1 != '\0')
00763    {
00764       s1++;
00765    }
00766    if (*s1 == '\0')
00767    {
00768       // String is all spaces
00769       *this = String();
00770       return *this;
00771    }
00772    const char* p2 = String::strchr(s1, '\0');
00773    const char* s2 = p2 - 1;
00774    while (isspace(*s2))
00775    {
00776       s2--;
00777    }
00778    if (s1 == m_buf->data() && s2 == p2)
00779    {
00780       // String has no leading or trailing spaces
00781       return *this;
00782    }
00783    size_t len = (s2 - s1) + 1;
00784    *this = String(s1, len);
00785    return *this;
00786 }
00788 String&
00789 String::erase()
00790 {
00791    m_buf = 0;
00792    return *this;
00793 }
00795 String&
00796 String::erase(size_t idx, size_t len)
00797 {
00798    if ( idx >= length() )
00799    {
00800       return *this;
00801    }
00802    if (len == npos)
00803    {
00804       *this = substring(0, idx);
00805    }
00806    else
00807    {
00808       *this = substring(0, idx) + substring(idx + len);
00809    }
00810    return *this;
00811 }
00813 String&
00814 String::toLowerCase()
00815 {
00816    if (m_buf)
00817    {
00818       if (!UTF8Utils::toLowerCaseInPlace(m_buf->data()))
00819       {
00820          *this = UTF8Utils::toLowerCase(m_buf->data());
00821       }
00822    }
00823    return *this;
00824 }
00825 
00827 String&
00828 String::toUpperCase()
00829 {
00830    if (m_buf)
00831    {
00832       if (!UTF8Utils::toUpperCaseInPlace(m_buf->data()))
00833       {
00834          *this = UTF8Utils::toUpperCase(m_buf->data());
00835       }
00836    }
00837    return *this;
00838 }
00840 void
00841 String::readObject(istream& istrm)
00842 {
00843    UInt32 len;
00844    BinarySerialization::readLen(istrm, len);
00845    AutoPtrVec<char> bfr(new char[len+1]);
00846    BinarySerialization::read(istrm, bfr.get(), len);
00847    bfr[len] = '\0';
00848    m_buf = new ByteBuf(bfr, len);
00849 }
00851 void
00852 String::writeObject(ostream& ostrm) const
00853 {
00854    UInt32 len = static_cast<UInt32>(length());
00855    BinarySerialization::writeLen(ostrm, len);
00856    if (len)
00857    {
00858       BinarySerialization::write(ostrm, m_buf->data(), len);
00859    }
00860 }
00862 String&
00863 String::operator= (const String& arg)
00864 {
00865    m_buf = arg.m_buf;
00866    return *this;
00867 }
00869 const char*
00870 String::c_str() const
00871 {
00872    if (m_buf)
00873    {
00874       return m_buf->data();
00875    }
00876    else
00877    {
00878       return "";
00879    }
00880 }
00882 static const char cnullChar = '\0';
00883 const char&
00884 String::operator[] (size_t ndx) const
00885 {
00886 #ifdef BLOCXX_DEBUG
00887    BLOCXX_ASSERT(ndx <= length());
00888 #endif
00889    // Don't need to check m_buf for NULL, because if length() == 0,
00890    // m_buf->data() won't be executed.
00891    //return (ndx <= length()) ? *(m_buf->data() + ndx) : cnullChar;
00892    if (ndx <= length())
00893    {
00894       return *(m_buf->data() + ndx);
00895    }
00896    else
00897    {
00898       return cnullChar;
00899    }
00900 }
00902 static char nullChar = '\0';
00903 char&
00904 String::operator[] (size_t ndx)
00905 {
00906 #ifdef BLOCXX_DEBUG
00907    BLOCXX_ASSERT(ndx <= length());
00908 #endif
00909    // Don't need to check m_buf for NULL, because if length() == 0,
00910    // m_buf->data() won't be executed.
00911    return (ndx <= length()) ? m_buf->data()[ndx] : nullChar;
00912 }
00914 String
00915 String::toString() const
00916 {
00917    return *this;
00918 }
00920 static inline void
00921 throwStringConversion(const String::buf_t& m_buf, const char* type)
00922 {
00923    BLOCXX_THROW(StringConversionException, Format("Unable to convert \"%1\" into %2", m_buf->data(), type).c_str());
00924 }
00926 static inline void
00927 throwStringConversion(const char* str, const char* type)
00928 {
00929    BLOCXX_THROW(StringConversionException, Format("Unable to convert \"%1\" into %2", str, type).c_str());
00930 }
00932 template <typename T, typename FP>
00933 static inline
00934 T convertToRealType(const String::buf_t& m_buf, const char* type, FP fp)
00935 {
00936    if (m_buf)
00937    {
00938       char* endptr(0);
00939       errno = 0;     // errno is thread local
00940       T rv = fp(m_buf->data(), &endptr);
00941       if (*endptr != '\0' || errno == ERANGE || rv == HUGE_VAL || rv == -HUGE_VAL)
00942       {
00943          throwStringConversion(m_buf, type);
00944       }
00945       return rv;
00946    }
00947    else
00948    {
00949       throwStringConversion("", type);
00950    }
00951    return T(); // to make compiler happy
00952 }
00954 Real32
00955 String::toReal32() const
00956 {
00957 #if defined(BLOCXX_REAL32_IS_FLOAT) && defined(BLOCXX_HAVE_STRTOF)
00958    return convertToRealType<Real32>(m_buf, "Real32", &strtof);
00959 #elif defined(BLOCXX_REAL32_IS_DOUBLE) || (defined(BLOCXX_REAL32_IS_FLOAT) && !defined(BLOCXX_HAVE_STRTOF))
00960    return convertToRealType<Real32>(m_buf, "Real32", &strtod);
00961 #endif
00962 }
00964 Real64
00965 String::toReal64() const
00966 {
00967 #if defined(BLOCXX_REAL64_IS_DOUBLE)
00968    return convertToRealType<Real64>(m_buf, "Real64", &strtod);
00969 #elif defined(BLOCXX_REAL64_IS_LONG_DOUBLE)
00970    return convertToRealType<Real64>(m_buf, "Real64", &strtold);
00971 #endif
00972 }
00974 bool
00975 String::toBool() const
00976 {
00977    if (equalsIgnoreCase("true"))
00978    {
00979       return true;
00980    }
00981    else if (equalsIgnoreCase("false"))
00982    {
00983       return false;
00984    }
00985    else
00986    {
00987       throwStringConversion(c_str(), "bool");
00988    }
00989    return false; // to make compiler happy
00990 }
00991 template <typename T, typename FP, typename FPRT>
00992 static inline
00993 T doConvertToIntType(const String::buf_t& m_buf, const char* type, FP fp, int base)
00994 {
00995    if (m_buf)
00996    {
00997       char* endptr(0);
00998       errno = 0;     // errno is thread local
00999       FPRT v = fp(m_buf->data(), &endptr, base);
01000       T rv = static_cast<T>(v);
01001       if (*endptr != '\0' || errno == ERANGE || FPRT(rv) != v)
01002       {
01003          throwStringConversion(m_buf, type);
01004       }
01005       return rv;
01006    }
01007    else
01008    {
01009       throwStringConversion("", type);
01010    }
01011    return T(); // to make compiler happy
01012 }
01013 typedef unsigned long int (*strtoulfp_t)(const char *, char **,int);
01014 typedef long int (*strtolfp_t)(const char *, char **,int);
01015 typedef unsigned long long int (*strtoullfp_t)(const char *, char **,int);
01016 typedef long long int (*strtollfp_t)(const char *, char **,int);
01017 template <typename T>
01018 static inline
01019 T convertToUIntType(const String::buf_t& m_buf, const char* msg, int base)
01020 {
01021    return doConvertToIntType<T, strtoulfp_t, unsigned long int>(m_buf, msg, &strtoul, base);
01022 }
01023 template <typename T>
01024 static inline
01025 T convertToIntType(const String::buf_t& m_buf, const char* msg, int base)
01026 {
01027    return doConvertToIntType<T, strtolfp_t, long int>(m_buf, msg, &strtol, base);
01028 }
01029 template <typename T>
01030 static inline
01031 T convertToUInt64Type(const String::buf_t& m_buf, const char* msg, int base)
01032 {
01033    return doConvertToIntType<T, strtoullfp_t, unsigned long long int>(m_buf, msg, &String::strtoull, base);
01034 }
01035 template <typename T>
01036 static inline
01037 T convertToInt64Type(const String::buf_t& m_buf, const char* msg, int base)
01038 {
01039    return doConvertToIntType<T, strtollfp_t, long long int>(m_buf, msg, &String::strtoll, base);
01040 }
01042 UInt8
01043 String::toUInt8(int base) const
01044 {
01045    return convertToUIntType<UInt8>(m_buf, "UInt8", base);
01046 }
01048 Int8
01049 String::toInt8(int base) const
01050 {
01051    return convertToIntType<Int8>(m_buf, "Int8", base);
01052 }
01054 UInt16
01055 String::toUInt16(int base) const
01056 {
01057    return convertToUIntType<UInt16>(m_buf, "UInt16", base);
01058 }
01060 Int16
01061 String::toInt16(int base) const
01062 {
01063    return convertToIntType<Int16>(m_buf, "Int16", base);
01064 }
01066 UInt32
01067 String::toUInt32(int base) const
01068 {
01069    return convertToUIntType<UInt32>(m_buf, "UInt32", base);
01070 }
01072 Int32
01073 String::toInt32(int base) const
01074 {
01075    return convertToIntType<Int32>(m_buf, "Int32", base);
01076 }
01078 UInt64
01079 String::toUInt64(int base) const
01080 {
01081    return convertToUInt64Type<UInt64>(m_buf, "UInt64", base);
01082 }
01084 Int64
01085 String::toInt64(int base) const
01086 {
01087    return convertToInt64Type<Int64>(m_buf, "Int64", base);
01088 }
01090 unsigned int
01091 String::toUnsignedInt(int base) const
01092 {
01093    return convertToUIntType<unsigned int>(m_buf, "unsigned int", base);
01094 }
01096 int
01097 String::toInt(int base) const
01098 {
01099    return convertToIntType<int>(m_buf, "int", base);
01100 }
01102 StringArray
01103 String::tokenize(const char* delims, EReturnDelimitersFlag returnDelimitersAsTokens, EEmptyTokenReturnFlag returnEmptyTokens) const
01104 {
01105    StringArray ra;
01106    if (empty())
01107    {
01108       return ra;
01109    }
01110    if (delims == 0)
01111    {
01112       ra.append(*this);
01113       return ra;
01114    }
01115    // Don't need to check m_buf for NULL, because if length() == 0,
01116    // this code won't be executed.
01117    char* pstr = m_buf->data();
01118    AutoPtrVec<char> data(new char[m_buf->length()+1]);
01119    data[0] = 0;
01120    int i = 0;
01121    bool last_was_delim = false;
01122    while (*pstr)
01123    {
01124       if (String::strchr(delims, *pstr))
01125       {
01126          if (data[0] != 0)
01127          {
01128             ra.append(String(data.get()));
01129             data[0] = 0;
01130          }
01131          if ( (returnEmptyTokens == E_RETURN_EMPTY_TOKENS) && last_was_delim )
01132          {
01133             ra.append(String());
01134          }
01135          if ( returnDelimitersAsTokens == E_RETURN_DELIMITERS )
01136          {
01137             ra.append(String(*pstr));
01138          }        
01139          i = 0;
01140          last_was_delim = true;
01141       }
01142       else
01143       {
01144          last_was_delim = false;
01145          data[i++] = *pstr;
01146          data[i] = 0;
01147       }
01148       pstr++;
01149    }
01150    if (data[0] != 0)
01151    {
01152       ra.append(String(data.get()));
01153    }
01154    return ra;
01155 }
01156 
01158 #ifdef BLOCXX_HAVE_STRTOLL
01159 long long int
01160 String::strtoll(const char* nptr, char** endptr, int base)
01161 {
01162    return ::strtoll(nptr, endptr, base);
01163 }
01164 #else
01165 #ifndef LLONG_MAX
01166 #if BLOCXX_SIZEOF_LONG_LONG_INT == 8
01167 #define LLONG_MAX 9223372036854775807LL
01168 #else
01169 #define LLONG_MAX 2147483647LL
01170 #endif
01171 #define LLONG_MIN (-LLONG_MAX - 1LL)
01172 #endif
01173 long long int
01174 String::strtoll(const char* nptr, char** endptr, int base)
01175 {
01176    const char *s;
01177    long long acc, cutoff;
01178    int c;
01179    int neg, any, cutlim;
01180    // Skip white space and pick up leading +/- sign if any.
01181    // If base is 0, allow 0x for hex and 0 for octal, else
01182    // assume decimal; if base is already 16, allow 0x.
01183    s = nptr;
01184    do
01185    {
01186       c = (unsigned char) *s++;
01187    } while (isspace(c));
01188    if (c == '-')
01189    {
01190       neg = 1;
01191       c = *s++;
01192    }
01193    else
01194    {
01195       neg = 0;
01196       if (c == '+')
01197       {
01198          c = *s++;
01199       }
01200    }
01201    if ((base == 0 || base == 16)
01202       && c == '0'
01203       && (*s == 'x' || *s == 'X'))
01204    {
01205       c = s[1];
01206       s += 2;
01207       base = 16;
01208    }
01209    if (base == 0)
01210    {
01211       base = c == '0' ? 8 : 10;
01212    }
01213    // Compute the cutoff value between legal numbers and illegal
01214    // numbers.  That is the largest legal value, divided by the
01215    // base.  An input number that is greater than this value, if
01216    // followed by a legal input character, is too big.  One that
01217    // is equal to this value may be valid or not; the limit
01218    // between valid and invalid numbers is then based on the last
01219    // digit.  For instance, if the range for longs is
01220    // [-2147483648..2147483647] and the input base is 10,
01221    // cutoff will be set to 214748364 and cutlim to either
01222    // 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
01223    // a value > 214748364, or equal but the next digit is > 7 (or 8),
01224    // the number is too big, and we will return a range error.
01225    //
01226    // Set any if any `digits' consumed; make it negative to indicate
01227    // overflow.
01228    cutoff = neg ? LLONG_MIN : LLONG_MAX;
01229    cutlim = static_cast<int>(cutoff % base);
01230    cutoff /= base;
01231    if (neg)
01232    {
01233       if (cutlim > 0)
01234       {
01235          cutlim -= base;
01236          cutoff += 1;
01237       }
01238       cutlim = -cutlim;
01239    }
01240    for (acc = 0, any = 0;; c = (unsigned char) *s++)
01241    {
01242       if (isdigit(c))
01243       {
01244          c -= '0';
01245       }
01246       else if (isalpha(c))
01247       {
01248          c -= isupper(c) ? 'A' - 10 : 'a' - 10;
01249       }
01250       else
01251       {
01252          break;
01253       }
01254       if (c >= base)
01255       {
01256          break;
01257       }
01258       if (any < 0)
01259       {
01260          continue;
01261       }
01262       if (neg)
01263       {
01264          if (acc < cutoff || acc == cutoff && c > cutlim)
01265          {
01266             any = -1;
01267             acc = LLONG_MIN;
01268             errno = ERANGE;
01269          }
01270          else
01271          {
01272             any = 1;
01273             acc *= base;
01274             acc -= c;
01275          }
01276       }
01277       else
01278       {
01279          if (acc > cutoff || acc == cutoff && c > cutlim)
01280          {
01281             any = -1;
01282             acc = LLONG_MAX;
01283             errno = ERANGE;
01284          }
01285          else
01286          {
01287             any = 1;
01288             acc *= base;
01289             acc += c;
01290          }
01291       }
01292    }
01293    if (endptr != 0)
01294    {
01295       *endptr = (char *) (any ? s - 1 : nptr);
01296    }
01297    return(acc);
01298 }
01299 #endif   // #ifdef BLOCXX_HAVE_STRTOLL
01300 
01302 #ifdef BLOCXX_HAVE_STRTOULL
01303 unsigned long long int
01304 String::strtoull(const char* nptr, char** endptr, int base)
01305 {
01306    return ::strtoull(nptr, endptr, base);
01307 }
01308 #else
01309 #ifndef ULLONG_MAX
01310 #if BLOCXX_SIZEOF_LONG_LONG_INT == 8
01311 #define ULLONG_MAX 18446744073709551615ULL
01312 #else
01313 #define ULLONG_MAX 4294967295ULL
01314 #endif
01315 #endif
01316 unsigned long long int
01317 String::strtoull(const char* nptr, char** endptr, int base)
01318 {
01319    const char *s;
01320    unsigned long long acc, cutoff, cutlim;
01321    unsigned int c;
01322    int neg, any;
01323    s = nptr;
01324    do
01325    {
01326       c = (unsigned char) *s++;
01327    } while (isspace(c));
01328    if (c == '-')
01329    {
01330       neg = 1;
01331       c = *s++;
01332    }
01333    else
01334    {
01335       neg = 0;
01336       if (c == '+')
01337       {
01338          c = *s++;
01339       }
01340    }
01341    if ((base == 0 || base == 16)
01342       && c == '0'
01343       && (*s == 'x' || *s == 'X'))
01344    {
01345       c = s[1];
01346       s += 2;
01347       base = 16;
01348    }
01349    if (base == 0)
01350    {
01351       base = c == '0' ? 8 : 10;
01352    }
01353    cutoff = ULLONG_MAX / (unsigned long long)base;
01354    cutlim = ULLONG_MAX % (unsigned long long)base;
01355    for (acc = 0, any = 0;; c = (unsigned char) *s++)
01356    {
01357       if (isdigit(c))
01358       {
01359          c -= '0';
01360       }
01361       else if (isalpha(c))
01362       {
01363          c -= isupper(c) ? 'A' - 10 : 'a' - 10;
01364       }
01365       else
01366       {
01367          break;
01368       }
01369       if (c >= (unsigned int)base)
01370       {
01371          break;
01372       }
01373       if (any < 0)
01374       {
01375          continue;
01376       }
01377       if (acc > cutoff || acc == cutoff && c > cutlim)
01378       {
01379          any = -1;
01380          acc = ULLONG_MAX;
01381          errno = ERANGE;
01382       }
01383       else
01384       {
01385          any = 1;
01386          acc *= (unsigned long)base;
01387          acc += c;
01388       }
01389    }
01390    if (neg && any > 0)
01391    {
01392 #ifdef BLOCXX_WIN32
01393 #pragma warning (push)
01394 #pragma warning (disable: 4146)
01395 #endif
01396 
01397       acc = -acc;
01398 
01399 #ifdef BLOCXX_WIN32
01400 #pragma warning (pop)
01401 #endif
01402 
01403    }
01404    if (endptr != 0)
01405    {
01406       *endptr = (char *) (any ? s - 1 : nptr);
01407    }
01408    return(acc);
01409 }
01410 #endif   // #ifdef BLOCXX_HAVE_STRTOULL
01411 
01412 String
01413 operator + (const String& s1, const String& s2)
01414 {
01415    String rstr(s1);
01416    rstr += s2;
01417    return rstr;
01418 }
01420 String
01421 operator + (const char* p, const String& s)
01422 {
01423    String rstr(p);
01424    rstr += s;
01425    return rstr;
01426 }
01428 String
01429 operator + (const String& s, const char* p)
01430 {
01431    String rstr(s);
01432    rstr += p;
01433    return rstr;
01434 }
01436 String
01437 operator + (char c, const String& s)
01438 {
01439    String rstr(c);
01440    rstr += s;
01441    return rstr;
01442 }
01444 String
01445 operator + (const String& s, char c)
01446 {
01447    String rstr(s);
01448    rstr += String(c);
01449    return rstr;
01450 }
01452 ostream&
01453 operator<< (ostream& ostr, const String& arg)
01454 {
01455    ostr.write(arg.c_str(), arg.length());
01456    return ostr;
01457 }
01459 // static
01460 String
01461 String::getLine(istream& is)
01462 {
01463    StringBuffer rv(80);
01464    rv.getLine(is);
01465    return rv.releaseString();
01466 }
01468 // STATIC
01469 const char*
01470 String::strchr(const char* theStr, int c)
01471 {
01472    const char* tmpChar = theStr;
01473    for (; *tmpChar && *tmpChar != c; tmpChar++)
01474    {
01475       // empty
01476    }
01477    return ((*tmpChar) == c ? tmpChar : 0);
01478 }
01479 
01480 } // end namespace BLOCXX_NAMESPACE
01481 

Generated on Mon Sep 12 23:56:36 2005 for blocxx by  doxygen 1.4.4