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
104 , m_len(arg.m_len)
105 , m_buf(new char[m_len+1])
106 {
107 strcpy(m_buf, arg.m_buf);
108 }
109
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}
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
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}
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
208 m_buf(NULL)
209{
210 OStringStream ss(33);
211 ss << val;
212 m_buf = new ByteBuf(ss.c_str());
213}
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.
226 ss << val;
227 m_buf = new ByteBuf(ss.c_str());
228#endif
229}
231// decimal digits = ceiling((bits)*ln(2)/ln(10))
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}
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}
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}
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
419{
420 return compareTo(arg.c_str());
421}
423int
425{
426 const char* lhs = "";
427 if (m_buf)
428 {
429 lhs = m_buf->data();
430 }
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
479{
480 return (m_buf
481 && m_buf->length()
482 && m_buf->data()[m_buf->length()-1] == arg);
483}
484
486bool
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)
507 : (::strcmp(m_buf->data()+ndx, arg) == 0);
508}
510bool
511String::equals(const char* arg) const
512{
513 return(compareTo(arg) == 0);
514}
516bool
518{
519 return equals(arg.c_str());
520}
522bool
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 {
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
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
664{
665 return (m_buf
666 && m_buf->length()
667 && m_buf->data()[0] == arg);
668}
669
671bool
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.
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
877{
878 UInt32 len;
880 AutoPtrVec<char> bfr(new char[len+1]);
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 {
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&
920{
921#ifdef BLOCXX_DEBUG
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
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
1067template <typename T>
1068static inline
1073template <typename T>
1074static inline
1079template <typename T>
1080static inline
1086UInt8
1088{
1089 return convertToUIntType<UInt8>(m_buf, "UInt8", base);
1090}
1092Int8
1094{
1095 return convertToIntType<Int8>(m_buf, "Int8", base);
1096}
1098UInt16
1100{
1101 return convertToUIntType<UInt16>(m_buf, "UInt16", base);
1102}
1104Int16
1106{
1107 return convertToIntType<Int16>(m_buf, "Int16", base);
1108}
1110UInt32
1112{
1113 return convertToUIntType<UInt32>(m_buf, "UInt32", base);
1114}
1116Int32
1118{
1119 return convertToIntType<Int32>(m_buf, "Int32", base);
1120}
1122UInt64
1124{
1125 return convertToUInt64Type<UInt64>(m_buf, "UInt64", base);
1126}
1128Int64
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
1142{
1143 return convertToIntType<int>(m_buf, "int", base);
1144}
1148{
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 }
1176 {
1177 ra.append(String());
1178 }
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.
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 {
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
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 Array.hpp:66
void append(const T &x)
Append an element to the end of the Array.
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
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
bool operator==(const Array< T > &x, const Array< T > &y)
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