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"
43 #include "blocxx/StringStream.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"
50 #include "blocxx/ExceptionIds.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 
74 namespace BLOCXX_NAMESPACE
75 {
76 
77 using std::istream;
78 using std::ostream;
79 using std::streambuf;
80 
82 
84 static inline int
85 strncmpi(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 {
95 public:
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); }
130 private:
131  size_t m_len;
132  char* m_buf;
133 };
135 #if defined(BLOCXX_AIX)
136 const size_t String::npos = ~0;
137 #endif
138 
140  m_buf(0)
141 {
142 }
145  m_buf(parm.toString().m_buf)
146 {
147 }
149 String::String(const Char16& parm) :
150  m_buf(parm.toString().m_buf)
151 {
152 }
154 String::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
161 
162 String::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 }
172 String::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)
182 
183 String::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 }
193 String::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
206 
207 String::String(Int64 val) :
208  m_buf(NULL)
209 {
210  OStringStream ss(33);
211  ss << val;
212  m_buf = new ByteBuf(ss.c_str());
213 }
215 String::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))
232 String::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 }
248 String::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 }
264 String::String(const char* str) :
265  m_buf(NULL)
266 {
267  m_buf = (NULL == str) ? 0 : new ByteBuf(str);
268 }
270 String::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 }
278 String::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 }
294 String::String(const String& arg) :
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 }
318 String::String(char c) :
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 }
338 void
340 {
341  m_buf.swap(x.m_buf);
342 }
344 char*
346 {
347  size_t len = length() + 1;
348  char* str = static_cast<char*>(malloc(len));
349  ::strcpy(str, c_str());
350  return str;
351 }
353 size_t
355 {
356  return (m_buf) ? m_buf->length() : 0;
357 }
359 size_t
361 {
362  return UTF8Utils::charCount(c_str());
363 }
365 #ifdef BLOCXX_WIN32
366 #define vsnprintf _vsnprintf // stupid windoze
367 #endif
368 int
369 String::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
399 
400 char
401 String::charAt(size_t ndx) const
402 {
403  return (m_buf) ? m_buf->data()[ndx] : '\0';
404 }
406 int
407 String::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 }
417 int
418 String::compareTo(const String& arg) const
419 {
420  return compareTo(arg.c_str());
421 }
423 int
424 String::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 }
434 int
436 {
437  return compareToIgnoreCase(arg.c_str());
438 }
439 
441 String&
442 String::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 
460 String&
461 String::concat(char arg)
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 
477 bool
478 String::endsWith(char arg) const
479 {
480  return (m_buf
481  && m_buf->length()
482  && m_buf->data()[m_buf->length()-1] == arg);
483 }
484 
486 bool
487 String::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 }
510 bool
511 String::equals(const char* arg) const
512 {
513  return(compareTo(arg) == 0);
514 }
516 bool
517 String::equals(const String& arg) const
518 {
519  return equals(arg.c_str());
520 }
522 bool
523 String::equalsIgnoreCase(const char* arg) const
524 {
525  return(compareToIgnoreCase(arg) == 0);
526 }
528 bool
530 {
531  return equalsIgnoreCase(arg.c_str());
532 }
534 UInt32
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 }
555 size_t
556 String::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 }
576 size_t
577 String::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 }
602 size_t
603 String::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 }
629 size_t
630 String::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 }
662 bool
663 String::startsWith(char arg) const
664 {
665  return (m_buf
666  && m_buf->length()
667  && m_buf->data()[0] == arg);
668 }
669 
671 bool
672 String::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 }
697 String
698 String::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 }
728 bool
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 }
743 String&
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 }
763 String&
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 }
789 String&
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 }
823 String&
825 {
826  m_buf = 0;
827  return *this;
828 }
830 String&
831 String::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 }
848 String&
850 {
851  if (m_buf)
852  {
854  {
855  *this = UTF8Utils::toLowerCase(m_buf->data());
856  }
857  }
858  return *this;
859 }
860 
862 String&
864 {
865  if (m_buf)
866  {
868  {
869  *this = UTF8Utils::toUpperCase(m_buf->data());
870  }
871  }
872  return *this;
873 }
875 void
876 String::readObject(streambuf & istrm)
877 {
878  UInt32 len;
879  BinarySerialization::readLen(istrm, 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 }
886 void
887 String::writeObject(streambuf & ostrm) const
888 {
889  UInt32 len = static_cast<UInt32>(length());
890  BinarySerialization::writeLen(ostrm, len);
891  if (len)
892  {
893  BinarySerialization::write(ostrm, m_buf->data(), len);
894  }
895 }
897 String&
899 {
900  m_buf = arg.m_buf;
901  return *this;
902 }
904 const char*
906 {
907  if (m_buf)
908  {
909  return m_buf->data();
910  }
911  else
912  {
913  return "";
914  }
915 }
917 static const char cnullChar = '\0';
918 const char&
919 String::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 }
932 static char nullChar = '\0';
933 char&
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 }
947 String
949 {
950  return *this;
951 }
953 static inline void
954 throwStringConversion(const String::buf_t& m_buf, const char* type)
955 {
956  BLOCXX_THROW(StringConversionException, Format("Unable to convert \"%1\" into %2", m_buf->data(), type).c_str());
957 }
959 static inline void
960 throwStringConversion(const char* str, const char* type)
961 {
962  BLOCXX_THROW(StringConversionException, Format("Unable to convert \"%1\" into %2", str, type).c_str());
963 }
965 Char16
967 {
968  if (UTF8Length() != 1)
969  {
970  throwStringConversion(c_str(), "Char16");
971  }
972  return Char16(*this);
973 }
974 template <typename T, typename FP>
975 static inline
976 T 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  {
985  throwStringConversion(m_buf, type);
986  }
987  return rv;
988  }
989  else
990  {
991  throwStringConversion("", type);
992  }
993  return T(); // to make compiler happy
994 }
996 Real32
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 }
1006 Real64
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 }
1016 bool
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 }
1033 template <typename T, typename FP, typename FPRT>
1034 static inline
1035 T 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  {
1047  throwStringConversion(m_buf, type);
1048  }
1049  return rv;
1050  }
1051  else
1052  {
1053  throwStringConversion("", type);
1054  }
1055  return T(); // to make compiler happy
1056 }
1057 typedef unsigned long int (*strtoulfp_t)(const char *, char **,int);
1058 typedef long int (*strtolfp_t)(const char *, char **,int);
1059 typedef unsigned long long int (*strtoullfp_t)(const char *, char **,int);
1060 typedef long long int (*strtollfp_t)(const char *, char **,int);
1061 template <typename T>
1062 static inline
1063 T convertToUIntType(const String::buf_t& m_buf, const char* msg, int base)
1064 {
1065  return doConvertToIntType<T, strtoulfp_t, unsigned long int>(m_buf, msg, &strtoul, base);
1066 }
1067 template <typename T>
1068 static inline
1069 T 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 }
1073 template <typename T>
1074 static inline
1075 T convertToUInt64Type(const String::buf_t& m_buf, const char* msg, int base)
1076 {
1077  return doConvertToIntType<T, strtoullfp_t, unsigned long long int>(m_buf, msg, &String::strtoull, base);
1078 }
1079 template <typename T>
1080 static inline
1081 T convertToInt64Type(const String::buf_t& m_buf, const char* msg, int base)
1082 {
1083  return doConvertToIntType<T, strtollfp_t, long long int>(m_buf, msg, &String::strtoll, base);
1084 }
1086 UInt8
1087 String::toUInt8(int base) const
1088 {
1089  return convertToUIntType<UInt8>(m_buf, "UInt8", base);
1090 }
1092 Int8
1093 String::toInt8(int base) const
1094 {
1095  return convertToIntType<Int8>(m_buf, "Int8", base);
1096 }
1098 UInt16
1099 String::toUInt16(int base) const
1100 {
1101  return convertToUIntType<UInt16>(m_buf, "UInt16", base);
1102 }
1104 Int16
1105 String::toInt16(int base) const
1106 {
1107  return convertToIntType<Int16>(m_buf, "Int16", base);
1108 }
1110 UInt32
1111 String::toUInt32(int base) const
1112 {
1113  return convertToUIntType<UInt32>(m_buf, "UInt32", base);
1114 }
1116 Int32
1117 String::toInt32(int base) const
1118 {
1119  return convertToIntType<Int32>(m_buf, "Int32", base);
1120 }
1122 UInt64
1123 String::toUInt64(int base) const
1124 {
1125  return convertToUInt64Type<UInt64>(m_buf, "UInt64", base);
1126 }
1128 Int64
1129 String::toInt64(int base) const
1130 {
1131  return convertToInt64Type<Int64>(m_buf, "Int64", base);
1132 }
1134 unsigned int
1135 String::toUnsignedInt(int base) const
1136 {
1137  return convertToUIntType<unsigned int>(m_buf, "unsigned int", base);
1138 }
1140 int
1141 String::toInt(int base) const
1142 {
1143  return convertToIntType<int>(m_buf, "int", base);
1144 }
1147 String::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
1203 long long int
1204 String::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
1217 long long int
1218 String::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
1347 unsigned long long int
1348 String::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
1360 unsigned long long int
1361 String::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
1455 
1456 String
1457 operator + (const String& s1, const String& s2)
1458 {
1459  String rstr(s1);
1460  rstr += s2;
1461  return rstr;
1462 }
1464 String
1465 operator + (const char* p, const String& s)
1466 {
1467  String rstr(p);
1468  rstr += s;
1469  return rstr;
1470 }
1472 String
1473 operator + (const String& s, const char* p)
1474 {
1475  String rstr(s);
1476  rstr += p;
1477  return rstr;
1478 }
1480 String
1481 operator + (char c, const String& s)
1482 {
1483  String rstr(c);
1484  rstr += s;
1485  return rstr;
1486 }
1488 String
1489 operator + (const String& s, char c)
1490 {
1491  String rstr(s);
1492  rstr += String(c);
1493  return rstr;
1494 }
1496 ostream&
1497 operator<< (ostream& ostr, const String& arg)
1498 {
1499  ostr.write(arg.c_str(), arg.length());
1500  return ostr;
1501 }
1503 // static
1504 String
1505 String::getLine(istream& is)
1506 {
1507  StringBuffer rv(80);
1508  rv.getLine(is);
1509  return rv.releaseString();
1510 }
1512 // STATIC
1513 const char*
1514 String::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