00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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>
00065 #include <cfloat>
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
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
00206
00207 OStringStream ss;
00208 ss << val;
00209 m_buf = new ByteBuf(ss.c_str());
00210 #endif
00211 }
00213
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
00340 while (true)
00341 {
00342 va_start(ap, fmt);
00343 n = vsnprintf(p.get(), size, fmt, ap);
00344 va_end(ap);
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)
00351 size = n+1;
00352 else
00353 size *= 2;
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
00503
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
00520
00521
00522
00523 size_t cc = npos;
00524 if (fromIndex < length())
00525 {
00526
00527
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
00544
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
00579
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
00613
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
00649
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
00689
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
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
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
00890
00891
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
00910
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;
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();
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;
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;
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();
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
01116
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
01181
01182
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
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
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
01460 String
01461 String::getLine(istream& is)
01462 {
01463 StringBuffer rv(80);
01464 rv.getLine(is);
01465 return rv.releaseString();
01466 }
01468
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
01476 }
01477 return ((*tmpChar) == c ? tmpChar : 0);
01478 }
01479
01480 }
01481