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(const std::string &str) :
00253    m_buf(NULL)
00254 {
00255    m_buf = str.empty() ? 0 : new ByteBuf(str.c_str());
00256 }
00258 String::String(ETakeOwnershipFlag, char* allocatedMemory, size_t len) :
00259    m_buf(NULL)
00260 {
00261    BLOCXX_ASSERT(allocatedMemory != 0);
00262    AutoPtrVec<char> p(allocatedMemory);
00263    m_buf = new ByteBuf(p, len);
00264 }
00266 String::String(const char* str, size_t len) :
00267    m_buf(NULL)
00268 {
00269    if (NULL == str)
00270    {
00271       m_buf = 0;
00272    }
00273    else
00274    {
00275       AutoPtrVec<char> bfr(new char[len+1]);
00276       ::memcpy(bfr.get(), str, len);
00277       bfr[len] = '\0';
00278       m_buf = new ByteBuf(bfr, len);
00279    }
00280 }
00282 String::String(const String& arg) :
00283    m_buf(arg.m_buf)
00284 {
00285 }
00287 String::String(char c) :
00288    m_buf(NULL)
00289 {
00290    if (c != '\0')
00291    {
00292       char bfr[2];
00293       bfr[0] = c;
00294       bfr[1] = '\0';
00295       m_buf = new ByteBuf(bfr);
00296    }
00297    else
00298    {
00299       m_buf = 0;
00300    }
00301 }
00303 String::~String() 
00304 {
00305 }
00307 void
00308 String::swap(String& x)
00309 {
00310    m_buf.swap(x.m_buf);
00311 }
00313 char*
00314 String::allocateCString() const
00315 {
00316    size_t len = length() + 1;
00317    char* str = static_cast<char*>(malloc(len));
00318    ::strcpy(str, c_str());
00319    return str;
00320 }
00322 size_t
00323 String::length() const
00324 {
00325    return (m_buf) ? m_buf->length() : 0;
00326 }
00328 size_t
00329 String::UTF8Length() const
00330 {
00331    return UTF8Utils::charCount(c_str());
00332 }
00334 #ifdef BLOCXX_WIN32
00335 #define vsnprintf _vsnprintf // stupid windoze
00336 #endif
00337 int
00338 String::format(const char* fmt, ...)
00339 {
00340    int n, size = 64;
00341    AutoPtrVec<char> p(new char[size]);
00342    
00343    va_list ap;
00344    
00345    // Try to print in the allocated space
00346    while (true)
00347    {
00348       va_start(ap, fmt);
00349       n = vsnprintf(p.get(), size, fmt, ap);
00350       va_end(ap);                // If that worked, return the string.
00351       if (n > -1 && n < size)
00352       {
00353          m_buf = new ByteBuf(p, n);
00354          return static_cast<int>(length());
00355       }
00356       if (n > -1)    // glibc 2.1
00357          size = n+1; // precisely what is needed
00358       else           // glibc 2.0
00359          size *= 2;  // twice the old size
00360       p = new char[size];
00361    }
00362 }
00363 #ifdef BLOCXX_WIN32
00364 #undef vsnprintf // stupid windoze
00365 #endif
00366 
00367 char
00368 String::charAt(size_t ndx) const
00369 {
00370    return (m_buf) ? m_buf->data()[ndx] : '\0';
00371 }
00373 int
00374 String::compareTo(const char* arg) const
00375 {
00376    const char* lhs = "";
00377    if (m_buf)
00378    {
00379       lhs = m_buf->data();
00380    }
00381    return ::strcmp(lhs, arg);
00382 }
00384 int
00385 String::compareTo(const String& arg) const
00386 {
00387    return compareTo(arg.c_str());
00388 }
00390 int
00391 String::compareToIgnoreCase(const char* arg) const
00392 {
00393    const char* lhs = "";
00394    if (m_buf)
00395    {
00396       lhs = m_buf->data();
00397    }
00398    return UTF8Utils::compareToIgnoreCase(lhs, arg);
00399 }
00401 int
00402 String::compareToIgnoreCase(const String& arg) const
00403 {
00404    return compareToIgnoreCase(arg.c_str());
00405 }
00406 
00408 String&
00409 String::concat(const char* arg)
00410 {
00411    if (arg && *arg)
00412    {
00413       size_t len = length() + ::strlen(arg);
00414       AutoPtrVec<char> bfr(new char[len+1]);
00415       bfr[0] = 0;
00416       if (m_buf)
00417       {
00418          ::strcpy(bfr.get(), m_buf->data());
00419       }
00420       ::strcat(bfr.get(), arg);
00421       m_buf = new ByteBuf(bfr, len);
00422    }
00423    return *this;
00424 }
00425 
00427 String&
00428 String::concat(char arg)
00429 {
00430    size_t newlen = length() + 1;
00431    AutoPtrVec<char> bfr(new char[newlen+1]);
00432    bfr[0] = 0;
00433    if (m_buf)
00434    {
00435       ::strcpy(bfr.get(), m_buf->data());
00436    }
00437    *(bfr.get()+length()) = arg;
00438    *(bfr.get()+newlen) = 0;
00439    m_buf = new ByteBuf(bfr, newlen);
00440    return *this;
00441 }
00442 
00444 bool
00445 String::endsWith(char arg) const
00446 {
00447    return (m_buf
00448          && m_buf->length()
00449          && m_buf->data()[m_buf->length()-1] == arg);
00450 }
00451 
00453 bool
00454 String::endsWith(const char* arg, EIgnoreCaseFlag ignoreCase) const
00455 {
00456    if (!arg || !*arg)
00457    {
00458       return (length() == 0);
00459    }
00460 
00461    if (!m_buf)
00462    {
00463       return false;
00464    }
00465 
00466    int ndx = static_cast<int>(length() - ::strlen(arg));
00467    if (ndx < 0)
00468    {
00469       return false;
00470    }
00471 
00472    return (ignoreCase)
00473       ? (UTF8Utils::compareToIgnoreCase(m_buf->data()+ndx, arg) == 0)
00474       : (::strcmp(m_buf->data()+ndx, arg) == 0);
00475 }
00477 bool
00478 String::equals(const char* arg) const
00479 {
00480    return(compareTo(arg) == 0);
00481 }
00483 bool
00484 String::equals(const String& arg) const
00485 {
00486    return equals(arg.c_str());
00487 }
00489 bool
00490 String::equalsIgnoreCase(const char* arg) const
00491 {
00492    return(compareToIgnoreCase(arg) == 0);
00493 }
00495 bool
00496 String::equalsIgnoreCase(const String& arg) const
00497 {
00498    return equalsIgnoreCase(arg.c_str());
00499 }
00501 UInt32
00502 String::hashCode() const
00503 {
00504    UInt32 hash = 0;
00505    size_t len = length();
00506    for (size_t i = 0; i < len; i++)
00507    {
00508       // Don't need to check if m_buf is null, because if it is, len == 0,
00509       // and this loop won't be executed.
00510       const char temp = m_buf->data()[i];
00511       hash = (hash << 4) + (temp * 13);
00512       UInt32 g = hash & 0xf0000000;
00513       if (g)
00514       {
00515          hash ^= (g >> 24);
00516          hash ^= g;
00517       }
00518    }
00519    return hash;
00520 }
00522 size_t
00523 String::indexOf(char ch, size_t fromIndex) const
00524 {
00525    //if (fromIndex < 0)
00526    //{
00527    // fromIndex = 0;
00528    //}
00529    size_t cc = npos;
00530    if (fromIndex < length())
00531    {
00532       // Don't need to check m_buf for NULL, because if length() == 0,
00533       // this code won't be executed.
00534       const char* p = String::strchr(m_buf->data()+fromIndex, ch);
00535       if (p)
00536       {
00537          cc = p - m_buf->data();
00538       }
00539    }
00540    return cc;
00541 }
00543 size_t
00544 String::indexOf(const char* arg, size_t fromIndex) const
00545 {
00546    size_t cc = npos;
00547    if (fromIndex < length())
00548    {
00549       // Don't need to check m_buf for NULL, because if length() == 0,
00550       // this code won't be executed, but we do need to check arg.m_buf
00551       char* p(0);
00552       if (arg && *arg)
00553       {
00554          p = ::strstr(m_buf->data()+fromIndex, arg);
00555       }
00556       else
00557       {
00558          p = m_buf->data()+fromIndex;
00559       }
00560 
00561       if (p != NULL)
00562       {
00563          cc = static_cast<size_t>(p - m_buf->data());
00564       }
00565    }
00566    return cc;
00567 }
00569 size_t
00570 String::lastIndexOf(char ch, size_t fromIndex) const
00571 {
00572    if (fromIndex == npos)
00573    {
00574       if ((fromIndex = length()-1) == npos)
00575       {
00576          return npos;
00577       }
00578    }
00579    size_t cc = npos;
00580    if (fromIndex < length())
00581    {
00582       for (size_t i = fromIndex; i != npos; i--)
00583       {
00584          // Don't need to check m_buf for NULL, because if length() == 0,
00585          // this code won't be executed.
00586          if (m_buf->data()[i] == ch)
00587          {
00588             cc = i;
00589             break;
00590          }
00591       }
00592    }
00593    return cc;
00594 }
00596 size_t
00597 String::lastIndexOf(const char* arg, size_t fromIndex) const
00598 {
00599    if (fromIndex == npos || fromIndex >= length())
00600    {
00601       if (static_cast<int>(fromIndex = length()-1) < 0)
00602       {
00603          return npos;
00604       }
00605    }
00606 
00607    int arglen = (arg) ? ::strlen(arg) : 0;
00608    if (static_cast<int>(fromIndex -= arglen - 1) < 0)
00609    {
00610       return npos;
00611    }
00612    if (!arg)
00613    {
00614       return length() - 1;
00615    }
00616    while (fromIndex != npos)
00617    {
00618       // Don't need to check m_buf for NULL, because if length() == 0,
00619       // this code won't be executed.
00620       if (::strncmp(m_buf->data()+fromIndex, arg, arglen) == 0)
00621       {
00622          break;
00623       }
00624       fromIndex--;
00625    }
00626    return fromIndex;
00627 }
00629 bool
00630 String::startsWith(char arg) const
00631 {
00632    return (m_buf
00633          && m_buf->length()
00634          && m_buf->data()[0] == arg);
00635 }
00636 
00638 bool
00639 String::startsWith(const char* arg, EIgnoreCaseFlag ignoreCase) const
00640 {
00641    bool cc = false;
00642    if (!arg && !m_buf)
00643    {
00644       return true;
00645    }
00646    if (!*arg)
00647    {
00648       return (length() == 0);
00649    }
00650 
00651    size_t arglen = ::strlen(arg);
00652    if (arglen <= length())
00653    {
00654       // Don't need to check m_buf for NULL, because if length() == 0,
00655       // this code won't be executed.
00656       if (ignoreCase)
00657       {
00658          cc = (strncmpi(m_buf->data(), arg, arglen) == 0);
00659       }
00660       else
00661       {
00662          cc = (::strncmp(m_buf->data(), arg, arglen) == 0);
00663       }
00664    }
00665    return cc;
00666 }
00668 String
00669 String::substring(size_t beginIndex, size_t len) const
00670 {
00671    String nil;
00672    size_t count = len;
00673    size_t l = length();
00674    if (0 == l)
00675    {
00676       return nil;
00677    }
00678    if (beginIndex >= l)
00679    {
00680       return nil;
00681    }
00682    else if (0 == len)
00683    {
00684       return nil;
00685    }
00686    else if (len == npos)
00687    {
00688       count = l - beginIndex;
00689    }
00690    if (count + beginIndex > l)
00691    {
00692       count = l - beginIndex;
00693    }
00694    // Don't need to check m_buf for NULL, because if length() == 0,
00695    // this code won't be executed.
00696    return String(static_cast<const char*>(m_buf->data()+beginIndex), count);
00697 }
00699 bool
00700 String::isSpaces() const
00701 {
00702    if (!m_buf)
00703    {
00704       return true;
00705    }
00706    char* p = m_buf->data();
00707    while (isspace(*p) && *p != '\0')
00708    {
00709       p++;
00710    }
00711    return (*p == '\0');
00712 }
00714 String&
00715 String::ltrim()
00716 {
00717    if (!m_buf)
00718    {
00719       return *this;
00720    }
00721    char* s1 = m_buf->data();
00722    while (isspace(*s1) && *s1 != '\0')
00723    {
00724       s1++;
00725    }
00726    if (s1 == m_buf->data())
00727    {
00728       return *this;
00729    }
00730    *this = String(s1);
00731    return *this;
00732 }
00734 String&
00735 String::rtrim()
00736 {
00737    if (length() == 0)
00738    {
00739       return *this;
00740    }
00741    char* s1 = m_buf->data() + (length()-1);
00742    while (isspace(*s1) && s1 >= m_buf->data())
00743    {
00744       s1--;
00745    }
00746    if (s1 == (m_buf->data() + (length()-1)))
00747    {
00748       return *this;
00749    }
00750    if (s1 < m_buf->data())
00751    {
00752       *this = String();
00753       return *this;
00754    }
00755    size_t len = (s1 - m_buf->data()) + 1;
00756    *this = String(m_buf->data(), len);
00757    return *this;
00758 }
00760 String&
00761 String::trim()
00762 {
00763    if (length() == 0)
00764    {
00765       return *this;
00766    }
00767    char* s1 = m_buf->data();
00768    while (isspace(*s1) && *s1 != '\0')
00769    {
00770       s1++;
00771    }
00772    if (*s1 == '\0')
00773    {
00774       // String is all spaces
00775       *this = String();
00776       return *this;
00777    }
00778    const char* p2 = String::strchr(s1, '\0');
00779    const char* s2 = p2 - 1;
00780    while (isspace(*s2))
00781    {
00782       s2--;
00783    }
00784    if (s1 == m_buf->data() && s2 == p2)
00785    {
00786       // String has no leading or trailing spaces
00787       return *this;
00788    }
00789    size_t len = (s2 - s1) + 1;
00790    *this = String(s1, len);
00791    return *this;
00792 }
00794 String&
00795 String::erase()
00796 {
00797    m_buf = 0;
00798    return *this;
00799 }
00801 String&
00802 String::erase(size_t idx, size_t len)
00803 {
00804    if ( idx >= length() )
00805    {
00806       return *this;
00807    }
00808    if (len == npos)
00809    {
00810       *this = substring(0, idx);
00811    }
00812    else
00813    {
00814       *this = substring(0, idx) + substring(idx + len);
00815    }
00816    return *this;
00817 }
00819 String&
00820 String::toLowerCase()
00821 {
00822    if (m_buf)
00823    {
00824       if (!UTF8Utils::toLowerCaseInPlace(m_buf->data()))
00825       {
00826          *this = UTF8Utils::toLowerCase(m_buf->data());
00827       }
00828    }
00829    return *this;
00830 }
00831 
00833 String&
00834 String::toUpperCase()
00835 {
00836    if (m_buf)
00837    {
00838       if (!UTF8Utils::toUpperCaseInPlace(m_buf->data()))
00839       {
00840          *this = UTF8Utils::toUpperCase(m_buf->data());
00841       }
00842    }
00843    return *this;
00844 }
00846 void
00847 String::readObject(istream& istrm)
00848 {
00849    UInt32 len;
00850    BinarySerialization::readLen(istrm, len);
00851    AutoPtrVec<char> bfr(new char[len+1]);
00852    BinarySerialization::read(istrm, bfr.get(), len);
00853    bfr[len] = '\0';
00854    m_buf = new ByteBuf(bfr, len);
00855 }
00857 void
00858 String::writeObject(ostream& ostrm) const
00859 {
00860    UInt32 len = static_cast<UInt32>(length());
00861    BinarySerialization::writeLen(ostrm, len);
00862    if (len)
00863    {
00864       BinarySerialization::write(ostrm, m_buf->data(), len);
00865    }
00866 }
00868 String&
00869 String::operator= (const String& arg)
00870 {
00871    m_buf = arg.m_buf;
00872    return *this;
00873 }
00875 const char*
00876 String::c_str() const
00877 {
00878    if (m_buf)
00879    {
00880       return m_buf->data();
00881    }
00882    else
00883    {
00884       return "";
00885    }
00886 }
00888 static const char cnullChar = '\0';
00889 const char&
00890 String::operator[] (size_t ndx) const
00891 {
00892 #ifdef BLOCXX_DEBUG
00893    BLOCXX_ASSERT(ndx <= length());
00894 #endif
00895    // Don't need to check m_buf for NULL, because if length() == 0,
00896    // m_buf->data() won't be executed.
00897    //return (ndx <= length()) ? *(m_buf->data() + ndx) : cnullChar;
00898    if (ndx <= length())
00899    {
00900       return *(m_buf->data() + ndx);
00901    }
00902    else
00903    {
00904       return cnullChar;
00905    }
00906 }
00908 static char nullChar = '\0';
00909 char&
00910 String::operator[] (size_t ndx)
00911 {
00912 #ifdef BLOCXX_DEBUG
00913    BLOCXX_ASSERT(ndx <= length());
00914 #endif
00915    // Don't need to check m_buf for NULL, because if length() == 0,
00916    // m_buf->data() won't be executed.
00917    return (ndx <= length()) ? m_buf->data()[ndx] : nullChar;
00918 }
00920 String
00921 String::toString() const
00922 {
00923    return *this;
00924 }
00926 static inline void
00927 throwStringConversion(const String::buf_t& m_buf, const char* type)
00928 {
00929    BLOCXX_THROW(StringConversionException, Format("Unable to convert \"%1\" into %2", m_buf->data(), type).c_str());
00930 }
00932 static inline void
00933 throwStringConversion(const char* str, const char* type)
00934 {
00935    BLOCXX_THROW(StringConversionException, Format("Unable to convert \"%1\" into %2", str, type).c_str());
00936 }
00938 template <typename T, typename FP>
00939 static inline
00940 T convertToRealType(const String::buf_t& m_buf, const char* type, FP fp)
00941 {
00942    if (m_buf)
00943    {
00944       char* endptr(0);
00945       errno = 0;     // errno is thread local
00946       T rv = fp(m_buf->data(), &endptr);
00947       if (*endptr != '\0' || errno == ERANGE || rv == HUGE_VAL || rv == -HUGE_VAL)
00948       {
00949          throwStringConversion(m_buf, type);
00950       }
00951       return rv;
00952    }
00953    else
00954    {
00955       throwStringConversion("", type);
00956    }
00957    return T(); // to make compiler happy
00958 }
00960 Real32
00961 String::toReal32() const
00962 {
00963 #if defined(BLOCXX_REAL32_IS_FLOAT) && defined(BLOCXX_HAVE_STRTOF)
00964    return convertToRealType<Real32>(m_buf, "Real32", &strtof);
00965 #elif defined(BLOCXX_REAL32_IS_DOUBLE) || (defined(BLOCXX_REAL32_IS_FLOAT) && !defined(BLOCXX_HAVE_STRTOF))
00966    return convertToRealType<Real32>(m_buf, "Real32", &strtod);
00967 #endif
00968 }
00970 Real64
00971 String::toReal64() const
00972 {
00973 #if defined(BLOCXX_REAL64_IS_DOUBLE)
00974    return convertToRealType<Real64>(m_buf, "Real64", &strtod);
00975 #elif defined(BLOCXX_REAL64_IS_LONG_DOUBLE)
00976    return convertToRealType<Real64>(m_buf, "Real64", &strtold);
00977 #endif
00978 }
00980 bool
00981 String::toBool() const
00982 {
00983    if (equalsIgnoreCase("true"))
00984    {
00985       return true;
00986    }
00987    else if (equalsIgnoreCase("false"))
00988    {
00989       return false;
00990    }
00991    else
00992    {
00993       throwStringConversion(c_str(), "bool");
00994    }
00995    return false; // to make compiler happy
00996 }
00997 template <typename T, typename FP, typename FPRT>
00998 static inline
00999 T doConvertToIntType(const String::buf_t& m_buf, const char* type, FP fp, int base)
01000 {
01001    if (m_buf)
01002    {
01003       char* endptr(0);
01004       errno = 0;     // errno is thread local
01005       FPRT v = fp(m_buf->data(), &endptr, base);
01006       T rv = static_cast<T>(v);
01007       if (*endptr != '\0' || errno == ERANGE || FPRT(rv) != v)
01008       {
01009          throwStringConversion(m_buf, type);
01010       }
01011       return rv;
01012    }
01013    else
01014    {
01015       throwStringConversion("", type);
01016    }
01017    return T(); // to make compiler happy
01018 }
01019 typedef unsigned long int (*strtoulfp_t)(const char *, char **,int);
01020 typedef long int (*strtolfp_t)(const char *, char **,int);
01021 typedef unsigned long long int (*strtoullfp_t)(const char *, char **,int);
01022 typedef long long int (*strtollfp_t)(const char *, char **,int);
01023 template <typename T>
01024 static inline
01025 T convertToUIntType(const String::buf_t& m_buf, const char* msg, int base)
01026 {
01027    return doConvertToIntType<T, strtoulfp_t, unsigned long int>(m_buf, msg, &strtoul, base);
01028 }
01029 template <typename T>
01030 static inline
01031 T convertToIntType(const String::buf_t& m_buf, const char* msg, int base)
01032 {
01033    return doConvertToIntType<T, strtolfp_t, long int>(m_buf, msg, &strtol, base);
01034 }
01035 template <typename T>
01036 static inline
01037 T convertToUInt64Type(const String::buf_t& m_buf, const char* msg, int base)
01038 {
01039    return doConvertToIntType<T, strtoullfp_t, unsigned long long int>(m_buf, msg, &String::strtoull, base);
01040 }
01041 template <typename T>
01042 static inline
01043 T convertToInt64Type(const String::buf_t& m_buf, const char* msg, int base)
01044 {
01045    return doConvertToIntType<T, strtollfp_t, long long int>(m_buf, msg, &String::strtoll, base);
01046 }
01048 UInt8
01049 String::toUInt8(int base) const
01050 {
01051    return convertToUIntType<UInt8>(m_buf, "UInt8", base);
01052 }
01054 Int8
01055 String::toInt8(int base) const
01056 {
01057    return convertToIntType<Int8>(m_buf, "Int8", base);
01058 }
01060 UInt16
01061 String::toUInt16(int base) const
01062 {
01063    return convertToUIntType<UInt16>(m_buf, "UInt16", base);
01064 }
01066 Int16
01067 String::toInt16(int base) const
01068 {
01069    return convertToIntType<Int16>(m_buf, "Int16", base);
01070 }
01072 UInt32
01073 String::toUInt32(int base) const
01074 {
01075    return convertToUIntType<UInt32>(m_buf, "UInt32", base);
01076 }
01078 Int32
01079 String::toInt32(int base) const
01080 {
01081    return convertToIntType<Int32>(m_buf, "Int32", base);
01082 }
01084 UInt64
01085 String::toUInt64(int base) const
01086 {
01087    return convertToUInt64Type<UInt64>(m_buf, "UInt64", base);
01088 }
01090 Int64
01091 String::toInt64(int base) const
01092 {
01093    return convertToInt64Type<Int64>(m_buf, "Int64", base);
01094 }
01096 unsigned int
01097 String::toUnsignedInt(int base) const
01098 {
01099    return convertToUIntType<unsigned int>(m_buf, "unsigned int", base);
01100 }
01102 int
01103 String::toInt(int base) const
01104 {
01105    return convertToIntType<int>(m_buf, "int", base);
01106 }
01108 StringArray
01109 String::tokenize(const char* delims, EReturnDelimitersFlag returnDelimitersAsTokens, EEmptyTokenReturnFlag returnEmptyTokens) const
01110 {
01111    StringArray ra;
01112    if (empty())
01113    {
01114       return ra;
01115    }
01116    if (delims == 0)
01117    {
01118       ra.append(*this);
01119       return ra;
01120    }
01121    // Don't need to check m_buf for NULL, because if length() == 0,
01122    // this code won't be executed.
01123    char* pstr = m_buf->data();
01124    AutoPtrVec<char> data(new char[m_buf->length()+1]);
01125    data[0] = 0;
01126    int i = 0;
01127    bool last_was_delim = false;
01128    while (*pstr)
01129    {
01130       if (String::strchr(delims, *pstr))
01131       {
01132          if (data[0] != 0)
01133          {
01134             ra.append(String(data.get()));
01135             data[0] = 0;
01136          }
01137          if ( (returnEmptyTokens == E_RETURN_EMPTY_TOKENS) && last_was_delim )
01138          {
01139             ra.append(String());
01140          }
01141          if ( returnDelimitersAsTokens == E_RETURN_DELIMITERS )
01142          {
01143             ra.append(String(*pstr));
01144          }        
01145          i = 0;
01146          last_was_delim = true;
01147       }
01148       else
01149       {
01150          last_was_delim = false;
01151          data[i++] = *pstr;
01152          data[i] = 0;
01153       }
01154       pstr++;
01155    }
01156    if (data[0] != 0)
01157    {
01158       ra.append(String(data.get()));
01159    }
01160    return ra;
01161 }
01162 
01164 #ifdef BLOCXX_HAVE_STRTOLL
01165 long long int
01166 String::strtoll(const char* nptr, char** endptr, int base)
01167 {
01168    return ::strtoll(nptr, endptr, base);
01169 }
01170 #else
01171 #ifndef LLONG_MAX
01172 #if BLOCXX_SIZEOF_LONG_LONG_INT == 8
01173 #define LLONG_MAX 9223372036854775807LL
01174 #else
01175 #define LLONG_MAX 2147483647LL
01176 #endif
01177 #define LLONG_MIN (-LLONG_MAX - 1LL)
01178 #endif
01179 long long int
01180 String::strtoll(const char* nptr, char** endptr, int base)
01181 {
01182    const char *s;
01183    long long acc, cutoff;
01184    int c;
01185    int neg, any, cutlim;
01186    // Skip white space and pick up leading +/- sign if any.
01187    // If base is 0, allow 0x for hex and 0 for octal, else
01188    // assume decimal; if base is already 16, allow 0x.
01189    s = nptr;
01190    do
01191    {
01192       c = (unsigned char) *s++;
01193    } while (isspace(c));
01194    if (c == '-')
01195    {
01196       neg = 1;
01197       c = *s++;
01198    }
01199    else
01200    {
01201       neg = 0;
01202       if (c == '+')
01203       {
01204          c = *s++;
01205       }
01206    }
01207    if ((base == 0 || base == 16)
01208       && c == '0'
01209       && (*s == 'x' || *s == 'X'))
01210    {
01211       c = s[1];
01212       s += 2;
01213       base = 16;
01214    }
01215    if (base == 0)
01216    {
01217       base = c == '0' ? 8 : 10;
01218    }
01219    // Compute the cutoff value between legal numbers and illegal
01220    // numbers.  That is the largest legal value, divided by the
01221    // base.  An input number that is greater than this value, if
01222    // followed by a legal input character, is too big.  One that
01223    // is equal to this value may be valid or not; the limit
01224    // between valid and invalid numbers is then based on the last
01225    // digit.  For instance, if the range for longs is
01226    // [-2147483648..2147483647] and the input base is 10,
01227    // cutoff will be set to 214748364 and cutlim to either
01228    // 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
01229    // a value > 214748364, or equal but the next digit is > 7 (or 8),
01230    // the number is too big, and we will return a range error.
01231    //
01232    // Set any if any `digits' consumed; make it negative to indicate
01233    // overflow.
01234    cutoff = neg ? LLONG_MIN : LLONG_MAX;
01235    cutlim = static_cast<int>(cutoff % base);
01236    cutoff /= base;
01237    if (neg)
01238    {
01239       if (cutlim > 0)
01240       {
01241          cutlim -= base;
01242          cutoff += 1;
01243       }
01244       cutlim = -cutlim;
01245    }
01246    for (acc = 0, any = 0;; c = (unsigned char) *s++)
01247    {
01248       if (isdigit(c))
01249       {
01250          c -= '0';
01251       }
01252       else if (isalpha(c))
01253       {
01254          c -= isupper(c) ? 'A' - 10 : 'a' - 10;
01255       }
01256       else
01257       {
01258          break;
01259       }
01260       if (c >= base)
01261       {
01262          break;
01263       }
01264       if (any < 0)
01265       {
01266          continue;
01267       }
01268       if (neg)
01269       {
01270          if (acc < cutoff || acc == cutoff && c > cutlim)
01271          {
01272             any = -1;
01273             acc = LLONG_MIN;
01274             errno = ERANGE;
01275          }
01276          else
01277          {
01278             any = 1;
01279             acc *= base;
01280             acc -= c;
01281          }
01282       }
01283       else
01284       {
01285          if (acc > cutoff || acc == cutoff && c > cutlim)
01286          {
01287             any = -1;
01288             acc = LLONG_MAX;
01289             errno = ERANGE;
01290          }
01291          else
01292          {
01293             any = 1;
01294             acc *= base;
01295             acc += c;
01296          }
01297       }
01298    }
01299    if (endptr != 0)
01300    {
01301       *endptr = (char *) (any ? s - 1 : nptr);
01302    }
01303    return(acc);
01304 }
01305 #endif   // #ifdef BLOCXX_HAVE_STRTOLL
01306 
01308 #ifdef BLOCXX_HAVE_STRTOULL
01309 unsigned long long int
01310 String::strtoull(const char* nptr, char** endptr, int base)
01311 {
01312    return ::strtoull(nptr, endptr, base);
01313 }
01314 #else
01315 #ifndef ULLONG_MAX
01316 #if BLOCXX_SIZEOF_LONG_LONG_INT == 8
01317 #define ULLONG_MAX 18446744073709551615ULL
01318 #else
01319 #define ULLONG_MAX 4294967295ULL
01320 #endif
01321 #endif
01322 unsigned long long int
01323 String::strtoull(const char* nptr, char** endptr, int base)
01324 {
01325    const char *s;
01326    unsigned long long acc, cutoff, cutlim;
01327    unsigned int c;
01328    int neg, any;
01329    s = nptr;
01330    do
01331    {
01332       c = (unsigned char) *s++;
01333    } while (isspace(c));
01334    if (c == '-')
01335    {
01336       neg = 1;
01337       c = *s++;
01338    }
01339    else
01340    {
01341       neg = 0;
01342       if (c == '+')
01343       {
01344          c = *s++;
01345       }
01346    }
01347    if ((base == 0 || base == 16)
01348       && c == '0'
01349       && (*s == 'x' || *s == 'X'))
01350    {
01351       c = s[1];
01352       s += 2;
01353       base = 16;
01354    }
01355    if (base == 0)
01356    {
01357       base = c == '0' ? 8 : 10;
01358    }
01359    cutoff = ULLONG_MAX / (unsigned long long)base;
01360    cutlim = ULLONG_MAX % (unsigned long long)base;
01361    for (acc = 0, any = 0;; c = (unsigned char) *s++)
01362    {
01363       if (isdigit(c))
01364       {
01365          c -= '0';
01366       }
01367       else if (isalpha(c))
01368       {
01369          c -= isupper(c) ? 'A' - 10 : 'a' - 10;
01370       }
01371       else
01372       {
01373          break;
01374       }
01375       if (c >= (unsigned int)base)
01376       {
01377          break;
01378       }
01379       if (any < 0)
01380       {
01381          continue;
01382       }
01383       if (acc > cutoff || acc == cutoff && c > cutlim)
01384       {
01385          any = -1;
01386          acc = ULLONG_MAX;
01387          errno = ERANGE;
01388       }
01389       else
01390       {
01391          any = 1;
01392          acc *= (unsigned long)base;
01393          acc += c;
01394       }
01395    }
01396    if (neg && any > 0)
01397    {
01398 #ifdef BLOCXX_WIN32
01399 #pragma warning (push)
01400 #pragma warning (disable: 4146)
01401 #endif
01402 
01403       acc = -acc;
01404 
01405 #ifdef BLOCXX_WIN32
01406 #pragma warning (pop)
01407 #endif
01408 
01409    }
01410    if (endptr != 0)
01411    {
01412       *endptr = (char *) (any ? s - 1 : nptr);
01413    }
01414    return(acc);
01415 }
01416 #endif   // #ifdef BLOCXX_HAVE_STRTOULL
01417 
01418 String
01419 operator + (const String& s1, const String& s2)
01420 {
01421    String rstr(s1);
01422    rstr += s2;
01423    return rstr;
01424 }
01426 String
01427 operator + (const char* p, const String& s)
01428 {
01429    String rstr(p);
01430    rstr += s;
01431    return rstr;
01432 }
01434 String
01435 operator + (const String& s, const char* p)
01436 {
01437    String rstr(s);
01438    rstr += p;
01439    return rstr;
01440 }
01442 String
01443 operator + (char c, const String& s)
01444 {
01445    String rstr(c);
01446    rstr += s;
01447    return rstr;
01448 }
01450 String
01451 operator + (const String& s, char c)
01452 {
01453    String rstr(s);
01454    rstr += String(c);
01455    return rstr;
01456 }
01458 ostream&
01459 operator<< (ostream& ostr, const String& arg)
01460 {
01461    ostr.write(arg.c_str(), arg.length());
01462    return ostr;
01463 }
01465 // static
01466 String
01467 String::getLine(istream& is)
01468 {
01469    StringBuffer rv(80);
01470    rv.getLine(is);
01471    return rv.releaseString();
01472 }
01474 // STATIC
01475 const char*
01476 String::strchr(const char* theStr, int c)
01477 {
01478    const char* tmpChar = theStr;
01479    for (; *tmpChar && *tmpChar != c; tmpChar++)
01480    {
01481       // empty
01482    }
01483    return ((*tmpChar) == c ? tmpChar : 0);
01484 }
01485 
01486 } // end namespace BLOCXX_NAMESPACE
01487 

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