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