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(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
00346 while (true)
00347 {
00348 va_start(ap, fmt);
00349 n = vsnprintf(p.get(), size, fmt, ap);
00350 va_end(ap);
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)
00357 size = n+1;
00358 else
00359 size *= 2;
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
00509
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
00526
00527
00528
00529 size_t cc = npos;
00530 if (fromIndex < length())
00531 {
00532
00533
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
00550
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
00585
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
00619
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
00655
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
00695
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
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
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
00896
00897
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
00916
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;
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();
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;
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;
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();
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
01122
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
01187
01188
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
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
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
01466 String
01467 String::getLine(istream& is)
01468 {
01469 StringBuffer rv(80);
01470 rv.getLine(is);
01471 return rv.releaseString();
01472 }
01474
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
01482 }
01483 return ((*tmpChar) == c ? tmpChar : 0);
01484 }
01485
01486 }
01487