blocxx
String.cpp
Go to the documentation of this file.
1/*******************************************************************************
2* Copyright (C) 2005, Vintela, Inc. All rights reserved.
3* Copyright (C) 2006, Novell, Inc. All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met:
7*
8* * Redistributions of source code must retain the above copyright notice,
9* this list of conditions and the following disclaimer.
10* * Redistributions in binary form must reproduce the above copyright
11* notice, this list of conditions and the following disclaimer in the
12* documentation and/or other materials provided with the distribution.
13* * Neither the name of
14* Vintela, Inc.,
15* nor Novell, Inc.,
16* nor the names of its contributors or employees may be used to
17* endorse or promote products derived from this software without
18* specific prior written permission.
19*
20* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30* POSSIBILITY OF SUCH DAMAGE.
31*******************************************************************************/
32
33
39#include "blocxx/BLOCXX_config.h"
40#include "blocxx/String.hpp"
41#include "blocxx/Char16.hpp"
42#include "blocxx/Array.hpp"
44#include "blocxx/Format.hpp"
46#include "blocxx/Assertion.hpp"
47#include "blocxx/AutoPtr.hpp"
48#include "blocxx/Bool.hpp"
49#include "blocxx/UTF8Utils.hpp"
52
53#include <cstdio>
54#include <cstdlib>
55#include <cstring>
56#include <cctype>
57#include <cstdarg>
58#include <cerrno>
59#if defined(BLOCXX_HAVE_ISTREAM) && defined(BLOCXX_HAVE_OSTREAM)
60#include <istream>
61#include <ostream>
62#else
63#include <iostream>
64#endif
65#include <cmath> // for HUGE_VAL
66#include <cfloat> // for DBL_MANT_DIG
67
68#ifdef BLOCXX_WIN32
69#define SNPRINTF _snprintf
70#else
71#define SNPRINTF snprintf
72#endif
73
74namespace BLOCXX_NAMESPACE
75{
76
77using std::istream;
78using std::ostream;
79using std::streambuf;
80
82
84static inline int
85strncmpi(const char* s1, const char* s2, size_t n)
86{
87 String ls1(s1, n);
88 String ls2(s2, n);
89 return ls1.compareToIgnoreCase(ls2);
90}
91
92// class invariant: m_buf points to a null-terminated sequence of characters. m_buf is m_len+1 bytes long.
94{
95public:
96 ByteBuf(const char* s) :
97 m_len(::strlen(s)), m_buf(new char[m_len+1])
98 {
99 strcpy(m_buf, s);
100 }
101
102 ByteBuf(const ByteBuf& arg)
104 , m_len(arg.m_len)
105 , m_buf(new char[m_len+1])
106 {
107 strcpy(m_buf, arg.m_buf);
108 }
109
110 ByteBuf(AutoPtrVec<char>& s, size_t len)
111 : m_len(len), m_buf(s.release())
112 {
113 }
114
115 ~ByteBuf() { delete [] m_buf; }
116
118 {
119 char* buf = new char[arg.m_len+1];
120 strcpy(buf, arg.m_buf);
121 delete [] m_buf;
122 m_buf = buf;
123 m_len = arg.m_len;
124 return *this;
125 }
126
127 size_t length() const { return m_len; }
128 char* data() const { return m_buf; }
129 ByteBuf* clone() const { return new ByteBuf(*this); }
130private:
131 size_t m_len;
132 char* m_buf;
133};
135#if defined(BLOCXX_AIX)
136const size_t String::npos = ~0;
137#endif
140 m_buf(0)
141{
142}
145 m_buf(parm.toString().m_buf)
146{
147}
149String::String(const Char16& parm) :
150 m_buf(parm.toString().m_buf)
151{
152}
154String::String(const std::string& str) :
155 m_buf(str.empty() ? 0 : new ByteBuf(str.c_str()))
156{
157}
158#if defined(BLOCXX_WIN32)
159#define snprintf _snprintf // stupid windoze...
160#endif
162String::String(Int32 val) :
163 m_buf(NULL)
164{
165 char tmpbuf[32];
166 int len = snprintf(tmpbuf, sizeof(tmpbuf), "%d", val);
167 AutoPtrVec<char> bfr(new char[len+1]);
168 ::snprintf(bfr.get(), len+1, "%d", val);
169 m_buf = new ByteBuf(bfr, len);
170}
172String::String(UInt32 val) :
173 m_buf(NULL)
174{
175 char tmpbuf[32];
176 int len = ::snprintf(tmpbuf, sizeof(tmpbuf), "%u", val);
177 AutoPtrVec<char> bfr(new char[len+1]);
178 ::snprintf(bfr.get(), len+1, "%u", val);
179 m_buf = new ByteBuf(bfr, len);
180}
181#if defined(BLOCXX_INT32_IS_INT) && defined(BLOCXX_INT64_IS_LONG_LONG)
183String::String(long val) :
184 m_buf(NULL)
185{
186 char tmpbuf[32];
187 int len = snprintf(tmpbuf, sizeof(tmpbuf), "%ld", val);
188 AutoPtrVec<char> bfr(new char[len+1]);
189 ::snprintf(bfr.get(), len+1, "%ld", val);
190 m_buf = new ByteBuf(bfr, len);
191}
193String::String(unsigned long val) :
194 m_buf(NULL)
195{
196 char tmpbuf[32];
197 int len = ::snprintf(tmpbuf, sizeof(tmpbuf), "%lu", val);
198 AutoPtrVec<char> bfr(new char[len+1]);
199 ::snprintf(bfr.get(), len+1, "%lu", val);
200 m_buf = new ByteBuf(bfr, len);
201}
202#endif
203#if defined(BLOCXX_WIN32)
204#undef snprintf
205#endif
207String::String(Int64 val) :
208 m_buf(NULL)
209{
210 OStringStream ss(33);
211 ss << val;
212 m_buf = new ByteBuf(ss.c_str());
213}
215String::String(UInt64 val) :
216 m_buf(NULL)
217{
218#if defined(BLOCXX_INT64_IS_LONG)
219 char tmpbuf[32];
220 ::snprintf(tmpbuf, sizeof(tmpbuf), "%lu", val);
221 m_buf = new ByteBuf(tmpbuf);
222#elif defined(BLOCXX_INT64_IS_LONG_LONG)
223 // unfortunately not all C libraries support long long with snprintf().
224 // but the C++ iostream library handles it.
225 OStringStream ss;
226 ss << val;
227 m_buf = new ByteBuf(ss.c_str());
228#endif
229}
231// decimal digits = ceiling((bits)*ln(2)/ln(10))
232String::String(Real32 val) :
233 m_buf(NULL)
234{
235 char tmpbuf[128];
236#if FLT_RADIX == 2
237#if defined(BLOCXX_REAL32_IS_FLOAT)
238 ::SNPRINTF(tmpbuf, sizeof(tmpbuf), "%.*g", FLT_MANT_DIG * 3 / 10 + 1, static_cast<double>(val));
239#elif defined(BLOCXX_REAL32_IS_DOUBLE)
240 ::SNPRINTF(tmpbuf, sizeof(tmpbuf), "%.*g", DBL_MANT_DIG * 3 / 10 + 1, val);
241#endif
242#else
243#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))"
244#endif
245 m_buf = new ByteBuf(tmpbuf);
246}
248String::String(Real64 val) :
249 m_buf(NULL)
250{
251 char tmpbuf[128];
252#if FLT_RADIX == 2
253#if defined(BLOCXX_REAL64_IS_DOUBLE)
254 ::SNPRINTF(tmpbuf, sizeof(tmpbuf), "%.*g", DBL_MANT_DIG * 3 / 10 + 1, val);
255#elif defined(BLOCXX_REAL64_IS_LONG_DOUBLE)
256 ::SNPRINTF(tmpbuf, sizeof(tmpbuf), "%.*Lg", LDBL_MANT_DIG * 3 / 10 + 1, val);
257#endif
258#else
259#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))"
260#endif
261 m_buf = new ByteBuf(tmpbuf);
262}
264String::String(const char* str) :
265 m_buf(NULL)
266{
267 m_buf = (NULL == str) ? 0 : new ByteBuf(str);
268}
270String::String(ETakeOwnershipFlag, char* allocatedMemory, size_t len) :
271 m_buf(NULL)
272{
273 BLOCXX_ASSERT(allocatedMemory != 0);
274 AutoPtrVec<char> p(allocatedMemory);
275 m_buf = new ByteBuf(p, len);
276}
278String::String(const char* str, size_t len) :
279 m_buf(NULL)
280{
281 if (NULL == str)
282 {
283 m_buf = 0;
284 }
285 else
286 {
287 AutoPtrVec<char> bfr(new char[len+1]);
288 ::memcpy(bfr.get(), str, len);
289 bfr[len] = '\0';
290 m_buf = new ByteBuf(bfr, len);
291 }
292}
295 m_buf(arg.m_buf)
296{
297}
300 m_buf(NULL)
301{
302 size_t sz = ra.size();
303 if (sz > 0)
304 {
305 StringBuffer buf(sz * 2);
306 for (size_t i = 0; i < sz; i++)
307 {
308 buf += ra[i].toString();
309 }
310 m_buf = buf.releaseString().m_buf;
311 }
312 else
313 {
314 m_buf = 0;
315 }
316}
319 m_buf(NULL)
320{
321 if (c != '\0')
322 {
323 char bfr[2];
324 bfr[0] = c;
325 bfr[1] = '\0';
326 m_buf = new ByteBuf(bfr);
327 }
328 else
329 {
330 m_buf = 0;
331 }
332}
335{
336}
338void
340{
341 m_buf.swap(x.m_buf);
342}
344char*
346{
347 size_t len = length() + 1;
348 char* str = static_cast<char*>(malloc(len));
349 ::strcpy(str, c_str());
350 return str;
351}
353size_t
355{
356 return (m_buf) ? m_buf->length() : 0;
357}
359size_t
361{
362 return UTF8Utils::charCount(c_str());
363}
365#ifdef BLOCXX_WIN32
366#define vsnprintf _vsnprintf // stupid windoze
367#endif
368int
369String::format(const char* fmt, ...)
370{
371 int n, size = 64;
372 AutoPtrVec<char> p(new char[size]);
373
374 va_list ap;
375
376 // Try to print in the allocated space
377 while (true)
378 {
379 va_start(ap, fmt);
380 n = vsnprintf(p.get(), size, fmt, ap);
381 va_end(ap); // If that worked, return the string.
382 if (n > -1 && n < size)
383 {
384 m_buf = new ByteBuf(p, n);
385 return static_cast<int>(length());
386 }
387 if (n > -1) // glibc 2.1
388 size = n+1; // precisely what is needed
389 else // glibc 2.0
390 size *= 2; // twice the old size
391 p = new char[size];
392 }
393 // Not reachable.
394 return 0;
395}
396#ifdef BLOCXX_WIN32
397#undef vsnprintf // stupid windoze
398#endif
400char
401String::charAt(size_t ndx) const
402{
403 return (m_buf) ? m_buf->data()[ndx] : '\0';
404}
406int
407String::compareTo(const char* arg) const
408{
409 const char* lhs = "";
410 if (m_buf)
411 {
412 lhs = m_buf->data();
413 }
414 return ::strcmp(lhs, arg);
415}
417int
418String::compareTo(const String& arg) const
419{
420 return compareTo(arg.c_str());
421}
423int
424String::compareToIgnoreCase(const char* arg) const
425{
426 const char* lhs = "";
427 if (m_buf)
428 {
429 lhs = m_buf->data();
430 }
431 return UTF8Utils::compareToIgnoreCase(lhs, arg);
432}
434int
436{
437 return compareToIgnoreCase(arg.c_str());
438}
439
441String&
442String::concat(const char* arg)
443{
444 if (arg && *arg)
445 {
446 size_t len = length() + ::strlen(arg);
447 AutoPtrVec<char> bfr(new char[len+1]);
448 bfr[0] = 0;
449 if (m_buf)
450 {
451 ::strcpy(bfr.get(), m_buf->data());
452 }
453 ::strcat(bfr.get(), arg);
454 m_buf = new ByteBuf(bfr, len);
455 }
456 return *this;
457}
458
460String&
462{
463 size_t newlen = length() + 1;
464 AutoPtrVec<char> bfr(new char[newlen+1]);
465 bfr[0] = 0;
466 if (m_buf)
467 {
468 ::strcpy(bfr.get(), m_buf->data());
469 }
470 *(bfr.get()+length()) = arg;
471 *(bfr.get()+newlen) = 0;
472 m_buf = new ByteBuf(bfr, newlen);
473 return *this;
474}
475
477bool
478String::endsWith(char arg) const
479{
480 return (m_buf
481 && m_buf->length()
482 && m_buf->data()[m_buf->length()-1] == arg);
483}
484
486bool
487String::endsWith(const char* arg, EIgnoreCaseFlag ignoreCase) const
488{
489 if (!arg || !*arg)
490 {
491 return (length() == 0);
492 }
493
494 if (!m_buf)
495 {
496 return false;
497 }
498
499 int ndx = static_cast<int>(length() - ::strlen(arg));
500 if (ndx < 0)
501 {
502 return false;
503 }
504
505 return (ignoreCase)
506 ? (UTF8Utils::compareToIgnoreCase(m_buf->data()+ndx, arg) == 0)
507 : (::strcmp(m_buf->data()+ndx, arg) == 0);
508}
510bool
511String::equals(const char* arg) const
512{
513 return(compareTo(arg) == 0);
514}
516bool
517String::equals(const String& arg) const
518{
519 return equals(arg.c_str());
520}
522bool
523String::equalsIgnoreCase(const char* arg) const
524{
525 return(compareToIgnoreCase(arg) == 0);
526}
528bool
530{
531 return equalsIgnoreCase(arg.c_str());
532}
534UInt32
536{
537 UInt32 hash = 0;
538 size_t len = length();
539 for (size_t i = 0; i < len; i++)
540 {
541 // Don't need to check if m_buf is null, because if it is, len == 0,
542 // and this loop won't be executed.
543 const char temp = m_buf->data()[i];
544 hash = (hash << 4) + (temp * 13);
545 UInt32 g = hash & 0xf0000000;
546 if (g)
547 {
548 hash ^= (g >> 24);
549 hash ^= g;
550 }
551 }
552 return hash;
553}
555size_t
556String::indexOf(char ch, size_t fromIndex) const
557{
558 //if (fromIndex < 0)
559 //{
560 // fromIndex = 0;
561 //}
562 size_t cc = npos;
563 if (fromIndex < length())
564 {
565 // Don't need to check m_buf for NULL, because if length() == 0,
566 // this code won't be executed.
567 const char* p = String::strchr(m_buf->data()+fromIndex, ch);
568 if (p)
569 {
570 cc = p - m_buf->data();
571 }
572 }
573 return cc;
574}
576size_t
577String::indexOf(const char* arg, size_t fromIndex) const
578{
579 size_t cc = npos;
580 if (fromIndex < length())
581 {
582 // Don't need to check m_buf for NULL, because if length() == 0,
583 // this code won't be executed
584 char* p(0);
585 if (arg && *arg)
586 {
587 p = ::strstr(m_buf->data()+fromIndex, arg);
588 }
589 else
590 {
591 p = m_buf->data()+fromIndex;
592 }
593
594 if (p != NULL)
595 {
596 cc = static_cast<size_t>(p - m_buf->data());
597 }
598 }
599 return cc;
600}
602size_t
603String::lastIndexOf(char ch, size_t fromIndex) const
604{
605 if (fromIndex == npos)
606 {
607 if ((fromIndex = length()-1) == npos)
608 {
609 return npos;
610 }
611 }
612 size_t cc = npos;
613 if (fromIndex < length())
614 {
615 for (size_t i = fromIndex; i != npos; i--)
616 {
617 // Don't need to check m_buf for NULL, because if length() == 0,
618 // this code won't be executed.
619 if (m_buf->data()[i] == ch)
620 {
621 cc = i;
622 break;
623 }
624 }
625 }
626 return cc;
627}
629size_t
630String::lastIndexOf(const char* arg, size_t fromIndex) const
631{
632 if (fromIndex == npos || fromIndex >= length())
633 {
634 if (static_cast<int>(fromIndex = length()-1) < 0)
635 {
636 return npos;
637 }
638 }
639
640 int arglen = (arg) ? ::strlen(arg) : 0;
641 if (static_cast<int>(fromIndex -= arglen - 1) < 0)
642 {
643 return npos;
644 }
645 if (!arg)
646 {
647 return length() - 1;
648 }
649 while (fromIndex != npos)
650 {
651 // Don't need to check m_buf for NULL, because if length() == 0,
652 // this code won't be executed.
653 if (::strncmp(m_buf->data()+fromIndex, arg, arglen) == 0)
654 {
655 break;
656 }
657 fromIndex--;
658 }
659 return fromIndex;
660}
662bool
663String::startsWith(char arg) const
664{
665 return (m_buf
666 && m_buf->length()
667 && m_buf->data()[0] == arg);
668}
669
671bool
672String::startsWith(const char* arg, EIgnoreCaseFlag ignoreCase) const
673{
674 bool cc = false;
675 if (!arg || !*arg) // treat NULL as identical to the empty string
676 {
677 return true; // the empty string is a prefix of any string
678 }
679
680 size_t arglen = ::strlen(arg);
681 if (arglen <= length())
682 {
683 // Don't need to check m_buf for NULL, because if length() == 0,
684 // this code won't be executed.
685 if (ignoreCase == E_CASE_INSENSITIVE)
686 {
687 cc = (strncmpi(m_buf->data(), arg, arglen) == 0);
688 }
689 else
690 {
691 cc = (::strncmp(m_buf->data(), arg, arglen) == 0);
692 }
693 }
694 return cc;
695}
697String
698String::substring(size_t beginIndex, size_t len) const
699{
700 String nil;
701 size_t count = len;
702 size_t l = length();
703 if (0 == l)
704 {
705 return nil;
706 }
707 if (beginIndex >= l)
708 {
709 return nil;
710 }
711 else if (0 == len)
712 {
713 return nil;
714 }
715 else if (len == npos)
716 {
717 count = l - beginIndex;
718 }
719 if (count + beginIndex > l)
720 {
721 count = l - beginIndex;
722 }
723 // Don't need to check m_buf for NULL, because if length() == 0,
724 // this code won't be executed.
725 return String(static_cast<const char*>(m_buf->data()+beginIndex), count);
726}
728bool
730{
731 if (!m_buf)
732 {
733 return true;
734 }
735 char* p = m_buf->data();
736 while (isspace(*p) && *p != '\0')
737 {
738 p++;
739 }
740 return (*p == '\0');
741}
743String&
745{
746 if (!m_buf)
747 {
748 return *this;
749 }
750 char* s1 = m_buf->data();
751 while (isspace(*s1) && *s1 != '\0')
752 {
753 s1++;
754 }
755 if (s1 == m_buf->data())
756 {
757 return *this;
758 }
759 *this = String(s1);
760 return *this;
761}
763String&
765{
766 if (length() == 0)
767 {
768 return *this;
769 }
770 char* s1 = m_buf->data() + (length()-1);
771 while (isspace(*s1) && s1 >= m_buf->data())
772 {
773 s1--;
774 }
775 if (s1 == (m_buf->data() + (length()-1)))
776 {
777 return *this;
778 }
779 if (s1 < m_buf->data())
780 {
781 *this = String();
782 return *this;
783 }
784 size_t len = (s1 - m_buf->data()) + 1;
785 *this = String(m_buf->data(), len);
786 return *this;
787}
789String&
791{
792 if (length() == 0)
793 {
794 return *this;
795 }
796 char* s1 = m_buf->data();
797 while (isspace(*s1) && *s1 != '\0')
798 {
799 s1++;
800 }
801 if (*s1 == '\0')
802 {
803 // String is all spaces
804 *this = String();
805 return *this;
806 }
807 const char* p2 = String::strchr(s1, '\0');
808 const char* s2 = p2 - 1;
809 while (isspace(*s2))
810 {
811 s2--;
812 }
813 if (s1 == m_buf->data() && s2 == p2)
814 {
815 // String has no leading or trailing spaces
816 return *this;
817 }
818 size_t len = (s2 - s1) + 1;
819 *this = String(s1, len);
820 return *this;
821}
823String&
825{
826 m_buf = 0;
827 return *this;
828}
830String&
831String::erase(size_t idx, size_t len)
832{
833 if ( idx >= length() )
834 {
835 return *this;
836 }
837 if (len == npos)
838 {
839 *this = substring(0, idx);
840 }
841 else
842 {
843 *this = substring(0, idx) + substring(idx + len);
844 }
845 return *this;
846}
848String&
850{
851 if (m_buf)
852 {
854 {
856 }
857 }
858 return *this;
859}
860
862String&
864{
865 if (m_buf)
866 {
868 {
870 }
871 }
872 return *this;
873}
875void
876String::readObject(streambuf & istrm)
877{
878 UInt32 len;
880 AutoPtrVec<char> bfr(new char[len+1]);
881 BinarySerialization::read(istrm, bfr.get(), len);
882 bfr[len] = '\0';
883 m_buf = new ByteBuf(bfr, len);
884}
886void
887String::writeObject(streambuf & ostrm) const
888{
889 UInt32 len = static_cast<UInt32>(length());
891 if (len)
892 {
893 BinarySerialization::write(ostrm, m_buf->data(), len);
894 }
895}
897String&
899{
900 m_buf = arg.m_buf;
901 return *this;
902}
904const char*
906{
907 if (m_buf)
908 {
909 return m_buf->data();
910 }
911 else
912 {
913 return "";
914 }
915}
917static const char cnullChar = '\0';
918const char&
919String::operator[] (size_t ndx) const
920{
921#ifdef BLOCXX_DEBUG
922 BLOCXX_ASSERT(ndx <= length());
923#endif
924 if (!m_buf) // then length() == 0
925 {
926 // Only needed in case ndx == 0, but doesn't hurt if ndx > 0
927 const_cast<buf_t &>(m_buf) = new ByteBuf("");
928 }
929 return *(ndx <= m_buf->length() ? m_buf->data() + ndx : &cnullChar);
930}
932static char nullChar = '\0';
933char&
935{
936#ifdef BLOCXX_DEBUG
937 BLOCXX_ASSERT(ndx <= length());
938#endif
939 if (!m_buf) // then length() == 0
940 {
941 // Only needed in case ndx == 0, but doesn't hurt if ndx > 0
942 m_buf = new ByteBuf("");
943 }
944 return (ndx <= m_buf->length() ? m_buf->data()[ndx] : nullChar);
945}
947String
949{
950 return *this;
951}
953static inline void
955{
956 BLOCXX_THROW(StringConversionException, Format("Unable to convert \"%1\" into %2", m_buf->data(), type).c_str());
957}
959static inline void
960throwStringConversion(const char* str, const char* type)
961{
962 BLOCXX_THROW(StringConversionException, Format("Unable to convert \"%1\" into %2", str, type).c_str());
963}
965Char16
967{
968 if (UTF8Length() != 1)
969 {
970 throwStringConversion(c_str(), "Char16");
971 }
972 return Char16(*this);
973}
974template <typename T, typename FP>
975static inline
976T convertToRealType(const String::buf_t& m_buf, const char* type, FP fp)
977{
978 if (m_buf && m_buf->length() > 0)
979 {
980 char* endptr(0);
981 errno = 0; // errno is thread local
982 T rv = fp(m_buf->data(), &endptr);
983 if (*endptr != '\0' || errno == ERANGE || rv == HUGE_VAL || rv == -HUGE_VAL)
984 {
986 }
987 return rv;
988 }
989 else
990 {
991 throwStringConversion("", type);
992 }
993 return T(); // to make compiler happy
994}
996Real32
998{
999#if defined(BLOCXX_REAL32_IS_FLOAT) && defined(BLOCXX_HAVE_STRTOF)
1000 return convertToRealType<Real32>(m_buf, "Real32", &strtof);
1001#elif defined(BLOCXX_REAL32_IS_DOUBLE) || (defined(BLOCXX_REAL32_IS_FLOAT) && !defined(BLOCXX_HAVE_STRTOF))
1002 return convertToRealType<Real32>(m_buf, "Real32", &strtod);
1003#endif
1004}
1006Real64
1008{
1009#if defined(BLOCXX_REAL64_IS_DOUBLE)
1010 return convertToRealType<Real64>(m_buf, "Real64", &strtod);
1011#elif defined(BLOCXX_REAL64_IS_LONG_DOUBLE)
1012 return convertToRealType<Real64>(m_buf, "Real64", &strtold);
1013#endif
1014}
1016bool
1018{
1019 if (equalsIgnoreCase("true"))
1020 {
1021 return true;
1022 }
1023 else if (equalsIgnoreCase("false"))
1024 {
1025 return false;
1026 }
1027 else
1028 {
1029 throwStringConversion(c_str(), "bool");
1030 }
1031 return false; // to make compiler happy
1032}
1033template <typename T, typename FP, typename FPRT>
1034static inline
1035T doConvertToIntType(const String::buf_t& m_buf, const char* type, FP fp, int base)
1036{
1037 // the error detecting code below won't detect an empty string, so
1038 // we have to check for it explicitly.
1039 if (m_buf && m_buf->length() > 0)
1040 {
1041 char* endptr(0);
1042 errno = 0; // errno is thread local
1043 FPRT v = fp(m_buf->data(), &endptr, base);
1044 T rv = static_cast<T>(v);
1045 if (*endptr != '\0' || errno == ERANGE || FPRT(rv) != v)
1046 {
1048 }
1049 return rv;
1050 }
1051 else
1052 {
1053 throwStringConversion("", type);
1054 }
1055 return T(); // to make compiler happy
1056}
1057typedef unsigned long int (*strtoulfp_t)(const char *, char **,int);
1058typedef long int (*strtolfp_t)(const char *, char **,int);
1059typedef unsigned long long int (*strtoullfp_t)(const char *, char **,int);
1060typedef long long int (*strtollfp_t)(const char *, char **,int);
1061template <typename T>
1062static inline
1063T convertToUIntType(const String::buf_t& m_buf, const char* msg, int base)
1064{
1066}
1067template <typename T>
1068static inline
1069T convertToIntType(const String::buf_t& m_buf, const char* msg, int base)
1070{
1071 return doConvertToIntType<T, strtolfp_t, long int>(m_buf, msg, &strtol, base);
1072}
1073template <typename T>
1074static inline
1075T convertToUInt64Type(const String::buf_t& m_buf, const char* msg, int base)
1076{
1078}
1079template <typename T>
1080static inline
1081T convertToInt64Type(const String::buf_t& m_buf, const char* msg, int base)
1082{
1084}
1086UInt8
1087String::toUInt8(int base) const
1088{
1089 return convertToUIntType<UInt8>(m_buf, "UInt8", base);
1090}
1092Int8
1093String::toInt8(int base) const
1094{
1095 return convertToIntType<Int8>(m_buf, "Int8", base);
1096}
1098UInt16
1099String::toUInt16(int base) const
1100{
1101 return convertToUIntType<UInt16>(m_buf, "UInt16", base);
1102}
1104Int16
1105String::toInt16(int base) const
1106{
1107 return convertToIntType<Int16>(m_buf, "Int16", base);
1108}
1110UInt32
1111String::toUInt32(int base) const
1112{
1113 return convertToUIntType<UInt32>(m_buf, "UInt32", base);
1114}
1116Int32
1117String::toInt32(int base) const
1118{
1119 return convertToIntType<Int32>(m_buf, "Int32", base);
1120}
1122UInt64
1123String::toUInt64(int base) const
1124{
1125 return convertToUInt64Type<UInt64>(m_buf, "UInt64", base);
1126}
1128Int64
1129String::toInt64(int base) const
1130{
1131 return convertToInt64Type<Int64>(m_buf, "Int64", base);
1132}
1134unsigned int
1136{
1137 return convertToUIntType<unsigned int>(m_buf, "unsigned int", base);
1138}
1140int
1141String::toInt(int base) const
1142{
1143 return convertToIntType<int>(m_buf, "int", base);
1144}
1147String::tokenize(const char* delims, EReturnDelimitersFlag returnDelimitersAsTokens, EEmptyTokenReturnFlag returnEmptyTokens) const
1148{
1149 StringArray ra;
1150 if (empty())
1151 {
1152 return ra;
1153 }
1154 if (delims == 0)
1155 {
1156 ra.append(*this);
1157 return ra;
1158 }
1159 // Don't need to check m_buf for NULL, because if length() == 0,
1160 // this code won't be executed.
1161 char* pstr = m_buf->data();
1162 AutoPtrVec<char> data(new char[m_buf->length()+1]);
1163 data[0] = 0;
1164 int i = 0;
1165 bool last_was_delim = false;
1166 while (*pstr)
1167 {
1168 if (String::strchr(delims, *pstr))
1169 {
1170 if (data[0] != 0)
1171 {
1172 ra.append(String(data.get()));
1173 data[0] = 0;
1174 }
1175 if ( (returnEmptyTokens == E_RETURN_EMPTY_TOKENS) && last_was_delim )
1176 {
1177 ra.append(String());
1178 }
1179 if ( returnDelimitersAsTokens == E_RETURN_DELIMITERS || returnDelimitersAsTokens == E_RETURN_TOKENS )
1180 {
1181 ra.append(String(*pstr));
1182 }
1183 i = 0;
1184 last_was_delim = true;
1185 }
1186 else
1187 {
1188 last_was_delim = false;
1189 data[i++] = *pstr;
1190 data[i] = 0;
1191 }
1192 pstr++;
1193 }
1194 if (data[0] != 0)
1195 {
1196 ra.append(String(data.get()));
1197 }
1198 return ra;
1199}
1200
1202#ifdef BLOCXX_HAVE_STRTOLL
1203long long int
1204String::strtoll(const char* nptr, char** endptr, int base)
1205{
1206 return ::strtoll(nptr, endptr, base);
1207}
1208#else
1209#ifndef LLONG_MAX
1210#if BLOCXX_SIZEOF_LONG_LONG_INT == 8
1211#define LLONG_MAX 9223372036854775807LL
1212#else
1213#define LLONG_MAX 2147483647LL
1214#endif
1215#define LLONG_MIN (-LLONG_MAX - 1LL)
1216#endif
1217long long int
1218String::strtoll(const char* nptr, char** endptr, int base)
1219{
1220 const char *s;
1221 long long acc, cutoff;
1222 int c;
1223 int neg, any, cutlim;
1224 // Skip white space and pick up leading +/- sign if any.
1225 // If base is 0, allow 0x for hex and 0 for octal, else
1226 // assume decimal; if base is already 16, allow 0x.
1227 s = nptr;
1228 do
1229 {
1230 c = (unsigned char) *s++;
1231 } while (isspace(c));
1232 if (c == '-')
1233 {
1234 neg = 1;
1235 c = *s++;
1236 }
1237 else
1238 {
1239 neg = 0;
1240 if (c == '+')
1241 {
1242 c = *s++;
1243 }
1244 }
1245 if ((base == 0 || base == 16)
1246 && c == '0'
1247 && (*s == 'x' || *s == 'X'))
1248 {
1249 c = s[1];
1250 s += 2;
1251 base = 16;
1252 }
1253 if (base == 0)
1254 {
1255 base = c == '0' ? 8 : 10;
1256 }
1257 // Compute the cutoff value between legal numbers and illegal
1258 // numbers. That is the largest legal value, divided by the
1259 // base. An input number that is greater than this value, if
1260 // followed by a legal input character, is too big. One that
1261 // is equal to this value may be valid or not; the limit
1262 // between valid and invalid numbers is then based on the last
1263 // digit. For instance, if the range for longs is
1264 // [-2147483648..2147483647] and the input base is 10,
1265 // cutoff will be set to 214748364 and cutlim to either
1266 // 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
1267 // a value > 214748364, or equal but the next digit is > 7 (or 8),
1268 // the number is too big, and we will return a range error.
1269 //
1270 // Set any if any `digits' consumed; make it negative to indicate
1271 // overflow.
1272 cutoff = neg ? LLONG_MIN : LLONG_MAX;
1273 cutlim = static_cast<int>(cutoff % base);
1274 cutoff /= base;
1275 if (neg)
1276 {
1277 if (cutlim > 0)
1278 {
1279 cutlim -= base;
1280 cutoff += 1;
1281 }
1282 cutlim = -cutlim;
1283 }
1284 for (acc = 0, any = 0;; c = (unsigned char) *s++)
1285 {
1286 if (isdigit(c))
1287 {
1288 c -= '0';
1289 }
1290 else if (isalpha(c))
1291 {
1292 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
1293 }
1294 else
1295 {
1296 break;
1297 }
1298 if (c >= base)
1299 {
1300 break;
1301 }
1302 if (any < 0)
1303 {
1304 continue;
1305 }
1306 if (neg)
1307 {
1308 if (acc < cutoff || acc == cutoff && c > cutlim)
1309 {
1310 any = -1;
1311 acc = LLONG_MIN;
1312 errno = ERANGE;
1313 }
1314 else
1315 {
1316 any = 1;
1317 acc *= base;
1318 acc -= c;
1319 }
1320 }
1321 else
1322 {
1323 if (acc > cutoff || acc == cutoff && c > cutlim)
1324 {
1325 any = -1;
1326 acc = LLONG_MAX;
1327 errno = ERANGE;
1328 }
1329 else
1330 {
1331 any = 1;
1332 acc *= base;
1333 acc += c;
1334 }
1335 }
1336 }
1337 if (endptr != 0)
1338 {
1339 *endptr = (char *) (any ? s - 1 : nptr);
1340 }
1341 return(acc);
1342}
1343#endif // #ifdef BLOCXX_HAVE_STRTOLL
1344
1346#ifdef BLOCXX_HAVE_STRTOULL
1347unsigned long long int
1348String::strtoull(const char* nptr, char** endptr, int base)
1349{
1350 return ::strtoull(nptr, endptr, base);
1351}
1352#else
1353#ifndef ULLONG_MAX
1354#if BLOCXX_SIZEOF_LONG_LONG_INT == 8
1355#define ULLONG_MAX 18446744073709551615ULL
1356#else
1357#define ULLONG_MAX 4294967295ULL
1358#endif
1359#endif
1360unsigned long long int
1361String::strtoull(const char* nptr, char** endptr, int base)
1362{
1363 const char *s;
1364 unsigned long long acc, cutoff, cutlim;
1365 unsigned int c;
1366 int neg, any;
1367 s = nptr;
1368 do
1369 {
1370 c = (unsigned char) *s++;
1371 } while (isspace(c));
1372 if (c == '-')
1373 {
1374 neg = 1;
1375 c = *s++;
1376 }
1377 else
1378 {
1379 neg = 0;
1380 if (c == '+')
1381 {
1382 c = *s++;
1383 }
1384 }
1385 if ((base == 0 || base == 16)
1386 && c == '0'
1387 && (*s == 'x' || *s == 'X'))
1388 {
1389 c = s[1];
1390 s += 2;
1391 base = 16;
1392 }
1393 if (base == 0)
1394 {
1395 base = c == '0' ? 8 : 10;
1396 }
1397 cutoff = ULLONG_MAX / (unsigned long long)base;
1398 cutlim = ULLONG_MAX % (unsigned long long)base;
1399 for (acc = 0, any = 0;; c = (unsigned char) *s++)
1400 {
1401 if (isdigit(c))
1402 {
1403 c -= '0';
1404 }
1405 else if (isalpha(c))
1406 {
1407 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
1408 }
1409 else
1410 {
1411 break;
1412 }
1413 if (c >= (unsigned int)base)
1414 {
1415 break;
1416 }
1417 if (any < 0)
1418 {
1419 continue;
1420 }
1421 if (acc > cutoff || acc == cutoff && c > cutlim)
1422 {
1423 any = -1;
1424 acc = ULLONG_MAX;
1425 errno = ERANGE;
1426 }
1427 else
1428 {
1429 any = 1;
1430 acc *= (unsigned long)base;
1431 acc += c;
1432 }
1433 }
1434 if (neg && any > 0)
1435 {
1436#ifdef BLOCXX_WIN32
1437#pragma warning (push)
1438#pragma warning (disable: 4146)
1439#endif
1440
1441 acc = -acc;
1442
1443#ifdef BLOCXX_WIN32
1444#pragma warning (pop)
1445#endif
1446
1447 }
1448 if (endptr != 0)
1449 {
1450 *endptr = (char *) (any ? s - 1 : nptr);
1451 }
1452 return(acc);
1453}
1454#endif // #ifdef BLOCXX_HAVE_STRTOULL
1456String
1457operator + (const String& s1, const String& s2)
1458{
1459 String rstr(s1);
1460 rstr += s2;
1461 return rstr;
1462}
1464String
1465operator + (const char* p, const String& s)
1466{
1467 String rstr(p);
1468 rstr += s;
1469 return rstr;
1470}
1472String
1473operator + (const String& s, const char* p)
1474{
1475 String rstr(s);
1476 rstr += p;
1477 return rstr;
1478}
1480String
1481operator + (char c, const String& s)
1482{
1483 String rstr(c);
1484 rstr += s;
1485 return rstr;
1486}
1488String
1489operator + (const String& s, char c)
1490{
1491 String rstr(s);
1492 rstr += String(c);
1493 return rstr;
1494}
1496ostream&
1497operator<< (ostream& ostr, const String& arg)
1498{
1499 ostr.write(arg.c_str(), arg.length());
1500 return ostr;
1501}
1503// static
1504String
1506{
1507 StringBuffer rv(80);
1508 rv.getLine(is);
1509 return rv.releaseString();
1510}
1512// STATIC
1513const char*
1514String::strchr(const char* theStr, int c)
1515{
1516 const char* tmpChar = theStr;
1517 for (; *tmpChar && *tmpChar != c; tmpChar++)
1518 {
1519 // empty
1520 }
1521 return ((*tmpChar) == c ? tmpChar : 0);
1522}
1523
1524} // end namespace BLOCXX_NAMESPACE
1525
#define BLOCXX_ASSERT(CON)
BLOCXX_ASSERT works similar to the assert() macro, but instead of calling abort(),...
Definition Assertion.hpp:57
#define BLOCXX_DEFINE_EXCEPTION_WITH_ID(NAME)
Define a new exception class named <NAME>Exception that derives from Exception.
#define BLOCXX_THROW(exType, msg)
Throw an exception using FILE and LINE.
std::vector< char > & m_buf
#define LLONG_MAX
Definition String.cpp:1213
#define SNPRINTF
Definition String.cpp:71
#define ULLONG_MAX
Definition String.cpp:1357
#define LLONG_MIN
Definition String.cpp:1215
Array<> wraps std::vector<> in COWReference<> adding ref counting and copy on write capability.
Definition ArrayFwd.hpp:46
void append(const T &x)
Append an element to the end of the Array.
size_type size() const
The AutoPtrVec class provides a simple class for smart pointers to a dynamically allocated array of o...
Definition AutoPtr.hpp:185
The Bool class is an abstraction for the boolean data type.
Definition Bool.hpp:57
The Char16 class is an abstraction for a double byte character.
Definition Char16.hpp:57
const char * c_str() const
Definition Format.cpp:55
ByteBuf(const ByteBuf &arg)
Definition String.cpp:102
ByteBuf & operator=(const ByteBuf &arg)
Definition String.cpp:117
ByteBuf(AutoPtrVec< char > &s, size_t len)
Definition String.cpp:110
const char * getLine(std::istream &is, bool resetBuffer=true)
Fill this StringBuffer object with the next line from the given input stream.
This String class is an abstract data type that represents as NULL terminated string of characters.
Definition String.hpp:67
bool equalsIgnoreCase(const String &arg) const
Determine if another String object is equal to this String object, ignoring case in the comparision.
Definition String.cpp:529
const char * c_str() const
Definition String.cpp:905
String & operator=(const String &arg)
Assignment operator.
Definition String.cpp:898
void swap(String &x)
Swap this instance with another.
Definition String.cpp:339
String & concat(const char *arg)
Append a C string to this String object.
Definition String.cpp:442
String & erase()
Delete all the characters of the string.
Definition String.cpp:824
static String getLine(std::istream &istr)
Reads from in input stream until a newline is encountered.
Definition String.cpp:1505
unsigned int toUnsignedInt(int base=10) const
Definition String.cpp:1135
int compareToIgnoreCase(const String &arg) const
Compare another string with this one ignoring case.
Definition String.cpp:435
~String()
Destroy this String object.
Definition String.cpp:334
UInt32 toUInt32(int base=10) const
Definition String.cpp:1111
static unsigned long long int strtoull(const char *nptr, char **endptr, int base)
Convert a null terminated string to an unsigned 64 bit value.
Definition String.cpp:1361
String()
Create a new String object with a length of 0.
Definition String.cpp:139
bool isSpaces() const
Definition String.cpp:729
UInt32 hashCode() const
Definition String.cpp:535
size_t length() const
Definition String.cpp:354
String toString() const
Definition String.cpp:948
String substring(size_t beginIndex, size_t length=npos) const
Create another String object that is comprised of a substring of this String object.
Definition String.cpp:698
size_t size() const
Definition String.hpp:227
int format(const char *fmt,...)
Format this string according to the given format and variable argument list (printf style)
Definition String.cpp:369
UInt8 toUInt8(int base=10) const
Definition String.cpp:1087
int toInt(int base=10) const
Definition String.cpp:1141
bool equals(const String &arg) const
Determine if another String object is equal to this String object.
Definition String.cpp:517
static const char * strchr(const char *theStr, int c)
Find the first occurrence of a character in a null terminated string.
Definition String.cpp:1514
Real64 toReal64() const
Definition String.cpp:1007
Char16 toChar16() const BLOCXX_DEPRECATED
DEPRECATED in favor of Char16::Char16(const String&) in 3.1.0.
Definition String.cpp:966
String & toLowerCase()
Convert this String object to lower case characters.
Definition String.cpp:849
void writeObject(std::streambuf &ostrm) const
Write this String object to the given ostream.
Definition String.cpp:887
char * allocateCString() const
Create a null terminated string that contains the contents of this String.
Definition String.cpp:345
String & trim()
Strip all leading and trailing space characters (as defined by the C function isspace()) from this St...
Definition String.cpp:790
StringArray tokenize(const char *delims=" \n\r\t\v", EReturnDelimitersFlag returnDelimitersAsTokens=E_DISCARD_DELIMITERS, EEmptyTokenReturnFlag returnEmptyTokens=E_SKIP_EMPTY_TOKENS) const
Tokenize this String object using the given delimeters.
Definition String.cpp:1147
Int32 toInt32(int base=10) const
Definition String.cpp:1117
Int64 toInt64(int base=10) const
Definition String.cpp:1129
bool startsWith(const char *arg, EIgnoreCaseFlag ignoreCase=E_CASE_SENSITIVE) const
Determine if this String object starts with a given substring.
Definition String.cpp:672
Int16 toInt16(int base=10) const
Definition String.cpp:1105
size_t indexOf(char ch, size_t fromIndex=0) const
Find the first occurence of a given character in this String object.
Definition String.cpp:556
UInt16 toUInt16(int base=10) const
Definition String.cpp:1099
UInt64 toUInt64(int base=10) const
Definition String.cpp:1123
String & rtrim()
Strip all trailing space characters (as defined by the C function isspace()) from this String object.
Definition String.cpp:764
size_t UTF8Length() const
If the string is not valid UTF-8, then the result of this function is undefined.
Definition String.cpp:360
static const size_t npos
Definition String.hpp:742
size_t lastIndexOf(char ch, size_t fromIndex=npos) const
Find the last occurence of a character in this String object.
Definition String.cpp:603
static long long int strtoll(const char *nptr, char **endptr, int base)
Convert a null terminated string to an signed 64 bit value.
Definition String.cpp:1218
int compareTo(const String &arg) const
Compare another String object with this one.
Definition String.cpp:418
Int8 toInt8(int base=10) const
Definition String.cpp:1093
String & toUpperCase()
Convert this String object to upper case characters.
Definition String.cpp:863
char charAt(size_t ndx) const
Get the character at a specified index.
Definition String.cpp:401
Real32 toReal32() const
Definition String.cpp:997
const char & operator[](size_t ndx) const
Operator [].
Definition String.cpp:919
bool endsWith(const char *arg, EIgnoreCaseFlag ignoreCase=E_CASE_SENSITIVE) const
Determine if this String object ends with given C string.
Definition String.cpp:487
String & ltrim()
Strip all leading space characters (as defined by the C function isspace()) from this String object.
Definition String.cpp:744
void readObject(std::streambuf &istrm)
Read this String object from the given istream.
Definition String.cpp:876
void readLen(std::streambuf &istrm, UInt32 &len)
void read(std::streambuf &istrm, void *dataIn, size_t dataInLen)
void write(std::streambuf &ostrm, void const *dataOut, size_t dataOutLen)
void writeLen(std::streambuf &ostrm, UInt32 len)
String toUpperCase(const char *input)
Convert the UTF-8 string to upper case and return the result.
BLOCXX_COMMON_API int compareToIgnoreCase(const char *str1, const char *str2)
Compares 2 UTF-8 strings, ignoring any case differences as defined by the Unicode spec CaseFolding....
bool toUpperCaseInPlace(char *input)
Convert the UTF-8 string to upper case.
String toLowerCase(const char *input)
Convert the UTF-8 string to lower case and return the result.
size_t charCount(const char *utf8str)
Count the number of UTF-8 chars in the string.
bool toLowerCaseInPlace(char *input)
Convert the UTF-8 string to lower case.
Taken from RFC 1321.
Char16 operator+(const Char16 &arg1, const Char16 &arg2)
Definition Char16.hpp:316
unsigned char UInt8
Definition Types.hpp:66
signed char Int8
Definition Types.hpp:67
unsigned long long int(* strtoullfp_t)(const char *, char **, int)
Definition String.cpp:1059
static int strncmpi(const char *s1, const char *s2, size_t n)
Definition String.cpp:85
static T convertToUIntType(const String::buf_t &m_buf, const char *msg, int base)
Definition String.cpp:1063
static T convertToInt64Type(const String::buf_t &m_buf, const char *msg, int base)
Definition String.cpp:1081
unsigned long int(* strtoulfp_t)(const char *, char **, int)
Definition String.cpp:1057
long long int(* strtollfp_t)(const char *, char **, int)
Definition String.cpp:1060
long int(* strtolfp_t)(const char *, char **, int)
Definition String.cpp:1058
static char nullChar
Definition String.cpp:932
static const char cnullChar
Definition String.cpp:917
static T doConvertToIntType(const String::buf_t &m_buf, const char *type, FP fp, int base)
Definition String.cpp:1035
ostream & operator<<(ostream &ostrm, const Bool &arg)
Definition Bool.cpp:77
static T convertToUInt64Type(const String::buf_t &m_buf, const char *msg, int base)
Definition String.cpp:1075
static void throwStringConversion(const String::buf_t &m_buf, const char *type)
Definition String.cpp:954
static T convertToIntType(const String::buf_t &m_buf, const char *msg, int base)
Definition String.cpp:1069
static T convertToRealType(const String::buf_t &m_buf, const char *type, FP fp)
Definition String.cpp:976