Evo C++ Library v0.5.1
string.h
Go to the documentation of this file.
1 // Evo C++ Library
2 /* Copyright 2019 Justin Crowell
3 Distributed under the BSD 2-Clause License -- see included file LICENSE.txt for details.
4 */
6 
7 #pragma once
8 #ifndef INCL_evo_string_h
9 #define INCL_evo_string_h
10 
11 #include "list.h"
12 #include "strscan.h"
13 
14 namespace evo {
17 
19 
53 template<class T, int PADDING=1>
54 struct StringInt : public ListBase<char,StrSizeT> {
56  typedef StrSizeT Size;
57 
58  static const int BUF_SIZE = IntegerT<T>::MAXSTRLEN + PADDING;
59 
60  char buffer[BUF_SIZE];
61 
64 
67  { }
68 
77  StringInt(T num, int base=fDEC, bool terminated=true, uint end_padding=0)
78  { set(num, base, terminated, end_padding); }
79 
85  char* data()
86  { return data_; }
87 
93  Size size() const
94  { return size_; }
95 
99  ThisType& set() {
100  data_ = NULL;
101  size_ = 0;
102  return *this;
103  }
104 
114  char* set(T num, int base=fDEC, bool terminated=true, uint end_padding=0) {
115  assert( base >= 2 );
116  assert( base <= 36 );
117  assert( end_padding <= BUF_SIZE - IntegerT<T>::MAXSTRLEN ); // Must have room for formatting and padding
118  char* endptr = buffer + BUF_SIZE - end_padding;
119  if (terminated) {
120  assert( BUF_SIZE > IntegerT<T>::MAXSTRLEN ); // Terminator requires padding > 0
121  *--endptr = '\0';
122  }
123  if (IsSigned<T>::value)
124  size_ = impl::fnum(endptr, num, base);
125  else
126  size_ = impl::fnumu(endptr, num, base);
127  data_ = endptr - size_;
128  return data_;
129  }
130 
139  ThisType& add(const char* data, Size size) {
140  assert( data != NULL );
141  assert( data_ != NULL );
142  memcpy(data_ + size_, data, size);
143  size_ += size;
144  return *this;
145  }
146 
155  char* addnew(Size size) {
156  assert( data_ != NULL );
157  char* p = data_ + size_;
158  size_ += size;
159  return p;
160  }
161 
162 private:
163  // Disable copying
165  StringInt& operator=(StringInt&);
166 };
167 
169 
203 template<class T=double, int PADDING=1>
204 struct StringFlt : public ListBase<char,StrSizeT> {
206  typedef StrSizeT Size;
207 
208  static const int BUF_SIZE = FloatT<T>::MAXDIGITS_AUTO + PADDING;
209 
210  char buffer[BUF_SIZE];
211 
214 
218  struct NumInfo {
219  Size size;
220  T number;
221  int exponent;
222  int precision;
223  bool terminated;
224 
227  { memset(this, 0, sizeof(NumInfo)); }
228 
235  char* format(char* ptr) {
236  const ulong len = impl::fnumf(ptr, number, exponent, precision);
237  if (terminated)
238  ptr[len] = '\0';
239  assert( len < IntegerT<Size>::MAX );
240  size = (Size)len;
241  return ptr;
242  }
243  };
244 
246  StringFlt() : dbuffer_(NULL), dbuffer_size_(0)
247  { }
248 
256  StringFlt(T num, int precision=fPREC_AUTO, bool terminated=true) : dbuffer_(NULL), dbuffer_size_(0)
257  { set(num, precision, terminated); }
258 
261  { free(); }
262 
268  char* data()
269  { return data_; }
270 
276  Size size() const
277  { return size_; }
278 
282  ThisType& set() {
283  data_ = NULL;
284  size_ = 0;
285  return *this;
286  }
287 
302  char* set(T num, int precision=fPREC_AUTO, bool terminated=true, NumInfo* info=NULL) {
303  ulong len;
304  int exp = 0;
305  if (precision < 0) {
306  // fPREC_AUTO
307  data_ = buffer;
308  num = FloatT<T>::fexp10(exp, num);
309  len = impl::fnumfe(data_, num, exp, false);
310  assert( len <= (ulong)BUF_SIZE );
311  } else {
312  // Explicit precision may require allocating memory
313  num = FloatT<T>::fexp10(exp, impl::fnumf_weight(num, precision));
314  ulong maxsize = (ulong)FloatT<T>::maxdigits_prec(exp, precision) + PADDING;
315  assert( maxsize > 0 );
316  assert( maxsize < IntegerT<Size>::MAX );
317  if (maxsize > (ulong)BUF_SIZE) {
318  if (maxsize > dbuffer_size_) {
319  if (info != NULL) {
320  // No alloc, populate info to defer formatting
321  info->size = maxsize;
322  info->number = num;
323  info->exponent = exp;
324  info->precision = precision;
325  info->terminated = terminated;
326  return NULL;
327  }
328  free();
329  assert( maxsize < IntegerT<size_t>::MAX );
330  dbuffer_ = (char*)::malloc((size_t)maxsize);
331  dbuffer_size_ = (Size)maxsize;
332  }
333  data_ = dbuffer_;
334  } else
335  data_ = buffer;
336  len = impl::fnumf(data_, num, exp, precision);
337  }
338  if (terminated) {
339  assert( PADDING > 0 ); // Terminator requires padding > 0
340  data_[len] = '\0';
341  }
342  assert( len < IntegerT<Size>::MAX );
343  size_ = (Size)len;
344  return data_;
345  }
346 
347 private:
348  // Disable copying
350  StringFlt& operator=(StringFlt&);
351 
352  // Dynamic buffer
353  char* dbuffer_;
354  Size dbuffer_size_;
355 
356  void free() {
357  if (dbuffer_ != NULL)
358  ::free(dbuffer_);
359  }
360 };
361 
363 
674 class String : public List<char,StrSizeT> {
675 public:
676  typedef String ThisType;
678  typedef String Out;
679 
682 
685  { }
686 
692  String(const String& str) : List<char,Size>(str)
693  { }
694 
700  String(const ListType& str) : List<char,Size>(str)
701  { }
702 
708  String(const ListType* str)
709  { if (str != NULL) set(*str); }
710 
718  String(const ListType& str, Key index, Key size=ALL) : List<char,Size>(str, index, size)
719  { }
720 
729  String(const StringBase& str, Key index=0, Key size=ALL) : List<char,Size>(str, index, size)
730  { }
731 
739  String(const char* str, Size size) : List<char,Size>(str, size)
740  { }
741 
750  String(const PtrBase<char>& str, Size size) {
751  if (str.ptr_ != NULL) {
752  if (size > 0)
753  copy(str.ptr_, size);
754  else
755  setempty();
756  }
757  }
758 
765  String(const UnicodeStringBase& str)
766  { set_unicode(str.data_, str.size_); }
767 
774  String(const char* str) : List<char,Size>(str, str?(Size)strlen(str):0) {
775  #if EVO_LIST_OPT_REFTERM
776  terminated_ = true;
777  #endif
778  }
779 
787  String(const PtrBase<char>& str) {
788  if (str.ptr_ != NULL) {
789  const size_t len = strlen(str.ptr_);
790  assert( len < IntegerT<Size>::MAX );
791  copy(str.ptr_, (Size)len);
792  }
793  }
794 
795 #if defined(EVO_CPP11)
796 
803  String(const char16_t* str, Size size, UtfMode mode=umREPLACE_INVALID) {
804  set_unicode(str, size, mode);
805  }
806 
813  String(const char16_t* str, UtfMode mode=umREPLACE_INVALID) {
814  set_unicode(str, mode);
815  }
816 
820  String(const std::initializer_list<char>& init) {
821  assert( init.size() < IntegerT<Size>::MAX );
822  ListType::advAdd((Size)init.size());
823  char* p = data_;
824  for (auto ch : init)
825  *(p++) = ch;
826  }
827 
831  String(String&& src) : List<char>(std::move(src)) {
832  }
833 
839  List<char>::operator=(std::move(src));
840  return *this;
841  }
842 
849  String& operator=(const char16_t* str) {
850  set_unicode(str);
851  return *this;
852  }
853 #endif
854 
856  const String& asconst() const {
857  return *this;
858  }
859 
860  // SET
861 
868  String& operator=(const String& str)
869  { set(str); return *this; }
870 
877  String& operator=(const ListType& str)
878  { set(str); return *this; }
879 
886  String& operator=(const ListType* str) {
887  if (str != NULL)
888  set(*str);
889  else
890  set();
891  return *this;
892  }
893 
901  String& operator=(const StringBase& data)
902  { ListType::operator=(data); return *this; }
903 
911  String& operator=(const char* str) {
912  if (str == NULL)
913  set();
914  else
915  ref(str, (Size)strlen(str), true);
916  return *this;
917  }
918 
928  if (str.ptr_ == NULL)
929  set();
930  else
931  copy(str.ptr_, (Size)strlen(str.ptr_));
932  return *this;
933  }
934 
941  template<class T>
943  assert( str.size_ < IntegerT<Size>::MAX );
944  set_unicode(str.data_, str.size_);
945  return *this;
946  }
947 
958  { set(); return *this; }
959 
970  { setempty(); return *this; }
971 
983  { ListType::setempty(); return *this; }
984 
995  String& set()
996  { ListType::set(); return *this; }
997 
1004  String& set(const ListType& str)
1005  { ListType::set(str); return *this; }
1006 
1015  String& set(const ListType& str, Key index, Key size=ALL)
1016  { ListType::set(str, index, size); return *this; }
1017 
1027  String& set(const StringBase& data, Key index=0, Key size=ALL)
1028  { ListType::set(data, index, size); return *this; }
1029 
1038  String& set(const char* str, Size size)
1039  { ListType::set(str, size); return *this; }
1040 
1049  String& set(const PtrBase<char>& str, Size size) {
1050  if (str.ptr_ == NULL)
1051  ListType::set();
1052  else
1053  ListType::copy(str.ptr_, size);
1054  return *this;
1055  }
1056 
1064  String& set(const char* str) {
1065  if (str == NULL)
1066  ListType::set();
1067  else
1068  ref(str, (Size)strlen(str), true);
1069  return *this;
1070  }
1071 
1079  String& set(const PtrBase<char>& str) {
1080  if (str.ptr_ == NULL)
1081  ListType::set();
1082  else
1083  ListType::copy(str.ptr_, (Size)strlen(str.ptr_));
1084  return *this;
1085  }
1086 
1097  String& set2(const ListType& str, Key index1, Key index2)
1098  { ListType::set2(str, index1, index2); return *this; }
1099 
1109  String& set2(const StringBase& data, Key index1, Key index2)
1110  { ListType::set2(data, index1, index2); return *this; }
1111 
1117  String& setn(int num, int base=fDEC)
1118  { setnum(num, base); return *this; }
1119 
1125  String& setn(long num, int base=fDEC)
1126  { setnum(num, base); return *this; }
1127 
1133  String& setn(longl num, int base=fDEC)
1134  { setnum(num, base); return *this; }
1135 
1141  String& setn(uint num, int base=fDEC)
1142  { setnumu(num, base); return *this; }
1143 
1149  String& setn(ulong num, int base=fDEC)
1150  { setnumu(num, base); return *this; }
1151 
1157  String& setn(ulongl num, int base=fDEC)
1158  { setnumu(num, base); return *this; }
1159 
1165  String& setn(float num, int precision=fPREC_AUTO)
1166  { setnumf(num, precision); return *this; }
1167 
1173  String& setn(double num, int precision=fPREC_AUTO)
1174  { setnumf(num, precision); return *this; }
1175 
1181  String& setn(ldouble num, int precision=fPREC_AUTO)
1182  { setnumf(num, precision); return *this; }
1183 
1196  bool set_unicode(const wchar16* str, Size size, UtfMode mode=umREPLACE_INVALID) {
1197  if (str == NULL) {
1198  set();
1199  } else {
1200  clear();
1201  const wchar16* p = str;
1202  const wchar16* end = str + size;
1203  ulong bytes = utf16_to8(p, end, NULL, 0, mode);
1204  if (bytes == END)
1205  return false;
1206  if (bytes > 0) {
1207  assert( bytes < IntegerT<Size>::MAX );
1208  char* buf = advWrite(bytes + 1);
1209  bytes = utf16_to8(str, end, buf, bytes, mode);
1210  advWriteDone((Size)bytes);
1211  }
1212  }
1213  return true;
1214  }
1215 
1227  bool set_unicode(const wchar16* str, UtfMode mode=umREPLACE_INVALID) {
1228  return set_unicode(str, utf16_strlen(str), mode);
1229  }
1230 
1231 #if defined(EVO_CPP11)
1232 
1233  bool set_unicode(const char16_t* str, Size size, UtfMode mode=umREPLACE_INVALID) {
1234  static_assert( sizeof(char16_t) == sizeof(wchar16), "ERROR: char16_t type larger than 16 bits" );
1235  return set_unicode((const wchar16*)str, size, mode);
1236  }
1237 
1239  bool set_unicode(const char16_t* str, UtfMode mode=umREPLACE_INVALID) {
1240  static_assert( sizeof(char16_t) == sizeof(wchar16), "ERROR: char16_t type larger than 16 bits" );
1241  return set_unicode((const wchar16*)str, mode);
1242  }
1243 #endif
1244 
1245 #if defined(_WIN32) || defined(DOXYGEN)
1246 
1255  String& set_win32(const WCHAR* str, int size) {
1256  if (str == NULL) {
1257  set();
1258  } else if (size <= 0) {
1259  setempty();
1260  } else {
1261  const int newsize = ::WideCharToMultiByte(CP_UTF8, 0, str, size, NULL, 0, NULL, NULL);
1262  if (newsize > 0) {
1263  clear();
1264  char* buf = advBuffer(newsize+1);
1265  int written = ::WideCharToMultiByte(CP_UTF8, 0, str, size, buf, newsize, NULL, NULL);
1266  if (written >= 0) {
1267  buf[written] = '\0';
1268  assert( written < IntegerT<Size>::MAX );
1269  advSize(written);
1270  }
1271  } else
1272  set();
1273  }
1274  return *this;
1275  }
1276 
1285  String& set_win32(const WCHAR* str) {
1286  if (str == NULL) {
1287  set();
1288  } else if (*str == 0) {
1289  setempty();
1290  } else {
1291  const int newsize = ::WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
1292  if (newsize > 0) {
1293  clear();
1294  int written = ::WideCharToMultiByte(CP_UTF8, 0, str, -1, advBuffer(newsize), newsize, NULL, NULL);
1295  if (written > 0)
1296  --written; // chop terminator
1297  assert( written < IntegerT<Size>::MAX );
1298  advSize(written);
1299  } else
1300  set();
1301  }
1302  return *this;
1303  }
1304 #endif
1305 
1317  template<class StringT>
1318  bool token(StringT& value, char delim) {
1319  if (size_ > 0) {
1320  const char* ptr = (char*)memchr(data_, delim, size_);
1321  if (ptr != NULL) {
1322  Key i = (Key)(ptr - data_);
1323  value.set(data_, i);
1324  ++i;
1325  data_ += i;
1326  size_ -= i;
1327  return true;
1328  }
1329  value.set(data_, size_);
1330  clear();
1331  return true;
1332  }
1333  value.set();
1334  return false;
1335  }
1336 
1348  template<class StringT>
1349  bool tokenr(StringT& value, char delim) {
1350  if (size_ > 0) {
1351  #if defined(EVO_GLIBC_MEMRCHR)
1352  const char* ptr = (char*)memrchr(data_, delim, size_);
1353  if (ptr != NULL) {
1354  const Key i = (Key)(ptr - data_);
1355  const Size len = size_ - i;
1356  value.set(data_ + i + 1, len - 1);
1357  size_ -= len;
1358  return true;
1359  }
1360  #else
1361  for (Key i=size_; i > 0; ) {
1362  if (data_[--i] == delim) {
1363  Size len = size_ - i;
1364  value.set(data_ + i + 1, len - 1);
1365  size_ -= len;
1366  return true;
1367  }
1368  }
1369  #endif
1370  value.set(data_, size_);
1371  clear();
1372  return true;
1373  }
1374  value.set();
1375  return false;
1376  }
1377 
1391  template<class StringT>
1392  bool token_any(StringT& value, Char& found_delim, const char* delims, Size count) {
1393  assert( count > 0 );
1394  if (size_ > 0) {
1395  Size j;
1396  for (Key i=0; i < size_; ++i) {
1397  for (j=0; j < count; ++j) {
1398  if (data_[i] == delims[j]) {
1399  value.set(data_, i);
1400  found_delim = data_[i];
1401  ++i;
1402  data_ += i;
1403  size_ -= i;
1404  return true;
1405  }
1406  }
1407  }
1408  value.set(data_, size_);
1409  found_delim.set();
1410  clear();
1411  return true;
1412  }
1413  value.set();
1414  found_delim.set();
1415  return false;
1416  }
1417 
1431  template<class StringT>
1432  bool tokenr_any(StringT& value, Char& found_delim, const char* delims, Size count) {
1433  assert( count > 0 );
1434  if (size_ > 0) {
1435  Size j;
1436  for (Key i=size_; i > 0; ) {
1437  --i;
1438  for (j=0; j < count; ++j) {
1439  if (data_[i] == delims[j]) {
1440  Size len = size_ - i;
1441  value.set(data_ + i + 1, len - 1);
1442  found_delim = data_[i];
1443  size_ -= len;
1444  return true;
1445  }
1446  }
1447  }
1448  value.set(data_, size_);
1449  found_delim.set();
1450  clear();
1451  return true;
1452  }
1453  value.set();
1454  found_delim.set();
1455  return false;
1456  }
1457 
1466  template<class StringT>
1467  bool token_line(StringT& line) {
1468  const char* NEWLINE_CHARS = "\n\r";
1469  Size i = findany(NEWLINE_CHARS, 2);
1470  if (i == END) {
1471  if (size_ > 0) {
1472  line.set(data_, size_);
1473  setempty();
1474  return true;
1475  }
1476  line.set();
1477  return false;
1478  }
1479  line.set(data_, i);
1480 
1481  if (++i < size_) {
1482  char ch1 = data_[i - 1];
1483  char ch2 = data_[i];
1484  if ((ch1 == '\n' && ch2 == '\r') || (ch1 == '\r' && ch2 == '\n'))
1485  ++i;
1486  }
1487  data_ += i;
1488  size_ -= i;
1489  return true;
1490  }
1491 
1500  template<class StringT>
1501  bool tokenr_line(StringT& line) {
1502  const char* NEWLINE_CHARS = "\n\r";
1503  Size i = findanyr(NEWLINE_CHARS, 2);
1504  if (i == END) {
1505  if (size_ > 0) {
1506  line.set(data_, size_);
1507  setempty();
1508  return true;
1509  }
1510  line.set();
1511  return false;
1512  }
1513  line.set(data_ + i + 1, size_ - i - 1);
1514 
1515  if (i > 1) {
1516  char ch1 = data_[i - 1];
1517  char ch2 = data_[i];
1518  if ((ch1 == '\n' && ch2 == '\r') || (ch1 == '\r' && ch2 == '\n'))
1519  --i;
1520  }
1521  size_ = i;
1522  return true;
1523  }
1524 
1525  // INFO
1526 
1533  const char* data() const
1534  { return data_; }
1535 
1561  const char* cstr(String& buffer) const
1562  { return (size_ > 0 ? buffer.set(*this).cstr() : ""); }
1563 
1571  const char* cstr() {
1572  const char* result = "";
1573  if (size_ > 0) {
1574  // Not empty
1575  if (buf_.ptr != NULL) {
1576  assert( buf_.header != NULL );
1577  assert( data_ >= buf_.ptr );
1578  assert( data_ < buf_.ptr+buf_.header->used );
1579  if (size_ + (data_-buf_.ptr) < buf_.header->used)
1580  // End is sliced off, jump to add terminator
1581  goto add_term;
1582  }
1583 
1584  // End not sliced
1585  #if EVO_LIST_OPT_REFTERM
1586  if (terminated_) {
1587  // Already terminated
1588  result = data_;
1589  } else
1590  #endif
1591  {
1592  // Add temporary terminator
1593  add_term:
1594  reserve(1);
1595  data_[size_] = '\0';
1596  result = data_;
1597  }
1598  }
1599  return result;
1600  }
1601 
1607  const char* cstrM() const
1608  { return (size_ > 0 ? const_cast<String*>(this)->cstr() : ""); }
1609 
1610  // COMPARE
1611 
1612  using ListType::compare;
1613 
1619  template<class T>
1620  int compare(const ListBase<wchar16,T>& str) {
1621  assert( str.size_ < ULong::MAX );
1622  return -utf16_compare8(str.data_, str.size_, data_, size_);
1623  }
1624 
1625  using ListType::operator==;
1626  using ListType::operator!=;
1627 
1632  bool operator==(const String& str) const
1633  { return ListType::operator==(str); }
1634 
1639  bool operator==(const char* str) const {
1640  return (utf8_compare(data_, size_, str) == 0);
1641  }
1642 
1648  template<class T>
1649  bool operator==(const ListBase<wchar16,T>& str) {
1650  assert( str.size_ < ULong::MAX );
1651  return (utf16_compare8(str.data_, str.size_, data_, size_) == 0);
1652  }
1653 
1658  bool operator!=(const String& str) const
1659  { return ListType::operator!=(str); }
1660 
1665  bool operator!=(const char* str) const {
1666  return (utf8_compare(data_, size_, str) != 0);
1667  }
1668 
1674  template<class T>
1675  bool operator!=(const ListBase<wchar16,T>& str) {
1676  assert( str.size_ < ULong::MAX );
1677  return (utf16_compare8(str.data_, str.size_, data_, size_) != 0);
1678  }
1679 
1680  using ListType::starts;
1681  using ListType::ends;
1682 
1687  bool starts(char ch) const
1688  { return ListType::starts(ch); }
1689 
1694  bool ends(char ch) const
1695  { return ListType::ends(ch); }
1696 
1697  // FIND
1698 
1705  Iter cbegin() const
1706  { return Iter(*this); }
1707 
1715  Iter cend() const
1716  { return Iter(); }
1717 
1726  { return IterM(*this); }
1727 
1734  Iter begin() const
1735  { return Iter(*this); }
1736 
1745  { return IterM(); }
1746 
1754  Iter end() const
1755  { return Iter(); }
1756 
1761  Key find(char ch) const {
1762  if (size_ > 0) {
1763  const char* ptr = (char*)memchr(data_, ch, size_);
1764  if (ptr != NULL)
1765  return (Key)(ptr - data_);
1766  }
1767  return NONE;
1768  }
1769 
1779  Key find(char ch, Key start, Key end=END) const {
1780  if (start < size_) {
1781  if (end > size_)
1782  end = size_;
1783  if (start < end) {
1784  const char* ptr = (char*)memchr(data_ + start, ch, end - start);
1785  if (ptr != NULL)
1786  return (Key)(ptr - data_);
1787  }
1788  }
1789  return NONE;
1790  }
1791 
1803  Key find(const char* pattern, uint pattern_size, Key start=0, Key end=END) const {
1804  if (start < size_ && start < end) {
1805  assert( pattern != NULL );
1806  if (end > size_)
1807  end = size_;
1808  return impl::string_search(pattern, pattern_size, data_ + start, end - start, start);
1809  }
1810  return NONE;
1811  }
1812 
1824  Key find(StringSearchAlg alg, const char* pattern, uint pattern_size, Key start=0, Key end=END) const {
1825  if (start < size_ && start < end) {
1826  assert( pattern != NULL );
1827  if (end > size_)
1828  end = size_;
1829  return impl::string_search(alg, pattern, pattern_size, data_ + start, end - start, start);
1830  }
1831  return NONE;
1832  }
1833 
1844  Key find(const StringBase& pattern, Key start=0, Key end=END) const {
1845  if (start < size_ && start < end) {
1846  if (end > size_)
1847  end = size_;
1848  return impl::string_search(pattern.data_, pattern.size_, data_ + start, end - start, start);
1849  }
1850  return NONE;
1851  }
1852 
1863  Key find(StringSearchAlg alg, const StringBase& pattern, Key start=0, Key end=END) const {
1864  if (start < size_ && start < end) {
1865  if (end > size_)
1866  end = size_;
1867  return impl::string_search(alg, pattern.data_, pattern.size_, data_ + start, end - start, start);
1868  }
1869  return NONE;
1870  }
1871 
1879  Key findr(char ch) const {
1880  #if !defined(EVO_NO_MEMRCHR) && defined(EVO_GLIBC_MEMRCHR)
1881  if (size_ > 0) {
1882  const char* ptr = (char*)memrchr(data_, ch, size_);
1883  if (ptr != NULL)
1884  return (Key)(ptr - data_);
1885  }
1886  #else
1887  const char* ptr = data_ + size_;
1888  while (ptr > data_)
1889  if (*--ptr == ch)
1890  return (Key)(ptr - data_);
1891  #endif
1892  return NONE;
1893  }
1894 
1904  Key findr(char ch, Key start, Key end=END) const {
1905  #if !defined(EVO_NO_MEMRCHR) && defined(EVO_GLIBC_MEMRCHR)
1906  if (start < size_) {
1907  if (end > size_)
1908  end = size_;
1909  if (start < end) {
1910  const char* ptr = (char*)memrchr(data_ + start, ch, end - start);
1911  if (ptr != NULL)
1912  return (Key)(ptr - data_);
1913  }
1914  }
1915  #else
1916  if (end > size_)
1917  end = size_;
1918  while (end>start)
1919  if (data_[--end] == ch)
1920  return end;
1921  #endif
1922  return NONE;
1923  }
1924 
1936  Key findr(const char* pattern, uint pattern_size, Key start=0, Key end=END) const {
1937  if (start < size_ && start < end) {
1938  assert( pattern != NULL );
1939  if (end > size_)
1940  end = size_;
1941  return impl::string_search_reverse(pattern, pattern_size, data_ + start, end - start, start);
1942  }
1943  return NONE;
1944  }
1945 
1957  Key findr(StringSearchAlg alg, const char* pattern, uint pattern_size, Key start=0, Key end=END) const {
1958  if (start < size_ && start < end) {
1959  assert( pattern != NULL );
1960  if (end > size_)
1961  end = size_;
1962  return impl::string_search_reverse(alg, pattern, pattern_size, data_ + start, end - start, start);
1963  }
1964  return NONE;
1965  }
1966 
1977  Key findr(const StringBase& pattern, Key start=0, Key end=END) const {
1978  if (start < size_ && start < end) {
1979  if (end > size_)
1980  end = size_;
1981  return impl::string_search_reverse(pattern.data_, pattern.size_, data_ + start, end - start, start);
1982  }
1983  return NONE;
1984  }
1985 
1996  Key findr(StringSearchAlg alg, const StringBase& pattern, Key start=0, Key end=END) const {
1997  if (start < size_ && start < end) {
1998  if (end > size_)
1999  end = size_;
2000  return impl::string_search_reverse(alg, pattern.data_, pattern.size_, data_ + start, end - start, start);
2001  }
2002  return NONE;
2003  }
2004 
2016  Key findany(const char* chars, Size count, Key start=0, Key end=END) const {
2017  if (start < size_ && start < end && count > 0) {
2018  if (end > size_)
2019  end = size_;
2020  if (count == 1) {
2021  // Special case for single char
2022  const char* ptr = (char*)memchr(data_ + start, *chars, end - start);
2023  if (ptr != NULL)
2024  return (Key)(ptr - data_);
2025  } else {
2026  const char* pend = data_ + end;
2027  const char* ptr = data_ + start;
2028  for (; ptr < pend; ++ptr)
2029  if (memchr(chars, *ptr, count) != NULL)
2030  return (Key)(ptr - data_);
2031  }
2032  }
2033  return NONE;
2034  }
2035 
2046  Key findany(const StringBase& chars, Key start=0, Key end=END) const
2047  { return findany(chars.data_, chars.size_, start, end); }
2048 
2060  Key findanyr(const char* chars, Size count, Key start=0, Key end=END) const {
2061  if (count == 1)
2062  return findr(*chars, start, end);
2063  if (start < size_ && start < end && count > 0) {
2064  if (end > size_)
2065  end = size_;
2066  const char* pstart = data_ + start;
2067  const char* ptr = data_ + end;
2068  while (ptr > pstart)
2069  if (memchr(chars, *--ptr, count) != NULL)
2070  return (Key)(ptr - data_);
2071  }
2072  return NONE;
2073  }
2074 
2085  Key findanyr(const StringBase& chars, Key start=0, Key end=END) const
2086  { return findanyr(chars.data_, chars.size_, start, end); }
2087 
2099  Key findanybut(const char* chars, Size count, Key start=0, Key end=END) const {
2100  if (start < size_ && start < end) {
2101  if (count == 0)
2102  return start;
2103  if (end > size_)
2104  end = size_;
2105  const char* pend = data_ + end;
2106  const char* ptr = data_ + start;
2107  for (; ptr < pend; ++ptr)
2108  if (memchr(chars, *ptr, count) == NULL)
2109  return (Key)(ptr - data_);
2110  }
2111  return NONE;
2112  }
2113 
2124  Key findanybut(const StringBase& chars, Key start=0, Key end=END) const
2125  { return findanybut(chars.data_, chars.size_, start, end); }
2126 
2138  Key findanybutr(const char* chars, Size count, Key start=0, Key end=END) const {
2139  if (start < size_ && start < end) {
2140  if (end > size_)
2141  end = size_;
2142  if (count == 0)
2143  return end - 1;
2144  const char* pstart = data_ + start;
2145  const char* ptr = data_ + end;
2146  while (ptr > pstart)
2147  if (memchr(chars, *--ptr, count) == NULL)
2148  return (Key)(ptr - data_);
2149  }
2150  return NONE;
2151  }
2152 
2163  Key findanybutr(const StringBase& chars, Key start=0, Key end=END) const
2164  { return findanybutr(chars.data_, chars.size_, start, end); }
2165 
2173  Key findword(Key start=0, Key end=END) const {
2174  if (start < size_ && start < end) {
2175  if (end > size_)
2176  end = size_;
2177  for (; start < end; ++start)
2178  if (ascii_breaktype(data_[start]) == cbtWORD)
2179  return start;
2180  }
2181  return NONE;
2182  }
2183 
2191  Key findwordr(Key start=0, Key end=END) const {
2192  if (start < size_ && start < end) {
2193  if (end > size_)
2194  end = size_;
2195  while (end > start)
2196  if (ascii_breaktype(data_[--end]) == cbtWORD)
2197  return end;
2198  }
2199  return NONE;
2200  }
2201 
2210  Key findnonword(Key start=0, Key end=END) const {
2211  if (start < size_ && start < end) {
2212  if (end > size_)
2213  end = size_;
2214  for (; start < end; ++start)
2215  if (ascii_breaktype(data_[start]) != cbtWORD)
2216  return start;
2217  }
2218  return NONE;
2219  }
2220 
2229  Key findnonwordr(Key start=0, Key end=END) const {
2230  if (start < size_ && start < end) {
2231  if (end > size_)
2232  end = size_;
2233  while (end > start)
2234  if (ascii_breaktype(data_[--end]) != cbtWORD)
2235  return end;
2236  }
2237  return NONE;
2238  }
2239 
2244  bool contains(char ch) const
2245  { return find(ch) != NONE; }
2246 
2252  bool contains(const char* str, Size size) const
2253  { return find(str, size) != NONE; }
2254 
2259  bool contains(const StringBase& str) const
2260  { return find(str) != NONE; }
2261 
2262  // SPLIT
2263 
2276  template<class T1,class T2>
2277  bool split(char delim, T1& left, T2& right) const {
2278  for (Key i=0; i<size_; ++i) {
2279  if (data_[i] == delim) {
2280  left.set(*this).slice(0, i);
2281  right.set(*this).slice(i+1, ALL);
2282  return true;
2283  }
2284  }
2285  left.set(*this);
2286  right.set();
2287  return false;
2288  }
2289 
2300  template<class T1>
2301  bool split(char delim, T1& left) const {
2302  for (Key i=0; i<size_; ++i) {
2303  if (data_[i] == delim) {
2304  left.set(*this).slice(0, i);
2305  return true;
2306  }
2307  }
2308  left.set(*this);
2309  return false;
2310  }
2311 
2323  template<class T2>
2324  bool split(char delim, ValNull left, T2& right) const {
2325  EVO_PARAM_UNUSED(left);
2326  for (Key i=0; i<size_; ++i) {
2327  if (data_[i] == delim) {
2328  right.set(*this).slice(i+1, ALL);
2329  return true;
2330  }
2331  }
2332  right.set();
2333  return false;
2334  }
2335 
2348  template<class T1,class T2>
2349  bool splitr(char delim, T1& left, T2& right) const {
2350  for (Key i=size_; i>0; ) {
2351  if (data_[--i] == delim) {
2352  left.set(*this).slice(0, i);
2353  right.set(*this).slice(i+1, ALL);
2354  return true;
2355  }
2356  }
2357  left.set(*this);
2358  right.set();
2359  return false;
2360  }
2361 
2372  template<class T1>
2373  bool splitr(char delim, T1& left) const {
2374  for (Key i=size_; i>0; ) {
2375  if (data_[--i] == delim) {
2376  left.set(*this).slice(0, i);
2377  return true;
2378  }
2379  }
2380  left.set(*this);
2381  return false;
2382  }
2383 
2395  template<class T2>
2396  bool splitr(char delim, ValNull left, T2& right) const {
2397  EVO_PARAM_UNUSED(left);
2398  for (Key i=size_; i>0; ) {
2399  if (data_[--i] == delim) {
2400  right.set(*this).slice(i+1, ALL);
2401  return true;
2402  }
2403  }
2404  right.set();
2405  return false;
2406  }
2407 
2408  // TRIM/STRIP
2409 
2417  char ch;
2418  while ( size_ > 0 && ((ch=data_[size_-1]) == ' ' || ch == '\t') )
2419  --size_;
2420  Size count = 0;
2421  while ( count < size_ && ((ch=data_[count]) == ' ' || ch == '\t') )
2422  ++count;
2423  triml(count);
2424  return *this;
2425  }
2426 
2433  String& strip(char ch) {
2434  while (size_ > 0 && data_[size_-1] == ch)
2435  --size_;
2436  Size count = 0;
2437  while (count < size_ && data_[count] == ch)
2438  ++count;
2439  triml(count);
2440  return *this;
2441  }
2442 
2450  char ch;
2451  Size count = 0;
2452  while ( count < size_ && ((ch=data_[count]) == ' ' || ch == '\t') )
2453  ++count;
2454  triml(count);
2455  return *this;
2456  }
2457 
2465  String& stripl(char ch, Size max=ALL) {
2466  Size count = 0;
2467  while (count < size_ && data_[count] == ch && count < max)
2468  ++count;
2469  triml(count);
2470  return *this;
2471  }
2472 
2481  String& stripl(const char* str, Size strsize, Size max=ALL) {
2482  if (strsize > 0 && strsize <= size_ && max > 0) {
2483  Size i, j = 0, count = 0;
2484  do {
2485  for (i=0; i < strsize; ++i, ++j)
2486  if (j >= size_ || str[i] != data_[j])
2487  goto break_all;
2488  ++count;
2489  } while (j < size_ && count < max);
2490  break_all:
2491  if (count > 0) {
2492  count *= strsize;
2493  size_ -= count;
2494  data_ += count;
2495  }
2496  }
2497  return *this;
2498  }
2499 
2507  char ch;
2508  while ( size_ > 0 && ((ch=data_[size_-1]) == ' ' || ch == '\t') )
2509  --size_;
2510  return *this;
2511  }
2512 
2520  String& stripr(char ch, Size max=ALL) {
2521  for (Size i=0; size_ > 0 && data_[size_-1] == ch && i < max; ++i)
2522  --size_;
2523  return *this;
2524  }
2525 
2534  String& stripr(const char* str, Size strsize, Size max=ALL) {
2535  if (strsize > 0 && strsize <= size_ && max > 0) {
2536  Size i, j = size_, count = 0;
2537  do {
2538  for (i=strsize; i > 0; )
2539  if (j == 0 || str[--i] != data_[--j])
2540  goto break_all;
2541  ++count;
2542  } while (j > 0 && count < max);
2543  break_all:
2544  if (count > 0)
2545  size_ -= (count * strsize);
2546  }
2547  return *this;
2548  }
2549 
2558  if (size_ > 0) {
2559  const char* end = data_ + size_;
2560  data_ = (char*)str_scan_nws(data_, end);
2561  size_ = (Size)(str_scan_nws_r(data_, end) - data_);
2562  }
2563  return *this;
2564  }
2565 
2574  if (size_ > 0) {
2575  const char* end = data_ + size_;
2576  data_ = (char*)str_scan_nws(data_, end);
2577  size_ = (Size)(end - data_);
2578  }
2579  return *this;
2580  }
2581 
2590  if (size_ > 0) {
2591  const char* end = data_ + size_;
2592  size_ = (Size)(str_scan_nws_r(data_, end) - data_);
2593  }
2594  return *this;
2595  }
2596 
2604  char ch;
2605  Size count = 0;
2606  while ( count < size_ && ((ch=data_[count]) == '\n' || ch == '\r') )
2607  ++count;
2608  if (count > 0) {
2609  size_ -= count;
2610  data_ += count;
2611  }
2612  return *this;
2613  }
2614 
2624  char ch;
2625  Size count = 0;
2626  for (; count < size_ && max > 0; --max) {
2627  ch = data_[count];
2628  if (ch == '\n') {
2629  if (count + 1 < size_ && data_[count + 1] == '\r') {
2630  count += 2;
2631  continue;
2632  }
2633  } else if (ch == '\r') {
2634  if (count + 1 < size_ && data_[count + 1] == '\n') {
2635  count += 2;
2636  continue;
2637  }
2638  } else
2639  break;
2640  ++count;
2641  }
2642  triml(count);
2643  return *this;
2644  }
2645 
2653  char ch;
2654  while ( size_ > 0 && ((ch=data_[size_-1]) == '\n' || ch == '\r') )
2655  --size_;
2656  return *this;
2657  }
2658 
2667  char ch;
2668  for (; size_ > 0 && max > 0; --max) {
2669  ch = data_[size_ - 1];
2670  if (ch == '\n') {
2671  if (size_ > 1 && data_[size_ - 2] == '\r') {
2672  size_ -= 2;
2673  continue;
2674  }
2675  } else if (ch == '\r') {
2676  if (size_ > 1 && data_[size_ - 2] == '\n') {
2677  size_ -= 2;
2678  continue;
2679  }
2680  } else
2681  break;
2682  --size_;
2683  }
2684  return *this;
2685  }
2686 
2694  stripl_newlines();
2695  stripr_newlines();
2696  return *this;
2697  }
2698 
2699  // COPY
2700 
2705  String& copy(const ListType& str)
2706  { ListType::copy(str); return *this; }
2707 
2712  String& copy(const StringBase& str)
2713  { ListType::copy(str); return *this; }
2714 
2720  String& copy(const char* str, Size size)
2721  { ListType::copy(str, size); return *this; }
2722 
2727  String& copy(const char* str) {
2728  if (str == NULL)
2729  ListType::set();
2730  else
2731  ListType::copy(str, (Size)strlen(str));
2732  return *this;
2733  }
2734 
2735  // ADD
2736 
2741  String& add(char ch)
2742  { ListType::add(ch); return *this; }
2743 
2749  String& add(char ch, Size count) {
2750  ListType::advAdd(count);
2751  if (count > 0)
2752  memset(data_ + size_ - count, (int)(uchar)ch, count);
2753  return *this;
2754  }
2755 
2762  String& add(const ListType& str)
2763  { ListType::add(str); return *this; }
2764 
2771  String& add(const StringBase& str)
2772  { ListType::add(str); return *this; }
2773 
2781  String& add(const char* str, Size size)
2782  { ListType::add(str, size); return *this; }
2783 
2790  String& add(const char* str)
2791  { if (str) add(str, (Size)strlen(str)); return *this; }
2792 
2799  String& addsep(char delim=',')
2800  { if (size_ > 0 && data_[size_-1] != delim) add(delim); return *this; }
2801 
2807  String& addn(int num, int base=fDEC)
2808  { writenum(num, base); return *this; }
2809 
2815  String& addn(long num, int base=fDEC)
2816  { writenum(num, base); return *this; }
2817 
2823  String& addn(longl num, int base=fDEC)
2824  { writenum(num, base); return *this; }
2825 
2831  String& addn(uint num, int base=fDEC)
2832  { writenumu(num, base); return *this; }
2833 
2839  String& addn(ulong num, int base=fDEC)
2840  { writenumu(num, base); return *this; }
2841 
2847  String& addn(ulongl num, int base=fDEC)
2848  { writenumu(num, base); return *this; }
2849 
2855  String& addn(float num, int precision=fPREC_AUTO)
2856  { writenumf(num, precision); return *this; }
2857 
2863  String& addn(double num, int precision=fPREC_AUTO)
2864  { writenumf(num, precision); return *this; }
2865 
2871  String& addn(ldouble num, int precision=fPREC_AUTO)
2872  { writenumf(num, precision); return *this; }
2873 
2880  String& operator<<(bool val) {
2881  if (val)
2882  add("true", 4);
2883  else
2884  add("false", 5);
2885  return *this;
2886  }
2887 
2900  String& operator<<(char ch)
2901  { return add(ch); }
2902 
2915  String& operator<<(const ListType& str)
2916  { return add(str); }
2917 
2930  String& operator<<(const StringBase& str)
2931  { return add(str); }
2932 
2945  String& operator<<(const char* str)
2946  { return add(str); }
2947 
2960  String& operator<<(const ValNull& val) {
2961  EVO_PARAM_UNUSED(val);
2962  return set();
2963  }
2964 
2977  String& operator<<(const ValEmpty& val) {
2978  EVO_PARAM_UNUSED(val);
2979  return setempty();
2980  }
2981 
2994  add(getnewline(nl), getnewlinesize(nl));
2995  return *this;
2996  }
2997 
3004  { return *this; }
3005 
3018  String& operator<<(int num)
3019  { writenum(num); return *this; }
3020 
3033  String& operator<<(long num)
3034  { writenum(num); return *this; }
3035 
3048  String& operator<<(longl num)
3049  { writenum(num); return *this; }
3050 
3063  String& operator<<(uint num)
3064  { writenumu(num); return *this; }
3065 
3078  String& operator<<(ulong num)
3079  { writenumu(num); return *this; }
3080 
3093  String& operator<<(ulongl num)
3094  { writenumu(num); return *this; }
3095 
3108  String& operator<<(float num)
3109  { writenumf(num); return *this; }
3110 
3123  String& operator<<(double num)
3124  { writenumf(num); return *this; }
3125 
3138  String& operator<<(ldouble num)
3139  { writenumf(num); return *this; }
3140 
3146  { add(fmt.ch, fmt.count); return *this; }
3147 
3153  { writefmtstr(fmt.str.data_, fmt.str.size_, fmt.fmt); return *this; }
3154 
3160  const char* newline_str = fmt.newline.getnewline();
3161  const uint newline_size = fmt.newline.getnewlinesize();
3162 
3163  const Size EST_LINES = (fmt.width > 0 ? fmt.str.size_ / fmt.width : 1) + 1;
3164  reserve(fmt.str.size_ + ((fmt.indent + newline_size + 1) * EST_LINES));
3165 
3166  String str(fmt.str.data_, fmt.str.size_), line, substr;
3167  for (uint notfirst=0; str.token_line(line); ) {
3168  for (;;) {
3169  if (line.empty()) {
3170  add(newline_str, newline_size);
3171  } else {
3172  if (notfirst == 0)
3173  ++notfirst;
3174  else if (fmt.indent > 0)
3175  add(' ', fmt.indent);
3176  if (fmt.width > 1 && line.size() > (Size)fmt.width) {
3177  // line too long, try to find a word break
3178  Size i = line.findnonwordr(0, (Size)fmt.width + 1);
3179  if (i == NONE) {
3180  i = (Size)fmt.width;
3181  } else {
3182  while (i > 0 && ascii_breaktype(line[i]) == cbtBEGIN)
3183  --i;
3184  if (i < (Size)fmt.width)
3185  ++i;
3186  }
3187 
3188  substr.set(line.data(), i).stripr();
3189  if (!substr.empty()) {
3190  add(substr);
3191  add(newline_str, newline_size);
3192  }
3193 
3194  line.triml(i).stripl();
3195  continue;
3196  }
3197  add(line);
3198  add(newline_str, newline_size);
3199  }
3200  break;
3201  }
3202  }
3203  return *this;
3204  }
3205 
3211  { writefmtnum(fmt.num, fmt.fmt); return *this; }
3212 
3214  String& operator<<(const FmtInt& fmt)
3215  { writefmtnum(fmt.num, fmt.fmt); return *this; }
3216 
3219  { writefmtnum(fmt.num, fmt.fmt); return *this; }
3220 
3223  { writefmtnum(fmt.num, fmt.fmt); return *this; }
3224 
3227  { writefmtnumu(fmt.num, fmt.fmt); return *this; }
3228 
3231  { writefmtnumu(fmt.num, fmt.fmt); return *this; }
3232 
3235  { writefmtnumu(fmt.num, fmt.fmt); return *this; }
3236 
3239  { writefmtnumu(fmt.num, fmt.fmt); return *this; }
3240 
3243  { writefmtnumf(fmt.num, fmt.fmt); return *this; }
3244 
3247  { writefmtnumf(fmt.num, fmt.fmt); return *this; }
3248 
3251  { writefmtnumf(fmt.num, fmt.fmt); return *this; }
3252 
3254  template<class T>
3255  String& operator<<(const FmtFieldNum<T>& fmt) {
3256  if (IntegerT<T>::SIGN)
3257  writefmtnum(fmt.num.num, fmt.num.fmt, &fmt.field);
3258  else
3259  writefmtnumu(fmt.num.num, fmt.num.fmt, &fmt.field);
3260  return *this;
3261  }
3262 
3264  template<class T>
3265  String& operator<<(const FmtFieldFloat<T>& fmt)
3266  { writefmtnumf(fmt.num.num, fmt.num.fmt, &fmt.field); return *this; }
3267 
3272  String& operator<<(const FmtPtr& fmtptr)
3273  { writefmtnumu((size_t)fmtptr.ptr, fmtptr.fmt); return *this; }
3274 
3280  { writefmtdump(fmt, getnewline(), getnewlinesize()); return *this; }
3281 
3315  struct Format {
3316  typedef String::Size Size;
3317  typedef String Out;
3318  typedef Format This;
3319 
3320  Out& out;
3322 
3326  Format(Out& out) : out(out)
3327  { }
3328 
3334  Format(const This& src) : out(src.out), fmt(src.fmt)
3335  { }
3336 
3343  This& operator=(const This& src)
3344  { memcpy(&fmt, &src.fmt, sizeof(FmtAttribs)); return *this; }
3345 
3349  Out& write_out()
3350  { return out; }
3351 
3352  // Field
3353 
3358  This& operator<<(FmtAlign align)
3359  { fmt.field.align = align; return *this; }
3360 
3365  This& operator<<(FmtWidth width)
3366  { fmt.field.width = width; return *this; }
3367 
3372  This& operator<<(const FmtSetField& field)
3373  { fmt.field.merge(field); return *this; }
3374 
3375  // Newlines/Flush
3376 
3382  { out.add(getnewline(nl), getnewlinesize(nl)); return *this; }
3383 
3390  { return *this; }
3391 
3392  // Null
3393 
3398  This& operator<<(const FmtSetNull& null)
3399  { fmt.null = null; return *this; }
3400 
3401  // Bools
3402 
3409  This& operator<<(bool val) {
3410  if (val)
3411  out.add("true", 4);
3412  else
3413  out.add("false", 5);
3414  return *this;
3415  }
3416 
3417  // Chars
3418 
3423  This& operator<<(char ch)
3424  { out.add(ch); return *this; }
3425 
3430  This& operator<<(const FmtChar& ch)
3431  { out.writefmtchar(ch.ch, ch.count, fmt.field); return *this; }
3432 
3433  // Strings
3434 
3441  This& operator<<(const char* val) {
3442  if (val == NULL) {
3443  if (fmt.null.size > 0)
3444  out.writefmtstr(fmt.null.str, fmt.null.size, fmt.field);
3445  } else if (*val != '\0')
3446  out.writefmtstr(val, (Size)strlen(val), fmt.field);
3447  return *this;
3448  }
3449 
3456  This& operator<<(const StringBase& val) {
3457  if (val.data_ == NULL) {
3458  if (fmt.null.size > 0)
3459  out.writefmtstr(fmt.null.str, fmt.null.size, fmt.field);
3460  } else if (val.size_ > 0)
3461  out.writefmtstr(val.data_, val.size_, fmt.field);
3462  return *this;
3463  }
3464 
3465  // Integers
3466 
3471  This& operator<<(FmtBase base)
3472  { fmt.num_int.base = base; return *this; }
3473 
3479  { fmt.num_int.prefix = prefix; return *this; }
3480 
3485  This& operator<<(const FmtSetInt& fmt_int)
3486  { fmt.num_int.merge(fmt_int); return *this; }
3487 
3494  This& operator<<(short num)
3495  { out.writefmtnum(num, fmt.num_int, &fmt.field); return *this; }
3496 
3498  This& operator<<(int num)
3499  { out.writefmtnum(num, fmt.num_int, &fmt.field); return *this; }
3500 
3502  This& operator<<(long num)
3503  { out.writefmtnum(num, fmt.num_int, &fmt.field); return *this; }
3504 
3506  This& operator<<(longl num)
3507  { out.writefmtnum(num, fmt.num_int, &fmt.field); return *this; }
3508 
3515  This& operator<<(ushort num)
3516  { out.writefmtnumu(num, fmt.num_int, &fmt.field); return *this; }
3517 
3519  This& operator<<(uint num)
3520  { out.writefmtnumu(num, fmt.num_int, &fmt.field); return *this; }
3521 
3523  This& operator<<(ulong num)
3524  { out.writefmtnumu(num, fmt.num_int, &fmt.field); return *this; }
3525 
3527  This& operator<<(ulongl num)
3528  { out.writefmtnumu(num, fmt.num_int, &fmt.field); return *this; }
3529 
3537  template<class T>
3538  This& operator<<(const IntegerT<T>& num) {
3539  if (num.null()) {
3540  if (fmt.null.size > 0)
3541  out.writefmtstr(fmt.null.str, fmt.null.size, fmt.field);
3542  } else if (IntegerT<T>::SIGN)
3543  out.writefmtnum(num.value(), fmt.num_int, &fmt.field);
3544  else
3545  out.writefmtnumu(num.value(), fmt.num_int, &fmt.field);
3546  return *this;
3547  }
3548 
3549  // Floats
3550 
3556  { fmt.num_flt.precision = prec; return *this; }
3557 
3562  This& operator<<(const FmtSetFloat& fmt_flt)
3563  { fmt.num_flt.merge(fmt_flt); return *this; }
3564 
3571  This& operator<<(float num)
3572  { out.writefmtnumf(num, fmt.num_flt, &fmt.field); return *this; }
3573 
3575  This& operator<<(double num)
3576  { out.writefmtnumf(num, fmt.num_flt, &fmt.field); return *this; }
3577 
3579  This& operator<<(ldouble num)
3580  { out.writefmtnumf(num, fmt.num_flt, &fmt.field); return *this; }
3581 
3589  template<class T>
3590  This& operator<<(const FloatT<T>& num) {
3591  if (num.null()) {
3592  if (fmt.null.size > 0)
3593  out.writefmtstr(fmt.null.str, fmt.null.size, fmt.field);
3594  } else
3595  out.writefmtnumf(num.value(), fmt.num_flt, &fmt.field);
3596  return *this;
3597  }
3598 
3599  // Dump
3600 
3601  This& operator<<(const FmtDump& fmtdump)
3602  { out.writefmtdump(fmtdump, getnewline(), getnewlinesize()); return *this; }
3603  };
3604 
3605  // PREPEND
3606 
3611  String& prepend(char ch)
3612  { ListType::prepend(ch); return *this; }
3613 
3619  String& prepend(char ch, Size count) {
3620  ListType::advPrepend(count);
3621  if (count > 0)
3622  memset(data_, (int)(uchar)ch, count);
3623  return *this;
3624  }
3625 
3630  String& prepend(const ListType& str)
3631  { ListType::prepend(str); return *this; }
3632 
3637  String& prepend(const StringBase& str)
3638  { ListType::prepend(str); return *this; }
3639 
3645  String& prepend(const char* str, Size size)
3646  { ListType::prepend(str, size); return *this; }
3647 
3652  String& prepend(const char* str)
3653  { if (str) prepend(str, (Size)strlen(str)); return *this; }
3654 
3661  String& prependsep(char delim=',')
3662  { if (size_ > 0 && data_[0] != delim) prepend(delim); return *this; }
3663 
3669  String& prependn(int num, int base=fDEC)
3670  { prependnum(num, base); return *this; }
3671 
3677  String& prependn(long num, int base=fDEC)
3678  { prependnum(num, base); return *this; }
3679 
3685  String& prependn(longl num, int base=fDEC)
3686  { prependnum(num, base); return *this; }
3687 
3693  String& prependn(uint num, int base=fDEC)
3694  { prependnum(num, base); return *this; }
3695 
3701  String& prependn(ulong num, int base=fDEC)
3702  { prependnum(num, base); return *this; }
3703 
3709  String& prependn(ulongl num, int base=fDEC)
3710  { prependnum(num, base); return *this; }
3711 
3717  String& prependn(float num, int precision=fPREC_AUTO)
3718  { prependnumf(num, precision); return *this; }
3719 
3725  String& prependn(double num, int precision=fPREC_AUTO)
3726  { prependnumf(num, precision); return *this; }
3727 
3733  String& prependn(ldouble num, int precision=fPREC_AUTO)
3734  { prependnumf(num, precision); return *this; }
3735 
3736  // INSERT
3737 
3743  Size insert(Key index, char ch)
3744  { return ListType::insert(index, ch); }
3745 
3752  Size insert(Key index, char ch, Size count) {
3753  index = ListType::advInsert(index, count);
3754  if (count > 0)
3755  memset(data_ + index, (int)(uchar)ch, count);
3756  return index;
3757  }
3758 
3764  Size insert(Key index, const ListType& str)
3765  { return ListType::insert(index, str); }
3766 
3772  Size insert(Key index, const StringBase& str)
3773  { return ListType::insert(index, str); }
3774 
3781  Size insert(Key index, const char* str, Size size)
3782  { return ListType::insert(index, str, size); }
3783 
3789  String& insert(Key index, const char* str)
3790  { if (str) insert(index, str, (Size)strlen(str)); return *this; }
3791 
3798  String& insertn(Key index, int num, int base=fDEC)
3799  { insertnum(index, num, base); return *this; }
3800 
3807  String& insertn(Key index, long num, int base=fDEC)
3808  { insertnum(index, num, base); return *this; }
3809 
3816  String& insertn(Key index, longl num, int base=fDEC)
3817  { insertnum(index, num, base); return *this; }
3818 
3825  String& insertn(Key index, uint num, int base=fDEC)
3826  { insertnum(index, num, base); return *this; }
3827 
3834  String& insertn(Key index, ulong num, int base=fDEC)
3835  { insertnum(index, num, base); return *this; }
3836 
3843  String& insertn(Key index, ulongl num, int base=fDEC)
3844  { insertnum(index, num, base); return *this; }
3845 
3852  String& insertn(Key index, float num, int precision=fPREC_AUTO)
3853  { insertnumf(index, num, precision); return *this; }
3854 
3861  String& insertn(Key index, double num, int precision=fPREC_AUTO)
3862  { insertnumf(index, num, precision); return *this; }
3863 
3870  String& insertn(Key index, ldouble num, int precision=fPREC_AUTO)
3871  { insertnumf(index, num, precision); return *this; }
3872 
3873  // FILL
3874 
3880  String& fillch(char ch, Key index=0, Size size=ALL)
3881  { ListType::fill(ch, index, size); return *this; }
3882 
3883  // REPLACE
3884 
3891  String& replace(Key index, Size rsize, const StringBase& str)
3892  { ListType::replace(index, rsize, str.data_, str.size_); return *this; }
3893 
3901  String& replace(Key index, Size rsize, const char* str, Size size)
3902  { ListType::replace(index, rsize, str, size); return *this; }
3903 
3910  String& replace(Key index, Size rsize, const char* str)
3911  { ListType::replace(index, rsize, str, str?(Size)strlen(str):0); return *this; }
3912 
3920  Size findreplace(char ch, const char* str, Size size, Size max=ALL) {
3921  uint startmax = max;
3922  for (Size i = 0; max > 0; --max) {
3923  i = find(ch, i);
3924  if (i == NONE)
3925  break;
3926  ListType::replace(i, 1, str, size);
3927  i += size;
3928  }
3929  return startmax - max;
3930  }
3931 
3938  Size findreplace(char ch, const StringBase& str, Size max=ALL)
3939  { return findreplace(ch, str.data_, str.size_, max); }
3940 
3949  Size findreplace(const char* fstr, Size fsize, const char* str, Size size, Size max=ALL) {
3950  uint startmax = max;
3951  for (Size i = 0; max > 0; --max) {
3952  i = find(fstr, fsize, i);
3953  if (i == NONE)
3954  break;
3955  ListType::replace(i, fsize, str, size);
3956  i += size;
3957  }
3958  return startmax - max;
3959  }
3960 
3968  Size findreplace(const char* fstr, Size fsize, const StringBase& str, Size max=ALL)
3969  { return findreplace(fstr, fsize, str.data_, str.size_, max); }
3970 
3977  Size findreplace(const StringBase& fstr, const StringBase& str, Size max=ALL)
3978  { return findreplace(fstr.data_, fstr.size_, str.data_, str.size_, max); }
3979 
3987  Size findreplace(const StringBase& fstr, const char* str, Size size, Size max=ALL)
3988  { return findreplace(fstr.data_, fstr.size_, str, size, max); }
3989 
3990  // GETBOOL
3991 
4006  bool getbool(Error& error) const {
4007  assert( data_ > (char*)1 || size_ == 0 );
4008  return impl::tobool(data_, size_, error);
4009  }
4010 
4020  template<class T> T getbool() const {
4021  assert( data_ > (char*)1 || size_ == 0 );
4022  return StaticIf< IsPodType<T>::value, impl::ToBoolPod<T>, impl::ToBool<T> >::Type::getbool(data_, size_);
4023  }
4024 
4025  // GETNUM
4026 
4045  template<class T> T getnum(Error& error, int base=0) const {
4046  STATIC_ASSERT( IsPodType<T>::value, getnum_POD_Type_Required );
4047  assert( data_ > (char*)1 || size_ == 0 );
4048  return impl::tonum<T>(data_, size_, error, base);
4049  }
4050 
4063  template<class T> T getnum(int base=0) const {
4064  assert( data_ > (char*)1 || size_ == 0 );
4065  return StaticIf< IsPodType<T>::value, impl::ToNumPod<T>, impl::ToNum<T> >::Type::getnum(data_, size_, base);
4066  }
4067 
4084  template<class T> T getnumf(Error& error) const {
4085  STATIC_ASSERT( IsPodType<T>::value, getnumf_POD_Type_Required );
4086  assert( data_ > (char*)1 || size_ == 0 );
4087  return impl::tonumf<T>(data_, size_, error);
4088  }
4089 
4101  template<class T> T getnumf() const {
4102  assert( data_ > (char*)1 || size_ == 0 );
4103  return StaticIf< IsPodType<T>::value, impl::ToNumfPod<T>, impl::ToNumf<T> >::Type::getnum(data_, size_);
4104  }
4105 
4106  // BOOLVAL
4107 
4116  Bool boolval() const
4117  { return impl::ToBool<Bool>::getbool(data_, size_); }
4118 
4119  // NUM
4120 
4132  Int num(int base=0) const
4133  { return impl::ToNum<Int>::getnum(data_, size_, base); }
4134 
4146  Long numl(int base=0) const
4147  { return impl::ToNum<Long>::getnum(data_, size_, base); }
4148 
4160  LongL numll(int base=0) const
4161  { return impl::ToNum<LongL>::getnum(data_, size_, base); }
4162 
4163  // NUMU
4164 
4177  UInt numu(int base=0) const
4178  { return impl::ToNum<UInt>::getnum(data_, size_, base); }
4179 
4192  ULong numul(int base=0) const
4193  { return impl::ToNum<ULong>::getnum(data_, size_, base); }
4194 
4207  ULongL numull(int base=0) const
4208  { return impl::ToNum<ULongL>::getnum(data_, size_, base); }
4209 
4210  // NUMF
4211 
4222  Float numf() const
4223  { return impl::ToNumf<Float>::getnum(data_, size_); }
4224 
4235  FloatD numfd() const
4236  { return impl::ToNumf<FloatD>::getnum(data_, size_); }
4237 
4248  FloatL numfl() const
4249  { return impl::ToNumf<FloatL>::getnum(data_, size_); }
4250 
4251  // STREAM FORMATTING
4252 
4256  Out& write_out()
4257  { return *this; }
4258 
4266  Size writechar(char ch, Size count=1) {
4267  add(ch, count);
4268  return count;
4269  }
4270 
4278  Size writebin(const char* buf, Size size) {
4279  add(buf, size);
4280  return size;
4281  }
4282 
4290  Size writetext(const char* buf, Size size) {
4291  add(buf, size);
4292  return size;
4293  }
4294 
4305  Size writequoted(const char* buf, Size size, char delim, bool optional=false) {
4306  bool quote_optional = false;
4307  const StrQuoting::Type type = StrQuoting::get(quote_optional, buf, size, delim);
4308  switch (type) {
4309  case StrQuoting::tSINGLE:
4310  if (quote_optional && optional) {
4311  add(buf, size);
4312  return size;
4313  }
4314  case StrQuoting::tDOUBLE:
4315  case StrQuoting::tBACKTICK: {
4316  const char ch = "'\"`"[(uint)type];
4317  const Size result = size + 2;
4318  reserve(result);
4319  add(ch, 1);
4320  add(buf, size);
4321  add(ch, 1);
4322  return result;
4323  }
4324  case StrQuoting::tSINGLE3:
4325  case StrQuoting::tDOUBLE3:
4326  case StrQuoting::tBACKTICK3: {
4327  const char* str = &"'''\"\"\"```"[(uint(type) - 3) * 3];
4328  const Size result = size + 6;
4329  reserve(result);
4330  add(str, 3);
4331  add(buf, size);
4332  add(str, 3);
4333  return result;
4334  }
4336  const char* str = "`\x7F";
4337  const Size result = size + 4;
4338  reserve(result);
4339  add(str, 2);
4340  add(buf, size);
4341  add(str, 2);
4342  return result;
4343  }
4344  case StrQuoting::tERROR:
4345  break;
4346  }
4347  return 0;
4348  }
4349 
4357  char* write_direct(Size size) {
4358  reserve(size);
4359  return buf_.ptr + used();
4360  }
4361 
4372  char* write_direct_multi(Size& available, Size reserve_size) {
4373  available = reserve_size;
4374  if (reserve_size == 0)
4375  return (char*)1; // finished
4376  reserve(reserve_size);
4377  return buf_.ptr + used();
4378  }
4379 
4390  char* write_direct_flush(Size& available, Size written_size, Size reserve_size) {
4391  advSize(used() + written_size);
4392  available = reserve_size;
4393  if (reserve_size == 0)
4394  return (char*)1; // finished
4395  reserve(reserve_size);
4396  return buf_.ptr + used();
4397  }
4398 
4407  advSize(used() + size);
4408  return true;
4409  }
4410 
4417  template<class TNum>
4418  bool writenum(TNum num, int base=fDEC) {
4419  reserve(IntegerT<TNum>::maxlen(base)+1);
4420  const Size len = impl::fnum(data_+size_+IntegerT<TNum>::digits(num,base), num, base);
4421  buf_.header->used += len;
4422  size_ += len;
4423  return true;
4424  }
4425 
4432  template<class TNum>
4433  bool writenumu(TNum num, int base=fDEC) {
4434  reserve(IntegerT<TNum>::maxlen(base)+1);
4435  const Size len = impl::fnumu(data_+size_+IntegerT<TNum>::digits(num,base), num, base);
4436  buf_.header->used += len;
4437  size_ += len;
4438  return true;
4439  }
4440 
4447  template<class TNum>
4448  bool writenumf(TNum num, int precision=fPREC_AUTO) {
4449  Size len;
4450  #if defined(EVO_FNUMF_SPRINTF)
4451  char buf[impl::FNUMF_SPRINTF_BUF_SIZE];
4452  char* fmt;
4453  len = impl::fnumf_sprintf_setup(fmt, buf, num, precision);
4454  if (len > 0) {
4455  reserve(len + 1);
4456  ::sprintf(data_ + size_, fmt, num);
4457  }
4458  #else
4459  int exp = 0;
4460  if (precision < 0) {
4461  num = FloatT<TNum>::fexp10(exp, num);
4462  reserve(FloatT<TNum>::MAXDIGITS_AUTO + 1);
4463  len = impl::fnumfe(data_ + size_, num, exp, false);
4464  } else {
4465  num = FloatT<TNum>::fexp10(exp, impl::fnumf_weight(num, precision));
4466  reserve(FloatT<TNum>::maxdigits_prec(exp, precision) + 1);
4467  len = impl::fnumf(data_ + size_, num, exp, precision);
4468  }
4469  #endif
4470  buf_.header->used += len;
4471  size_ += len;
4472  return true;
4473  }
4474 
4481  bool writefmtchar(char ch, Size count, const FmtSetField& field) {
4482  const Size index = size_;
4483  if (field.width >= 0 && (Size)field.width > count) {
4484  const int fillchar = (int)(field.fill != 0 ? (uchar)field.fill : (uchar)' ');
4485  const uint padding = field.width - count;
4486  ListType::advAdd(count + padding);
4487 
4488  char* p = data_ + index;
4489  switch (field.align) {
4490  case faCURRENT: // fallthrough
4491  case fLEFT:
4492  memset(p, (int)(uchar)ch, count);
4493  if (padding > 0)
4494  memset(p + count, fillchar, padding);
4495  break;
4496  case fCENTER: {
4497  const uint padleft = (padding / 2);
4498  if (padleft > 0) {
4499  memset(p, fillchar, padleft);
4500  p += padleft;
4501  }
4502  memset(p, (int)(uchar)ch, count);
4503  const uint padright = (padding - padleft);
4504  if (padright > 0) {
4505  p += count;
4506  memset(p, fillchar, padright);
4507  }
4508  break;
4509  }
4510  case fRIGHT:
4511  if (padding > 0) {
4512  memset(p, fillchar, padding);
4513  p += padding;
4514  }
4515  memset(p, (int)(uchar)ch, count);
4516  break;
4517  };
4518  } else if (count > 0) {
4519  ListType::advAdd(count);
4520  memset(data_ + index, (int)(uchar)ch, count);
4521  }
4522  return true;
4523  }
4524 
4531  bool writefmtstr(const char* str, Size size, const FmtSetField& field) {
4532  const Size index = size_;
4533  if (field.width >= 0 && (Size)field.width > size) {
4534  const int fillchar = (int)(field.fill != 0 ? (uchar)field.fill : (uchar)' ');
4535  const uint padding = field.width - size;
4536  ListType::advAdd(size + padding);
4537 
4538  char* p = data_ + index;
4539  switch (field.align) {
4540  case faCURRENT: // fallthrough
4541  case fLEFT:
4542  memcpy(p, str, size);
4543  if (padding > 0)
4544  memset(p + size, fillchar, padding);
4545  break;
4546  case fCENTER: {
4547  const uint padleft = (padding / 2);
4548  if (padleft > 0) {
4549  memset(p, fillchar, padleft);
4550  p += padleft;
4551  }
4552  memcpy(p, str, size);
4553  const uint padright = (padding - padleft);
4554  if (padright > 0) {
4555  p += size;
4556  memset(p, fillchar, padright);
4557  }
4558  break;
4559  }
4560  case fRIGHT:
4561  if (padding > 0) {
4562  memset(p, fillchar, padding);
4563  p += padding;
4564  }
4565  memcpy(p, str, size);
4566  break;
4567  };
4568  } else if (size > 0) {
4569  ListType::advAdd(size);
4570  memcpy(data_ + index, str, size);
4571  }
4572  return true;
4573  }
4574 
4582  template<class TNum>
4583  bool writefmtnum(TNum num, const FmtSetInt& fmt, const FmtSetField* field=NULL) {
4584  if (fmt.base <= 0 || fmt.base == fDEC) {
4585  const Size index = size_;
4586  const int digits = IntegerT<TNum>::digits(num, fDEC);
4587  const int width = (fmt.pad_width > digits ? fmt.pad_width : digits);
4588  const int align_padding = (field != NULL && field->width > width ? field->width - width : 0);
4589  ListType::advAdd(width + align_padding);
4590  fmt.impl_num_write(data_ + index, num, digits, width, align_padding, field);
4591  } else
4592  writefmtnumu((typename ToUnsigned<TNum>::Type)num, fmt, field);
4593  return true;
4594  }
4595 
4603  template<class TNum>
4604  bool writefmtnumu(TNum num, const FmtSetInt& fmt, const FmtSetField* field=NULL) {
4605  const int base = (fmt.base > 0 ? fmt.base : fDEC);
4606 
4607  char prefix_ch = 0;
4608  uint prefix_len = 0;
4609  fmt.impl_prefix_info(prefix_ch, prefix_len);
4610 
4611  const int digits = IntegerT<TNum>::digits(num, base);
4612  const int width = (fmt.pad_width > digits ? fmt.pad_width : digits);
4613  const int full_width = width + prefix_len;
4614  const int align_padding = (field != NULL && field->width > full_width ? field->width - full_width : 0);
4615 
4616  const Size index = size_;
4617  ListType::advAdd(full_width + align_padding);
4618  char* p = data_ + index;
4619 
4620  int align_padleft, align_padright;
4621  FmtSetField::setup_align(align_padleft, align_padright, align_padding, field);
4622 
4623  if (align_padleft > 0) {
4624  memset(p, (int)(uchar)field->fill, align_padleft);
4625  p += align_padleft;
4626  }
4627 
4628  FmtSetInt::impl_prefix_write(p, prefix_ch, prefix_len);
4629 
4630  if (digits < width) {
4631  const uint padlen = width - digits;
4632  const int ch = (fmt.pad_ch == 0 ? '0' : (int)(uchar)fmt.pad_ch);
4633  memset(p, ch, padlen);
4634  p += padlen;
4635  }
4636  p += digits;
4637  impl::fnumu(p, num, base);
4638 
4639  if (align_padright > 0)
4640  memset(p, (int)(uchar)field->fill, align_padright);
4641  return true;
4642  }
4643 
4651  template<class TNum>
4652  bool writefmtnumf(TNum num, const FmtSetFloat& fmt, const FmtSetField* field=NULL) {
4653  const int align_width = (field != NULL ? field->width : 0);
4654  int exp = 0, maxlen;
4655  fmt.impl_info(num, exp, maxlen, align_width); // sets maxlen
4656  reserve(maxlen);
4657 
4658  const ulong len = fmt.impl_write(data_ + size_, num, exp, align_width, field);
4659  buf_.header->used += len;
4660  size_ += len;
4661  return true;
4662  }
4663 
4672  bool writefmtdump(const FmtDump& fmt, const char* newline, uint newlinesize) {
4673  assert( newlinesize <= 2 );
4674  if (fmt.size > 0) {
4675  const char* DIGITS = (fmt.upper ? "0123456789ABCDEF" : "0123456789abcdef");
4676  const ulong LINE_SIZE = (fmt.maxline > 0 ? fmt.maxline : fmt.size);
4677 
4678  const uchar* ptr = (uchar*)fmt.buf;
4679  const uchar* ptr_end = ptr + fmt.size;
4680  const uchar* ptr_nl;
4681 
4682  FmtSetInt offset_fmt(fHEX, 0);
4683  ulong offset = 0;
4684  if (fmt.maxline > 0 && !fmt.compact) {
4685  offset_fmt.pad_width = Int::digits(fmt.size, fHEX);
4686  const ulong lines = (fmt.size / fmt.maxline) + 1;
4687  reserve( ((offset_fmt.pad_width + 4 + (fmt.maxline * 4) + newlinesize) * lines) + 1 );
4688  } else
4689  reserve( (fmt.size * 4) + newlinesize + 1 );
4690 
4691  // Loop for each line
4692  int padding;
4693  for (const uchar* ptr2; ptr < ptr_end; ) {
4694  // Show offset
4695  if (fmt.maxline > 0 && !fmt.compact) {
4696  padding = offset_fmt.pad_width - IntegerT<ulong>::digits(offset, fHEX);
4697  if (padding > 0)
4698  memset(data_ + size_, '0', padding);
4699  size_ += offset_fmt.pad_width;
4700  impl::fnumu(data_ + size_, offset, fHEX);
4701 
4702  offset += fmt.maxline;
4703  data_[size_++] = ':';
4704  data_[size_++] = ' ';
4705  data_[size_++] = ' ';
4706  }
4707 
4708  // Figure newline position
4709  ptr_nl = ptr + LINE_SIZE;
4710  if (ptr_nl > ptr_end)
4711  ptr_nl = ptr_end;
4712 
4713  // Hex dump line
4714  ptr2 = ptr;
4715  for (; ptr < ptr_nl; ++ptr) {
4716  data_[size_++] = DIGITS[(*ptr >> 4) & 0x0F];
4717  data_[size_++] = DIGITS[*ptr & 0x0F];
4718  data_[size_++] = ' ';
4719  }
4720 
4721  if (fmt.compact) {
4722  assert( size_ > 0 );
4723  --size_; // trim extra space from last byte
4724  } else {
4725  if (ptr_nl >= ptr_end && fmt.maxline > 0 && ptr2 != (uchar*)fmt.buf) {
4726  // Pad last line, add separator
4727  const ulong remainder = fmt.size % fmt.maxline;
4728  const ulong count = (remainder > 0 ? ((fmt.maxline - remainder) * 3) + 1 : 1);
4729  if (count > 0) {
4730  memset(data_ + size_, ' ', count);
4731  size_ += count;
4732  }
4733  } else
4734  // Separator
4735  data_[size_++] = ' ';
4736 
4737  // ASCII dump line
4738  for (; ptr2 < ptr_nl; ++ptr2) {
4739  if (*ptr2 < ' ' || *ptr2 > '~')
4740  data_[size_++] = '.';
4741  else
4742  data_[size_++] = (char)*ptr2;
4743  }
4744  }
4745 
4746  // Newline
4747  memcpy(data_ + size_, newline, newlinesize);
4748  size_ += newlinesize;
4749  }
4750  buf_.header->used = size_;
4751  assert( buf_.header->used <= buf_.header->size );
4752  }
4753  return true;
4754  }
4755 
4763  bool writefmtdump(const FmtDump& fmt, Newline nl=NL_SYS) {
4764  writefmtdump(fmt, getnewline(nl), getnewlinesize(nl));
4765  return true;
4766  }
4767 
4768  // CONVERT
4769 
4776  template<class C> C convert() const
4777  // An "undefined reference" compiler error pointing here means the given conversion isn't implemented/supported
4778  { return Convert<String,C>::value(*this); }
4779 
4786  template<class C> String& convert_set(C value)
4787  // An "undefined reference" compiler error pointing here means the given conversion isn't implemented/supported
4788  { Convert<String,C>::set(*this, value); return *this; }
4789 
4796  template<class C> String& convert_add(C value)
4797  // An "undefined reference" compiler error pointing here means the given conversion isn't implemented/supported
4798  { Convert<String,C>::add(*this, value); return *this; }
4799 
4808  template<class C> bool convert_addq(C value, char delim=',')
4809  // An "undefined reference" compiler error pointing here means the given conversion isn't implemented/supported
4810  { return Convert<String,C>::addq(*this, value, delim); }
4811 
4820  template<class C> String& join(const C& items, char delim=',') {
4821  typename C::Iter iter(items);
4822  for (typename C::Size i=0; iter; ++iter, ++i) {
4823  if (i > 0)
4824  add(delim);
4826  }
4827  return *this;
4828  }
4829 
4839  template<class C> String& joinq(const C& items, char delim=',') {
4840  typename C::Iter iter(items);
4841  for (typename C::Size i=0; iter; ++iter, ++i) {
4842  if (i > 0)
4843  add(delim);
4844  Convert<String,typename C::Item>::addq(*this, *iter, delim);
4845  }
4846  return *this;
4847  }
4848 
4858  template<class C> String& joinmap(const C& map, char delim=',', char kvdelim='=') {
4859  typename C::Iter iter(map);
4860  for (typename C::Size i=0; iter; ++iter, ++i) {
4861  if (i > 0)
4862  add(delim);
4863  Convert<String,typename C::Key>::add(*this, iter->first);
4864  add(kvdelim);
4865  Convert<String,typename C::Value>::add(*this, iter->second);
4866  }
4867  return *this;
4868  }
4869 
4880  template<class C> String& joinmapq(const C& map, char delim=',', char kvdelim='=') {
4881  typename C::Iter iter(map);
4882  for (typename C::Size i=0; iter; ++iter, ++i) {
4883  if (i > 0)
4884  add(delim);
4885  Convert<String,typename C::Key>::addq(*this, iter->first, kvdelim);
4886  add(kvdelim);
4887  Convert<String,typename C::Value>::addq(*this, iter->second, delim);
4888  }
4889  return *this;
4890  }
4891 
4902  template<class Tok,class C> typename C::Size split(C& items, char delim=',') const {
4903  typename C::Size count = 0;
4904  Tok tok(*this);
4905  for (; tok.next(delim); ++count)
4906  items.add(tok.value().template convert<typename C::Item>());
4907  return count;
4908  }
4909 
4921  template<class C> typename C::Size splitmap(C& map, char delim=',', char kvdelim='=') const
4922  { return map.addsplit(*this, delim, kvdelim); }
4923 
4924  // CASE
4925 
4932  ThisType& toupper() {
4933  bool found = false;
4934  Size index = 0;
4935  for (; index < size_; ++index) {
4936  if (ascii_type(data_[index]) == ctLOWER) {
4937  found = true;
4938  break;
4939  }
4940  }
4941  if (found) {
4942  unshare();
4943  for (; index < size_; ++index)
4944  data_[index] = ascii_toupper(data_[index]);
4945  }
4946  return *this;
4947  }
4948 
4955  ThisType& tolower() {
4956  bool found = false;
4957  Size index = 0;
4958  for (; index < size_; ++index) {
4959  if (ascii_type(data_[index]) == ctUPPER) {
4960  found = true;
4961  break;
4962  }
4963  }
4964  if (found) {
4965  unshare();
4966  for (; index < size_; ++index)
4967  data_[index] = ascii_tolower(data_[index]);
4968  }
4969  return *this;
4970  }
4971 
4972  // OVERRIDES
4973 
4976  { ListType::clear(); return *this; }
4977 
4980  { ListType::triml(size); return *this; }
4981 
4984  { ListType::trimr(size); return *this; }
4985 
4988  { ListType::truncate(size); return *this; }
4989 
4991  String& slice(Key index)
4992  { ListType::slice(index); return *this; }
4993 
4995  String& slice(Key index, Size size)
4996  { ListType::slice(index, size); return *this; }
4997 
4999  String& slice2(Key index1, Key index2)
5000  { ListType::slice2(index1, index2); return *this; }
5001 
5004  { ListType::unslice(); return *this; }
5005 
5007  Size capacity() const
5008  { return ListType::capacity(); }
5009 
5012  { ListType::capacity(size); return *this; }
5013 
5016  { ListType::capacitymin(min); return *this; }
5017 
5020  { ListType::capacitymax(max); return *this; }
5021 
5024  { ListType::compact(); return *this; }
5025 
5027  String& reserve(Size size, bool prefer_realloc=false)
5028  { ListType::reserve(size, prefer_realloc); return *this; }
5029 
5032  { ListType::unshare(); return *this; }
5033 
5036  { ListType::resize(size); return *this; }
5037 
5040  { ListType::reverse(); return *this; }
5041 
5044  { ListType::advResize(size); return *this; }
5045 
5046  // STATIC
5047 
5051  static const String& digits()
5052  { static const String str("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"); return str; }
5053 
5057  static const String& digitsl()
5058  { static const String str("0123456789abcdefghijklmnopqrstuvwxyz"); return str; }
5059 
5063  static const String& letters()
5064  { static const String str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); return str; }
5065 
5069  static const String& lettersu()
5070  { static const String str("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); return str; }
5071 
5075  static const String& lettersl()
5076  { static const String str("abcdefghijklmnopqrstuvwxyz"); return str; }
5077 
5081  static const String& whitespace()
5082  { static const String str(" \t"); return str; }
5083 
5084 private:
5085  // Hide unused parent members
5086  ListType& fill(const char& item, Key index=0, Size size=ALL);
5087  String& addnew(Size);
5088  String& prependnew(Size);
5089  Size insertnew(Key, Size);
5090  void advAdd(Size);
5091  void advPrepend(Size);
5092  void advInsert(Key, Size);
5093  void advRemove(Key, Size);
5094 
5095  // Doxygen: Hide unused overidden parent members from documentation
5096 #if defined(DOXYGEN)
5097  bool contains(ItemVal) const;
5098  bool starts(ItemVal) const;
5099  bool ends(ItemVal) const;
5100  ListType& operator<<(const char&);
5101  ListType& add(const char&);
5102  ListType& prepend(const char&);
5103  Size insert(Key,const char&);
5104 
5105  Size used() const;
5106  #if EVO_LIST_OPT_REFTERM
5107  bool terminated() const;
5108  #endif
5109  Size refs() const;
5110  const char* buffer() const;
5111  void iterInitMutable();
5112  const char* iterFirst(IterKey& key) const;
5113  const char* iterNext(IterKey& key) const;
5114  const char* iterNext(Size count,IterKey& key) const;
5115  const char* iterLast(IterKey& key) const;
5116  const char* iterPrev(IterKey& key) const;
5117  const char* iterPrev(Size count,IterKey& key) const;
5118  Size iterCount() const;
5119  const char* iterSet(IterKey key) const;
5120 #endif
5121 
5122  // Set number
5123  template<class T>
5124  void setnum(T num, int base=fDEC) {
5125  clear().capacitymin(IntegerT<T>::maxlen(base)+1).unshare();
5126  const Size len = impl::fnum(data_+IntegerT<T>::digits(num,base), num, base);
5127  buf_.header->used += len;
5128  size_ += len;
5129  }
5130  template<class T>
5131  void setnumu(T num, int base=fDEC) {
5132  clear().capacitymin(IntegerT<T>::maxlen(base)+1).unshare();
5133  const Size len = impl::fnumu(data_+IntegerT<T>::digits(num,base), num, base);
5134  buf_.header->used += len;
5135  size_ += len;
5136  }
5137  template<class T>
5138  void setnumf(T num, int precision=fPREC_AUTO) {
5139  Size len;
5140  #if defined(EVO_FNUMF_SPRINTF)
5141  char buf[impl::FNUMF_SPRINTF_BUF_SIZE];
5142  char* fmt;
5143  len = impl::fnumf_sprintf_setup(fmt, buf, num, precision);
5144  if (len > 0) {
5145  clear().capacitymin(len + 1).unshare();
5146  ::sprintf(data_, fmt, num);
5147  }
5148  #else
5149  int exp = 0;
5150  if (precision < 0) {
5151  num = FloatT<T>::fexp10(exp, num);
5152  clear().capacitymin(FloatT<T>::MAXDIGITS_AUTO).unshare();
5153  len = impl::fnumfe(data_, num, exp, false);
5154  } else {
5155  num = FloatT<T>::fexp10(exp, impl::fnumf_weight(num, precision));
5156  clear().capacitymin(FloatT<T>::maxdigits_prec(exp, precision)).unshare();
5157  len = impl::fnumf(data_, num, exp, precision);
5158  }
5159  #endif
5160  buf_.header->used += len;
5161  size_ += len;
5162  }
5163 
5164  // Prepend number
5165  template<class T>
5166  void prependnum(T num, int base=fDEC) {
5167  StringInt<T> str(num, base, false);
5168  prepend(str.data(), str.size());
5169  }
5170  template<class T>
5171  void prependnumf(T num, int precision=fPREC_AUTO) {
5172  StringFlt<T> str(num, precision, false);
5173  prepend(str.data(), str.size());
5174  }
5175 
5176  // Insert number
5177  template<class T>
5178  void insertnum(Key index, T num, int base=fDEC) {
5179  StringInt<T> str(num, base, false);
5180  insert(index, str.data(), str.size());
5181  }
5182  template<class T>
5183  void insertnumf(Key index, T num, int precision=fPREC_AUTO) {
5184  StringFlt<T> str(num, precision, false);
5185  insert(index, str.data(), str.size());
5186  }
5187 };
5188 
5189 // String comparison
5191 inline bool operator==(const char* str1, const String& str2)
5192  { return str2 == str1; }
5193 inline bool operator!=(const char* str1, const String& str2)
5194  { return str2 != str1; }
5197 // String conversion
5199 // Common base types for string conversion -- used internally
5200 template<class T> struct Convert_StringToIntBase {
5201  template<class V> static void set(String& dest, V value)
5202  { dest.setn(value); }
5203  template<class V> static void add(String& dest, V value)
5204  { dest.addn(value); }
5205  template<class V> static bool addq(String& dest, V value, char)
5206  { dest.addn(value); return true; }
5207  static T value(const String& src)
5208  { return src.getnum<T>(); }
5209 };
5210 template<class T> struct Convert_StringToFltBase {
5211  template<class V> static void set(String& dest, V value)
5212  { dest.setn(value); }
5213  template<class V> static void add(String& dest, V value)
5214  { dest.addn(value); }
5215  template<class V> static bool addq(String& dest, V value, char)
5216  { dest.addn(value); return true; }
5217  static T value(const String& src)
5218  { return src.getnumf<T>(); }
5219 };
5220 template<class T> struct Convert_StringToCIntBase {
5221  template<class V> static void set(String& dest, const V& value)
5222  { if (value.valid()) dest.setn(*value); }
5223  template<class V> static void add(String& dest, const V& value)
5224  { if (value.valid()) dest.addn(*value); }
5225  template<class V> static bool addq(String& dest, const V& value, char)
5226  { if (value.valid()) dest.addn(*value); return true; }
5227  static T value(const String& src)
5228  { return src.getnum<T>(); }
5229 };
5230 template<class T> struct Convert_StringToCFltBase {
5231  template<class V> static void set(String& dest, const V& value)
5232  { if (value.valid()) dest.setn(*value); }
5233  template<class V> static void add(String& dest, const V& value)
5234  { if (value.valid()) dest.addn(*value); }
5235  template<class V> static bool addq(String& dest, const V& value, char)
5236  { if (value.valid()) dest.addn(*value); return true; }
5237  static T value(const String& src)
5238  { return src.getnumf<T>(); }
5239 };
5240 // Conversion templates
5241 template<> struct Convert<const char*,String> {
5242  static void set(String& dest, const char* value)
5243  { dest.set(value); }
5244  static void add(String& dest, const char* value)
5245  { dest.add(value); }
5246  static String value(const char* src)
5247  { return src; }
5248 };
5249 template<> struct Convert<char*,String> {
5250  static void set(String& dest, const char* value)
5251  { dest.set(value); }
5252  static void add(String& dest, const char* value)
5253  { dest.add(value); }
5254  static String value(const char* src)
5255  { return src; }
5256 };
5257 template<> struct Convert<String,String> {
5258  static void set(String& dest, const String& value)
5259  { dest.set(value); }
5260  static void add(String& dest, const String& value)
5261  { dest.add(value); }
5262  static bool addq(String& dest, const String& value, char delim)
5263  { return (value.size() == 0 || dest.writequoted(value.data(), value.size(), delim, true) > 0); }
5264  static const String& value(const String& src)
5265  { return src; }
5266 };
5267 template<> struct Convert<String,const char*> {
5268  static void set(String& dest, const char* value)
5269  { dest.set(value); }
5270  static void add(String& dest, const char* value)
5271  { dest.add(value); }
5272  static bool addq(String& dest, const char* value, char delim) {
5273  const StrSizeT len = (StrSizeT)strlen(value);
5274  return (len == 0 || dest.writequoted(value, (StrSizeT)strlen(value), delim, true) > 0);
5275  }
5276  // Unsafe: Converting String to const char*
5277  //template<class U> static const char* value(U&)
5278 };
5279 template<> struct Convert<String,char*> {
5280  static void set(String& dest, const char* value)
5281  { dest.set(value); }
5282  static void add(String& dest, const char* value)
5283  { dest.add(value); }
5284  static bool addq(String& dest, const char* value, char delim) {
5285  const StrSizeT len = (StrSizeT)strlen(value);
5286  return (len == 0 || dest.writequoted(value, (StrSizeT)strlen(value), delim, true) > 0);
5287  }
5288  // Unsafe: Converting String to char*
5289  //template<class U> static const char* value(U&)
5290 };
5291 template<> struct Convert<String,bool> {
5292  static void set(String& dest, bool value) {
5293  if (value) dest.set("true", 4);
5294  else dest.set("false", 5);
5295  }
5296  static void add(String& dest, bool value) {
5297  if (value) dest.add("true", 4);
5298  else dest.add("false", 5);
5299  }
5300  static bool addq(String& dest, bool value, char) {
5301  if (value) dest.add("true", 4);
5302  else dest.add("false", 5);
5303  return true;
5304  }
5305  static bool value(const String& src)
5306  { return src.getbool<bool>(); }
5307 };
5308 template<> struct Convert<String,short> : public Convert_StringToIntBase<short> { };
5309 template<> struct Convert<String,int> : public Convert_StringToIntBase<int> { };
5310 template<> struct Convert<String,long> : public Convert_StringToIntBase<long> { };
5311 template<> struct Convert<String,longl> : public Convert_StringToIntBase<longl> { };
5312 template<> struct Convert<String,ushort> : public Convert_StringToIntBase<ushort> { };
5313 template<> struct Convert<String,uint> : public Convert_StringToIntBase<uint> { };
5314 template<> struct Convert<String,ulong> : public Convert_StringToIntBase<ulong> { };
5315 template<> struct Convert<String,ulongl> : public Convert_StringToIntBase<ulongl> { };
5316 template<> struct Convert<String,float> : public Convert_StringToFltBase<float> { };
5317 template<> struct Convert<String,double> : public Convert_StringToFltBase<double> { };
5318 template<> struct Convert<String,ldouble> : public Convert_StringToFltBase<ldouble> { };
5319 template<> struct Convert<String,Bool> {
5320  static void set(String& dest, Bool value) {
5321  if (value.null()) dest.set();
5322  else if (*value) dest.set("true", 4);
5323  else dest.set("false", 5);
5324  }
5325  static void add(String& dest, Bool value) {
5326  if (value.valid()) {
5327  if (*value) dest.add("true", 4);
5328  else dest.add("false", 5);
5329  }
5330  }
5331  static bool addq(String& dest, Bool value, char) {
5332  if (value.valid()) {
5333  if (*value) dest.add("true", 4);
5334  else dest.add("false", 5);
5335  }
5336  return true;
5337  }
5338  static Bool value(const String& src)
5339  { return src.getbool<Bool>(); }
5340 };
5341 template<> struct Convert<String,Short> : public Convert_StringToCIntBase<Short> { };
5342 template<> struct Convert<String,Int> : public Convert_StringToCIntBase<Int> { };
5343 template<> struct Convert<String,Long> : public Convert_StringToCIntBase<Long> { };
5344 template<> struct Convert<String,LongL> : public Convert_StringToCIntBase<LongL> { };
5345 template<> struct Convert<String,UShort> : public Convert_StringToCIntBase<UShort> { };
5346 template<> struct Convert<String,UInt> : public Convert_StringToCIntBase<UInt> { };
5347 template<> struct Convert<String,ULong> : public Convert_StringToCIntBase<ULong> { };
5348 template<> struct Convert<String,ULongL> : public Convert_StringToCIntBase<ULongL> { };
5349 template<> struct Convert<String,Float> : public Convert_StringToCFltBase<Float> { };
5350 template<> struct Convert<String,FloatD> : public Convert_StringToCFltBase<FloatD> { };
5351 template<> struct Convert<String,FloatL> : public Convert_StringToCFltBase<FloatL> { };
5354 
5373 
5375 
5376 }
5377 #endif
ULong numul(int base=0) const
Convert to number value (unsigned long).
Definition: string.h:4192
bool writefmtchar(char ch, Size count, const FmtSetField &field)
Write (append) formatted and/or repeated character.
Definition: string.h:4481
bool compact
Whether to use compact mode (no address or ASCII output)
Definition: str.h:3298
~StringFlt()
Destructor.
Definition: string.h:260
static void add(C &dest, T value)=delete
Add/Append value to target (reversed conversion).
Bool boolval() const
Convert to bool value.
Definition: string.h:4116
char ascii_tolower(char ch)
Convert ASCII character to lowercase.
Definition: str.h:119
String & addn(double num, int precision=fPREC_AUTO)
Append formatted floating point number (modifier).
Definition: string.h:2863
String & operator<<(const FmtLongL &fmt)
Append operator to append formatted number field.
Definition: string.h:3222
CharBreakType ascii_breaktype(char ch)
Get ASCII character word-break type.
Definition: str.h:91
bool terminated
Whether to add terminator.
Definition: string.h:223
String & operator=(const char16_t *str)
Assignment operator to set and convert from terminated UTF-16 string.
Definition: string.h:849
FloatL numfl() const
Convert to number value (ldouble floating point).
Definition: string.h:4248
Size size() const
Get size.
Definition: list.h:759
T & max(T &a, T &b)
Returns highest of given values.
Definition: alg.h:47
String & addn(long num, int base=fDEC)
Append formatted signed number (modifier).
Definition: string.h:2815
String & operator=(const ValNull &)
Assignment operator to set as null and empty.
Definition: string.h:957
String & prependn(long num, int base=fDEC)
Prepend formatted signed number (modifier).
Definition: string.h:3677
const char * getnewline(Newline newline=NL)
Get newline string for given type.
Definition: sys.h:793
Key findanybut(const StringBase &chars, Key start=0, Key end=END) const
Find first occurrence of any character not listed with forward search.
Definition: string.h:2124
String & reverse()
Reverse item order (modifier).
Definition: string.h:5039
This & operator<<(const StringBase &val)
Append a string.
Definition: string.h:3456
Size size() const
Get formatting string size.
Definition: string.h:276
ulong size
Buffer size in bytes to dump.
Definition: str.h:3296
Key findr(const StringBase &pattern, Key start=0, Key end=END) const
Find last occurrence of pattern string with reverse search.
Definition: string.h:1977
int compare(const ListBase< wchar16, T > &str)
Comparison against UTF-16 string.
Definition: string.h:1620
String & setn(longl num, int base=fDEC)
Set as formatted signed number (modifier).
Definition: string.h:1133
Out & out
Associated output string.
Definition: string.h:3320
Key findword(Key start=0, Key end=END) const
Find first word character.
Definition: string.h:2173
StringFlt()
Constructor intializes to null.
Definition: string.h:246
String & copy(const ListType &str)
Set as full (unshared) copy of another string (modifier).
Definition: string.h:2705
String(const char16_t *str, Size size, UtfMode mode=umREPLACE_INVALID)
Constructor to initialize and convert from UTF-16 string literal (using u prefix).
Definition: string.h:803
String Out
Associated output string type, type returned by write_out()
Definition: string.h:3317
UInt numu(int base=0) const
Convert to number value (unsigned).
Definition: string.h:4177
Holds integer formatting attributes.
Definition: str.h:2589
bool writefmtdump(const FmtDump &fmt, Newline nl=NL_SYS)
Write formatted data dump.
Definition: string.h:4763
LongL numll(int base=0) const
Convert to number value (signed long-long).
Definition: string.h:4160
This & operator<<(FmtWidth width)
Set field width to use.
Definition: string.h:3365
String formatter with state.
Definition: string.h:3315
bool writefmtdump(const FmtDump &fmt, const char *newline, uint newlinesize)
Write formatted data dump.
Definition: string.h:4672
char pad_ch
Fill character, 0 if unspecified (use baseline or default) (default: &#39;0&#39;)
Definition: str.h:2593
bool writenumu(TNum num, int base=fDEC)
Write (append) formatted unsigned number.
Definition: string.h:4433
T getbool() const
Convert to bool value for given boolean type.
Definition: string.h:4020
bool operator!=(const char *str) const
Inequality operator.
Definition: string.h:1665
String & addn(ldouble num, int precision=fPREC_AUTO)
Append formatted floating point number (modifier).
Definition: string.h:2871
Basic boolean type.
Definition: type.h:568
bool token_any(StringT &value, Char &found_delim, const char *delims, Size count)
Extract next token from string using any of given delimiters.
Definition: string.h:1392
String & operator<<(Newline nl)
Append operator to append newline.
Definition: string.h:2993
String(const ListType &str)
Copy constructor.
Definition: string.h:700
String & prependn(longl num, int base=fDEC)
Prepend formatted signed number (modifier).
Definition: string.h:3685
String & addn(ulongl num, int base=fDEC)
Append formatted unsigned number (modifier).
Definition: string.h:2847
String(const char *str)
Constructor for null terminated string.
Definition: string.h:774
StringBase str
Definition: str.h:3006
int utf8_compare(const char *str1, ulong len1, const char *str2, ulong len2)
Compare two non-terminated UTF-8 strings.
Definition: str.h:305
ValEmpty
Special empty value type, pass as vEMPTY.
Definition: sys.h:1101
bool splitr(char delim, ValNull left, T2 &right) const
Split at last occurrence of delimiter into right substring.
Definition: string.h:2396
String & operator<<(const ValEmpty &val)
Append operator to set as empty but not null.
Definition: string.h:2977
String(const ListType *str)
Copy constructor.
Definition: string.h:708
Static conditional type.
Definition: meta.h:134
ListType & operator=(ListType &&src)
Move assignment operator (C++11).
Definition: list.h:496
String & operator=(const ListType *str)
Assignment operator for pointer.
Definition: string.h:886
CharType ascii_type(char ch)
Get ASCII character type.
Definition: str.h:76
static const String & lettersl()
Get string of ASCII lowercase letters (a-z).
Definition: string.h:5075
Evo string scanning helpers with SSE optimized code.
bool upper
Whether to use uppercase hex, false for lowercase.
Definition: str.h:3299
Nullable< T > & set()
Set as null.
Definition: type.h:342
bool split(char delim, ValNull left, T2 &right) const
Split at first occurrence of delimiter into right substring.
Definition: string.h:2324
String & prepend(const char *str, Size size)
Prepend from string pointer (modifier).
Definition: string.h:3645
Size insert(Key index, const ListType &str)
Insert from another string (modifier).
Definition: string.h:3764
String & joinq(const C &items, char delim=',')
Join list items into delimited string, with quoting as needed.
Definition: string.h:4839
Base 16: hexadecimal.
Definition: str.h:2324
bool split(char delim, T1 &left, T2 &right) const
Split at first occurrence of delimiter into left/right substrings.
Definition: string.h:2277
String & stripl(const char *str, Size strsize, Size max=ALL)
Strip left (beginning) occurrences of string.
Definition: string.h:2481
String & prependsep(char delim=',')
Prepend separator/delimiter if needed (modifier).
Definition: string.h:3661
String & joinmap(const C &map, char delim=',', char kvdelim='=')
Join map items into delimited string.
Definition: string.h:4858
Formatting attributes (used internally).
Definition: str.h:2886
Single-quotes: &#39;
Definition: strscan.h:1898
Key find(const StringBase &pattern, Key start=0, Key end=END) const
Find first occurrence of pattern string.
Definition: string.h:1844
This & operator<<(bool val)
Append operator.
Definition: string.h:3409
Size findreplace(char ch, const char *str, Size size, Size max=ALL)
Find character and replace with string (modifier).
Definition: string.h:3920
String & operator<<(bool val)
Append operator.
Definition: string.h:2880
String & operator<<(const FmtULongL &fmt)
Append operator to append formatted number field.
Definition: string.h:3238
Basic character type (char) – see CharT.
Definition: type.h:775
String & insertn(Key index, uint num, int base=fDEC)
Insert formatted unsigned number (modifier).
Definition: string.h:3825
String & operator<<(const FmtFloatD &fmt)
Append operator to append formatted number field.
Definition: string.h:3246
String & slice2(Key index1, Key index2)
Slice to given sublist using start/end positions.
Definition: string.h:4999
String & set2(const StringBase &data, Key index1, Key index2)
Set and reference sublist using start/end positions.
Definition: string.h:1109
This & operator<<(char ch)
Append a character.
Definition: string.h:3423
String & triml(Size size)
Trim left (beginning) items.
Definition: string.h:4979
String & setn(ulong num, int base=fDEC)
Set as formatted unsigned number (modifier).
Definition: string.h:1149
char * format(char *ptr)
Format number using given buffer.
Definition: string.h:235
Key find(char ch, Key start, Key end=END) const
Find first occurrence of character with forward search.
Definition: string.h:1779
bool splitr(char delim, T1 &left, T2 &right) const
Split at last occurrence of delimiter into left/right substrings.
Definition: string.h:2349
String & operator<<(const FmtLong &fmt)
Append operator to append formatted number field.
Definition: string.h:3218
Word character (A-Z, a-z, 0-9, _)
Definition: str.h:65
Automatic floating point precision – either normal decimal notation or E notation, whichever is shorter (default)
Definition: str.h:2343
String & copy(const char *str, Size size)
Set as full (unshared) copy using string pointer (modifier).
Definition: string.h:2720
Random access iterator.
Definition: iter.h:904
Size writequoted(const char *buf, Size size, char delim, bool optional=false)
Write (append) quoted output to string.
Definition: string.h:4305
bool tokenr_any(StringT &value, Char &found_delim, const char *delims, Size count)
Extract next token from string in reverse (from end of string) using any of given delimiters...
Definition: string.h:1432
ValNull
Unique null value type and value (vNULL).
Definition: sys.h:1096
String & insertn(Key index, float num, int precision=fPREC_AUTO)
Insert formatted floating point number (modifier).
Definition: string.h:3852
Key find(const char *pattern, uint pattern_size, Key start=0, Key end=END) const
Find first occurrence of pattern string.
Definition: string.h:1803
String & trimr(Size size)
Trim right (ending) items.
Definition: string.h:4983
String & stripr(char ch, Size max=ALL)
Strip right (ending) occurences of character.
Definition: string.h:2520
String & slice(Key index)
Slice beginning items.
Definition: string.h:4991
This & operator<<(int num)
Append a formatted signed integer.
Definition: string.h:3498
static const T & value(const T &src)=delete
Convert value to target.
Backtick: `
Definition: strscan.h:1900
Holds string to use when formatting null values.
Definition: str.h:2406
Triple backtick: ```
Definition: strscan.h:1903
Triple single-quotes: &#39;&#39;&#39;
Definition: strscan.h:1901
String & operator<<(long num)
Append operator to append formatted number.
Definition: string.h:3033
String & copy(const char *str)
Set as full (unshared) copy of null terminated string (modifier).
Definition: string.h:2727
char fill
Field fill character to pad up to width (default: &#39; &#39;)
Definition: str.h:2484
This & operator<<(const FmtSetInt &fmt_int)
Set integer formatting attributes.
Definition: string.h:3485
static int digits(T num, int base=10)
Get number of digits for given number and base.
Definition: type.h:1028
This & operator<<(longl num)
Append a formatted signed integer.
Definition: string.h:3506
String & operator<<(const FmtUInt &fmt)
Append operator to append formatted number field.
Definition: string.h:3230
String & prependn(ulong num, int base=fDEC)
Prepend formatted unsigned number (modifier).
Definition: string.h:3701
String & setn(double num, int precision=fPREC_AUTO)
Set as formatted floating point number (modifier).
Definition: string.h:1173
String & capacitymax(Size max)
Set maximum capacity (modifier).
Definition: string.h:5019
const char * cstr(String &buffer) const
Get terminated string pointer, using given string buffer if needed (const).
Definition: string.h:1561
String & operator<<(const ValNull &val)
Append operator to set as null and empty.
Definition: string.h:2960
ulong utf16_strlen(const wchar16 *str)
Find terminated UTF-16 string length.
Definition: str.h:946
T getnum(int base=0) const
Convert to number value for given integer type.
Definition: string.h:4063
String & replace(Key index, Size rsize, const StringBase &str)
Replace characters with string (modifier).
Definition: string.h:3891
uint count
Character repeat count.
Definition: str.h:2916
ULongL numull(int base=0) const
Convert to number value (unsigned long-long).
Definition: string.h:4207
Out & write_out()
Get parent output string.
Definition: string.h:3349
String & prependn(uint num, int base=fDEC)
Prepend formatted unsigned number (modifier).
Definition: string.h:3693
Newline
Newline type.
Definition: sys.h:748
String & operator<<(ulong num)
Append operator to append formatted number.
Definition: string.h:3078
bool convert_addq(C value, char delim=',')
Convert value to string with quoting as needed, appending to current string.
Definition: string.h:4808
This & operator<<(const FmtSetNull &null)
Set attributes for null values.
Definition: string.h:3398
Size writebin(const char *buf, Size size)
Write (append) to string.
Definition: string.h:4278
static const T MAX
Maximum interger value.
Definition: type.h:996
Int num(int base=0) const
Convert to number value (signed).
Definition: string.h:4132
Generic value conversion template.
Definition: type.h:1757
String fixed-size buffer for formatting an integer.
Definition: string.h:54
This & operator<<(long num)
Append a formatted signed integer.
Definition: string.h:3502
String & stripl_newlines()
Strip all left (beginning) newlines from string.
Definition: string.h:2603
String & operator=(const StringBase &data)
Assignment operator to copy from base list type.
Definition: string.h:901
static const String & digitsl()
Get string of all ASCII alphanumeric digits with lowercase letters (0-9, a-z).
Definition: string.h:5057
String(const ListType &str, Key index, Key size=ALL)
Extended copy constructor.
Definition: string.h:718
Key findanybutr(const char *chars, Size count, Key start=0, Key end=END) const
Find last occurrence of any character not listed with reverse search.
Definition: string.h:2138
String & operator=(const ValEmpty &)
Assignment operator to set as empty but not null.
Definition: string.h:969
String ThisType
This string type.
Definition: string.h:676
String & insertn(Key index, longl num, int base=fDEC)
Insert formatted signed number (modifier).
Definition: string.h:3816
Long numl(int base=0) const
Convert to number value (signed long).
Definition: string.h:4146
const char * str_scan_nws(const char *str, const char *end)
Scan string pointer for next non-whitespace character and return stop pointer.
Definition: strscan.h:877
String & clear()
Clear by removing all items.
Definition: string.h:4975
This & operator=(const This &src)
Assignment operator copies attributes.
Definition: string.h:3343
String & stripr()
Strip right (ending) whitespace (spaces and tabs).
Definition: string.h:2506
Key find(char ch) const
Find first occurrence of character with forward search.
Definition: string.h:1761
bool getbool(Error &error) const
Convert to bool value for given boolean type.
Definition: string.h:4006
Basic integer type.
Definition: type.h:980
String & stripr2()
Strip right (ending) whitespace (including newlines) from string.
Definition: string.h:2589
uint maxline
Maximum bytes per line to dump, 0 for none (all 1 line)
Definition: str.h:3297
This & operator<<(FmtAlign align)
Set field alignment type to use.
Definition: string.h:3358
String & operator<<(Flush)
Flush output buffer – no-op for string.
Definition: string.h:3003
FmtSetFloat fmt
Definition: str.h:3156
String Out
Type returned by write_out()
Definition: string.h:678
String()
Default constructor sets as null.
Definition: string.h:684
This & operator<<(FmtPrecision prec)
Set floating point formatting precision.
Definition: string.h:3555
IterM begin()
Get iterator at first item (mutable).
Definition: string.h:1725
static const String & letters()
Get string of ASCII letters (A-z).
Definition: string.h:5063
int width
Definition: str.h:3007
StrSizeT Size
List size integer type
Definition: list.h:247
String & insertn(Key index, long num, int base=fDEC)
Insert formatted signed number (modifier).
Definition: string.h:3807
Key findanyr(const StringBase &chars, Key start=0, Key end=END) const
Find last occurrence of any given characters with reverse search.
Definition: string.h:2085
String & operator<<(const FmtFloat &fmt)
Append operator to append formatted number field.
Definition: string.h:3242
String & strip(char ch)
Strip left (beginning) and right (ending) occurences of character.
Definition: string.h:2433
String & resize(Size size)
Resize while preserving existing data (modifier).
Definition: string.h:5035
bool token_line(StringT &line)
Extract next line from string.
Definition: string.h:1467
Check if type is a Plan Old Data type.
Definition: meta.h:528
Size findreplace(const StringBase &fstr, const StringBase &str, Size max=ALL)
Find string and replace with string (modifier).
Definition: string.h:3977
Size findreplace(const char *fstr, Size fsize, const char *str, Size size, Size max=ALL)
Find string and replace with string (modifier).
Definition: string.h:3949
String & operator=(const ListBase< wchar16, T > &str)
Assignment operator to convert from UTF-16 string to UTF-8 string.
Definition: string.h:942
This & operator<<(ulong num)
Append a formatted unsigned integer.
Definition: string.h:3523
bool set_unicode(const char16_t *str, Size size, UtfMode mode=umREPLACE_INVALID)
Set as normal UTF-8 string converted from a raw UTF-16 string.
Definition: string.h:1233
StringFlt(T num, int precision=fPREC_AUTO, bool terminated=true)
Constructor intializes with set().
Definition: string.h:256
int pad_width
Width to fill to, 0 for none, -1 if unspecified (use baseline or default) (default: 0) ...
Definition: str.h:2592
bool operator==(const String &str) const
Equality operator.
Definition: string.h:1632
String & add(const char *str)
Append null terminated string (modifier).
Definition: string.h:2790
char buffer[BUF_SIZE]
String buffer
Definition: string.h:60
String & prependn(int num, int base=fDEC)
Prepend formatted signed number (modifier).
Definition: string.h:3669
Error
General Evo error code stored in exceptions, or used directly when exceptions are disabled...
Definition: sys.h:1113
Key findanybutr(const StringBase &chars, Key start=0, Key end=END) const
Find last occurrence of any character not listed with reverse search.
Definition: string.h:2163
Advanced: Special structure used to avoid automatically allocating memory when a bigger buffer is nee...
Definition: string.h:218
Size writechar(char ch, Size count=1)
Write (append) repeat character as text output to string.
Definition: string.h:4266
const char * cstr()
Get terminated string pointer (modifier).
Definition: string.h:1571
uint getnewlinesize(Newline newline=NL)
Get newline string size for given type.
Definition: sys.h:804
FmtAlign
Formatting alignment.
Definition: str.h:2356
StringInt< T, PADDING > ThisType
This type.
Definition: string.h:55
const char * data() const
Get string pointer (const).
Definition: string.h:1533
bool empty() const
Get whether empty.
Definition: list.h:753
Size findreplace(char ch, const StringBase &str, Size max=ALL)
Find character and replace with string (modifier).
Definition: string.h:3938
uint32 StrSizeT
Default Evo string size type.
Definition: sys.h:734
Key findwordr(Key start=0, Key end=END) const
Find last word character with reverse search.
Definition: string.h:2191
bool tokenr_line(StringT &line)
Extract next line from string in reverse (from end of string).
Definition: string.h:1501
Base 10: decimal (default)
Definition: str.h:2323
String & strip2()
Strip left (beginning) and right (ending) whitespace from string, including newlines.
Definition: string.h:2557
String container.
Definition: string.h:674
String & operator=(const String &str)
Assignment operator.
Definition: string.h:868
String & set2(const ListType &str, Key index1, Key index2)
Set from substring of another string using start/end positions.
Definition: string.h:1097
const void * buf
Buffer to dump.
Definition: str.h:3295
Size insert(Key index, const StringBase &str)
Insert from another string (modifier).
Definition: string.h:3772
String & prepend(const ListType &str)
Prepend from another string (modifier).
Definition: string.h:3630
String & operator<<(float num)
Append operator to append formatted number.
Definition: string.h:3108
Size insert(Key index, char ch, Size count)
Insert copies of the same character (modifier).
Definition: string.h:3752
FloatD numfd() const
Convert to number value (double floating point).
Definition: string.h:4235
String & strip()
Strip left (beginning) and right (ending) whitespace (spaces and tabs).
Definition: string.h:2416
String & replace(Key index, Size rsize, const char *str, Size size)
Replace characters with string (modifier).
Definition: string.h:3901
String(const String &str)
Copy constructor.
Definition: string.h:692
String(String &&src)
Move constructor (C++11).
Definition: string.h:831
String & convert_set(C value)
Convert value to string, replacing current string.
Definition: string.h:4786
Key findanyr(const char *chars, Size count, Key start=0, Key end=END) const
Find last occurrence of any given characters with reverse search.
Definition: string.h:2060
String & prepend(char ch, Size count)
Prepend copies of the same character (modifier).
Definition: string.h:3619
String & operator<<(const FmtChar &fmt)
Append operator to append formatted character field.
Definition: string.h:3145
char * write_direct_multi(Size &available, Size reserve_size)
Get pointer for writing directly to buffer to append data and allow multiple passes for larger sizes...
Definition: string.h:4372
Key findnonword(Key start=0, Key end=END) const
Find first non-word word character.
Definition: string.h:2210
Definition: str.h:3003
String & operator<<(uint num)
Append operator to append formatted number.
Definition: string.h:3063
bool operator==(const PtrBase< T > &ptr1, const PtrBase< T, Atomic< T *> > &ptr2)
Equality operator for managed pointer base and atomic pointer base.
Definition: atomic.h:1193
String & operator<<(const FmtULong &fmt)
Append operator to append formatted number field.
Definition: string.h:3234
bool writefmtnumf(TNum num, const FmtSetFloat &fmt, const FmtSetField *field=NULL)
Write (append) formatted floating point number with field alignment.
Definition: string.h:4652
Size size
Buffer size required to format number (including PADDING), modified by format() to formatted size (ex...
Definition: string.h:219
T getnumf() const
Convert to floating point number value for given type.
Definition: string.h:4101
C::Size split(C &items, char delim=',') const
Split delimited string into item list using given tokenizer.
Definition: string.h:4902
String::ListBaseType StringBase
Base string typedef.
Definition: string.h:5372
Flush
Signals an output stream to flush pending data.
Definition: sys.h:739
T Type
Translated type.
Definition: meta.h:373
StrSizeT Size
Size type.
Definition: string.h:56
bool operator==(const ListBase< wchar16, T > &str)
Equality operator to compare against UTF-16 string.
Definition: string.h:1649
Evo List container.
bool operator!=(const ListBase< wchar16, T > &str)
Inequality operator to compare against UTF-16 string.
Definition: string.h:1675
String & add(const ListType &str)
Append from another string (modifier).
Definition: string.h:2762
String & insertn(Key index, ulongl num, int base=fDEC)
Insert formatted unsigned number (modifier).
Definition: string.h:3843
String & stripl_newlines(Size max)
Strip left (beginning) newlines from string.
Definition: string.h:2623
ThisType & add(const char *data, Size size)
Append additional data to buffer.
Definition: string.h:139
String & setn(int num, int base=fDEC)
Set as formatted signed number (modifier).
Definition: string.h:1117
int exponent
Exponent for normalized floating point number to format.
Definition: string.h:221
static void set(C &dest, T value)=delete
Set target to value (reversed conversion).
static const EndT END
Special integer value for indicating end of items or no item.
Definition: type.h:1846
String & addn(int num, int base=fDEC)
Append formatted signed number (modifier).
Definition: string.h:2807
void merge(const FmtSetInt &src)
Merge source attributes (used internally).
Definition: str.h:2626
const char * str
Pointer to string for formatting null values, ignored if size is 0.
Definition: str.h:2407
Align center by adding filler on left and right sides.
Definition: str.h:2359
bool writefmtstr(const char *str, Size size, const FmtSetField &field)
Write (append) text with field alignment.
Definition: string.h:4531
static const EndT ALL
Special integer value for indicating all items or all remaining items.
Definition: type.h:1839
void merge(const FmtSetField &src)
Merge source attributes (used internally).
Definition: str.h:2514
Format This
This type.
Definition: string.h:3318
Iter cbegin() const
Get iterator at first item (const).
Definition: string.h:1705
Explicitly format an integer.
Definition: str.h:3065
String & capacitymin(Size min)
Set minimum capacity (modifier).
Definition: string.h:5015
String & strip_newlines()
Strip left (beginning) and right (ending) newlines from string.
Definition: string.h:2693
char * write_direct(Size size)
Get pointer for writing directly to buffer to append data.
Definition: string.h:4357
String & joinmapq(const C &map, char delim=',', char kvdelim='=')
Join map items into delimited string, with quoting as needed.
Definition: string.h:4880
const char * str_scan_nws_r(const char *str, const char *end)
Scan string pointer for next non-whitespace character in reverse and return new end after stop pointe...
Definition: strscan.h:896
String & insert(Key index, const char *str)
Insert null terminated string (modifier).
Definition: string.h:3789
char * data()
Get formatted string pointer.
Definition: string.h:268
bool set_unicode(const wchar16 *str, UtfMode mode=umREPLACE_INVALID)
Set as normal UTF-8 string converted from a raw terminated UTF-16 string.
Definition: string.h:1227
const char * getnewline() const
Get newline string pointer for current value.
Definition: sys.h:885
bool operator!=(const PtrBase< T > &ptr1, const PtrBase< T, Atomic< T *> > &ptr2)
Inequality operator for managed pointer base and atomic pointer base.
Definition: atomic.h:1202
String & join(const C &items, char delim=',')
Join list items into delimited string.
Definition: string.h:4820
const char * cstrM() const
Get terminated string pointer (modifier).
Definition: string.h:1607
Format(Out &out)
Constructor.
Definition: string.h:3326
bool writefmtnum(TNum num, const FmtSetInt &fmt, const FmtSetField *field=NULL)
Write (append) formatted signed number with field alignment.
Definition: string.h:4583
String & operator<<(longl num)
Append operator to append formatted number.
Definition: string.h:3048
String & setempty()
Set as empty but not null.
Definition: string.h:982
String & stripl()
Strip left (beginning) whitespace (spaces and tabs).
Definition: string.h:2449
String & prependn(double num, int precision=fPREC_AUTO)
Prepend formatted floating point number (modifier).
Definition: string.h:3725
String fixed-size buffer for formatting a floating point number.
Definition: string.h:204
String & operator<<(ldouble num)
Append operator to append formatted number.
Definition: string.h:3138
String & operator<<(const FmtFloatL &fmt)
Append operator to append formatted number field.
Definition: string.h:3250
String & operator<<(char ch)
Append operator.
Definition: string.h:2900
FmtAlign align
Field alignment type (default: fLEFT)
Definition: str.h:2482
static const String & whitespace()
Get string of ASCII whitespace characters (space, tab).
Definition: string.h:5081
This & operator<<(FmtBase base)
Set base for formatting integers.
Definition: string.h:3471
char ascii_toupper(char ch)
Convert ASCII character to uppercase.
Definition: str.h:105
FmtPrecision
Formatting floating point precision type.
Definition: str.h:2341
String & operator<<(const FmtUShort &fmt)
Append operator to append formatted number field.
Definition: string.h:3226
This & operator<<(const FmtDump &fmtdump)
Definition: string.h:3601
String & slice(Key index, Size size)
Slice to given sublist.
Definition: string.h:4995
Key findr(StringSearchAlg alg, const char *pattern, uint pattern_size, Key start=0, Key end=END) const
Find last occurrence of pattern string with reverse search.
Definition: string.h:1957
This & operator<<(const FmtChar &ch)
Append a repeated character.
Definition: string.h:3430
FmtSetInt fmt
Formatting attributes.
Definition: str.h:3266
String::Size Size
String data size type
Definition: string.h:3316
String & fillch(char ch, Key index=0, Size size=ALL)
Fill with copies of character (modifier).
Definition: string.h:3880
bool contains(const StringBase &str) const
Check whether contains given string.
Definition: string.h:2259
String & operator<<(const FmtShort &fmt)
Append operator to append formatted number field.
Definition: string.h:3210
String & setn(long num, int base=fDEC)
Set as formatted signed number (modifier).
Definition: string.h:1125
Double-quotes: "
Definition: strscan.h:1899
void merge(const FmtSetFloat &src)
Merge from source (used internally).
Definition: str.h:2806
T number
Normalized floating point number to format.
Definition: string.h:220
Key findr(const char *pattern, uint pattern_size, Key start=0, Key end=END) const
Find last occurrence of pattern string with reverse search.
Definition: string.h:1936
char * data()
Get formatted string pointer.
Definition: string.h:85
String & operator<<(double num)
Append operator to append formatted number.
Definition: string.h:3123
String & stripl(char ch, Size max=ALL)
Strip left (beginning) occurrences of character.
Definition: string.h:2465
bool ends(char ch) const
Check if this ends with given character.
Definition: string.h:1694
Triple double-quotes: """
Definition: strscan.h:1902
Evo C++ Library namespace.
Definition: alg.h:11
ListBaseType StringBase
Alias for ListBaseType.
Definition: string.h:680
String & operator=(const char *str)
Assignment operator for null terminated string.
Definition: string.h:911
StringSearchAlg
String search algorithm selection.
Definition: str.h:1164
static const EndT NONE
Special integer value for indicating no item or unknown item.
Definition: type.h:1832
Size insert(Key index, const char *str, Size size)
Insert string data (modifier).
Definition: string.h:3781
String(const UnicodeStringBase &str)
Constructor to convert from UTF-16 string to UTF-8 string.
Definition: string.h:765
This & operator<<(FmtBasePrefix prefix)
Set prefix for formatting integers.
Definition: string.h:3478
Size capacity() const
Get capacity.
Definition: string.h:5007
String & operator<<(const FmtInt &fmt)
Append operator to append formatted number field.
Definition: string.h:3214
bool set_unicode(const char16_t *str, UtfMode mode=umREPLACE_INVALID)
Set as normal UTF-8 string converted from a raw terminated UTF-16 string.
Definition: string.h:1239
FmtAttribs fmt
Formatting attributes (state)
Definition: string.h:3321
Holds floating point formatting attributes.
Definition: str.h:2775
uint getnewlinesize() const
Get newline string size for current value.
Definition: sys.h:909
This & operator<<(float num)
Append a formatting floating point number.
Definition: string.h:3571
Explicitly format a string.
Definition: str.h:2931
Uppercase alphabetic character (A-Z)
Definition: str.h:54
String & insertn(Key index, int num, int base=fDEC)
Insert formatted signed number (modifier).
Definition: string.h:3798
This & operator<<(ushort num)
Append a formatted unsigned integer.
Definition: string.h:3515
Iter begin() const
Get iterator at first item (const).
Definition: string.h:1734
Replace invalid characters with UNICODE_REPLACEMENT_CHAR.
Definition: str.h:138
Iter end() const
Get iterator at end.
Definition: string.h:1754
String & prependn(ulongl num, int base=fDEC)
Prepend formatted unsigned number (modifier).
Definition: string.h:3709
UtfMode
UTF decoding mode used to set how to handle invalid character values.
Definition: str.h:136
String & insertn(Key index, ulong num, int base=fDEC)
Insert formatted unsigned number (modifier).
Definition: string.h:3834
String & set_win32(const WCHAR *str)
Set as normal (UTF-8) string converted from a terminated Windows UTF-16 (WCHAR) string (Windows only)...
Definition: string.h:1285
This & operator<<(Newline nl)
Append a newline.
Definition: string.h:3381
String(const char16_t *str, UtfMode mode=umREPLACE_INVALID)
Constructor to initialize and convert from terminated UTF-16 string literal (using u prefix)...
Definition: string.h:813
String & unslice()
Clean and remove hidden items previously removed via slicing (modifier).
Definition: string.h:5003
String(const PtrBase< char > &str, Size size)
Constructor for managed string pointer.
Definition: string.h:750
bool contains(char ch) const
Check whether this contains given character.
Definition: string.h:2244
String & operator<<(const FmtDump &fmt)
Append operator to append data dump.
Definition: string.h:3279
T num
Definition: str.h:3155
T getnumf(Error &error) const
Convert to floating point number value for given type.
Definition: string.h:4084
String & unshare()
Make data unique by allocating new buffer, if needed (modifier).
Definition: string.h:5031
FmtSetInt fmt
Formatting attributes.
Definition: str.h:3072
String & stripr_newlines(Size max)
Strip right (ending) newlines from string.
Definition: string.h:2666
String & add(char ch, Size count)
Append copies of the same character (modifier).
Definition: string.h:2749
Size Key
Key type (item index)
Definition: list.h:248
String & addn(longl num, int base=fDEC)
Append formatted signed number (modifier).
Definition: string.h:2823
int precision
Floating point precision (number of digits after decimal), fPREC_AUTO for automatic (default: fPREC_A...
Definition: str.h:2776
ThisType & tolower()
Convert all uppercase characters in string to lowercase (modifier).
Definition: string.h:4955
String & replace(Key index, Size rsize, const char *str)
Replace characters with string (modifier).
Definition: string.h:3910
Size findreplace(const StringBase &fstr, const char *str, Size size, Size max=ALL)
Find string and replace with string (modifier).
Definition: string.h:3987
String(const PtrBase< char > &str)
Constructor to copy null terminated string from managed pointer.
Definition: string.h:787
Key findr(StringSearchAlg alg, const StringBase &pattern, Key start=0, Key end=END) const
Find last occurrence of pattern string with reverse search.
Definition: string.h:1996
String & addsep(char delim=',')
Append separator/delimiter if needed (modifier).
Definition: string.h:2799
bool write_direct_finish(Size size)
Finish writing directly to buffer.
Definition: string.h:4406
This & operator<<(double num)
Append a formatting floating point number.
Definition: string.h:3575
This & operator<<(const char *val)
Append a terminated string.
Definition: string.h:3441
String & insertn(Key index, double num, int precision=fPREC_AUTO)
Insert formatted floating point number (modifier).
Definition: string.h:3861
String & operator=(String &&src)
Move assignment operator (C++11).
Definition: string.h:838
String & stripl2()
Strip left (beginning) whitespace from string, including newlines.
Definition: string.h:2573
const String & asconst() const
Explicitly use a const reference to this.
Definition: string.h:856
Check if integer type is unsigned.
Definition: meta.h:296
C::Size splitmap(C &map, char delim=',', char kvdelim='=') const
Split delimited string into map key/value items.
Definition: string.h:4921
DataCopy< char >::PassType ItemVal
Item type as parameter (POD types passed by value, otherwise by const-ref)
Definition: list.h:251
Size writetext(const char *buf, Size size)
Write (append) text output to string.
Definition: string.h:4290
static const Newline NL_SYS
Current system newline type.
Definition: sys.h:763
bool splitr(char delim, T1 &left) const
Split at last occurrence of delimiter into left substring.
Definition: string.h:2373
static T fexp10(int &exp, T num)
Extract normalized base 10 mantissa and exponent from number.
Definition: type.h:1438
List< char, StrSizeT > ListType
List type.
Definition: string.h:677
char * data_
Data pointer, NULL if null.
Definition: sys.h:979
Backtick followed by DEL char (7F) – last resort (rare)
Definition: strscan.h:1904
P ptr_
Pointer.
Definition: type.h:1566
This & operator<<(ulongl num)
Append a formatted unsigned integer.
Definition: string.h:3527
T getnum(Error &error, int base=0) const
Convert to number value for given integer type.
Definition: string.h:4045
String & add(char ch)
Append character (modifier).
Definition: string.h:2741
String & setn(ulongl num, int base=fDEC)
Set as formatted unsigned number (modifier).
Definition: string.h:1157
Key findany(const char *chars, Size count, Key start=0, Key end=END) const
Find first occurrence of any given characters with forward search.
Definition: string.h:2016
bool operator!=(const String &str) const
Inequality operator.
Definition: string.h:1658
Size findreplace(const char *fstr, Size fsize, const StringBase &str, Size max=ALL)
Find string and replace with string (modifier).
Definition: string.h:3968
This & operator<<(const FmtSetFloat &fmt_flt)
Set floating point formatting attributes.
Definition: string.h:3562
This & operator<<(uint num)
Append a formatted unsigned integer.
Definition: string.h:3519
StringInt(T num, int base=fDEC, bool terminated=true, uint end_padding=0)
Constructor intializes with set().
Definition: string.h:77
Explicitly format a repeated character.
Definition: str.h:2914
Align left by adding filler on right side.
Definition: str.h:2358
This & operator<<(ldouble num)
Append a formatting floating point number.
Definition: string.h:3579
C convert() const
Convert string to value of given type.
Definition: string.h:4776
int base
Base for formatting (default: fDEC)
Definition: str.h:2590
Iter cend() const
Get iterator at end (const).
Definition: string.h:1715
ThisType & toupper()
Convert all lowercase characters in string to uppercase (modifier).
Definition: string.h:4932
char * addnew(Size size)
Add additional space to buffer and return pointer to new uninitialized space in buffer.
Definition: string.h:155
Explicitly format a pointer.
Definition: str.h:3264
String & operator<<(const FmtString &fmt)
Append operator to append formatted string field.
Definition: string.h:3152
FmtWidth
Formatting field width.
Definition: str.h:2367
String & addn(uint num, int base=fDEC)
Append formatted unsigned number (modifier).
Definition: string.h:2831
String & prependn(float num, int precision=fPREC_AUTO)
Prepend formatted floating point number (modifier).
Definition: string.h:3717
String & operator<<(const StringBase &str)
Append operator.
Definition: string.h:2930
int precision
Precision to format.
Definition: string.h:222
StrSizeT size
String (str) size for formatting null values, 0 for none/empty
Definition: str.h:2408
String & addn(ulong num, int base=fDEC)
Append formatted unsigned number (modifier).
Definition: string.h:2839
static const String & lettersu()
Get string of ASCII uppercase letters (A-Z).
Definition: string.h:5069
FmtSetField field
Field alignment attributes.
Definition: str.h:2890
String & truncate(Size size=0)
Truncate to given size.
Definition: string.h:4987
bool set_unicode(const wchar16 *str, Size size, UtfMode mode=umREPLACE_INVALID)
Set as normal UTF-8 string converted from a raw UTF-16 string.
Definition: string.h:1196
int indent
Definition: str.h:3008
Key findr(char ch) const
Find last occurrence of character with reverse search.
Definition: string.h:1879
static Type get(const char *data, ulong data_size)
Definition: strscan.h:1917
NumInfo()
Constructor.
Definition: string.h:226
bool contains(const char *str, Size size) const
Check whether this contains given string.
Definition: string.h:2252
String & operator=(const PtrBase< char > &str)
Assignment operator to copy from managed pointer with null terminated string.
Definition: string.h:927
bool valid() const
Get whether valid (not null).
Definition: type.h:324
static bool addq(C &dest, T value, typename C::Value delim)=delete
Add/Append value to target with quoting when needed (reversed conversion).
String & prepend(char ch)
Prepend character (modifier).
Definition: string.h:3611
String & setn(ldouble num, int precision=fPREC_AUTO)
Set as formatted floating point number (modifier).
Definition: string.h:1181
FmtBasePrefix prefix
Formatting prefix type (default: fPREFIX0)
Definition: str.h:2591
IterM end()
Get iterator at end.
Definition: string.h:1744
String & advResize(Size size)
Advanced: Resize while preserving existing data, POD items not initialized (modifier).
Definition: string.h:5043
StrSizeT size_
Data size as item count, 0 if empty or null.
Definition: sys.h:980
String & setn(float num, int precision=fPREC_AUTO)
Set as formatted floating point number (modifier).
Definition: string.h:1165
Nullable basic floating-point base type.
Definition: type.h:1291
StringBase str
Definition: str.h:2936
Sequential list container with random access.
Definition: list.h:240
Key findanybut(const char *chars, Size count, Key start=0, Key end=END) const
Find first occurrence of any character not listed with forward search.
Definition: string.h:2099
String(const StringBase &str, Key index=0, Key size=ALL)
Constructor to copy substring data.
Definition: string.h:729
String & copy(const StringBase &str)
Set as full (unshared) copy of substring (modifier).
Definition: string.h:2712
Key findnonwordr(Key start=0, Key end=END) const
Find last non-word character with reverse search.
Definition: string.h:2229
Size insert(Key index, char ch)
Insert character (modifier).
Definition: string.h:3743
static void setup_align(int &align_padleft, int &align_padright, int align_padding, const FmtSetField *field)
Used to setup and calculate alignment padding (used internally).
Definition: str.h:2529
FmtBasePrefix
Formatting integer base prefix type.
Definition: str.h:2331
Format(const This &src)
Copy constructor.
Definition: string.h:3334
String & add(const char *str, Size size)
Append from string pointer (modifier).
Definition: string.h:2781
int width
Field width to align in (default: 0)
Definition: str.h:2483
StringFlt< T, PADDING > ThisType
This type.
Definition: string.h:205
String & operator<<(const char *str)
Append operator.
Definition: string.h:2945
bool writefmtnumu(TNum num, const FmtSetInt &fmt, const FmtSetField *field=NULL)
Write (append) formatted unsigned number with field alignment.
Definition: string.h:4604
Lowercase alphabetic character (a-z)
Definition: str.h:55
StrSizeT Size
Size type.
Definition: string.h:206
const void * ptr
Pointer to format.
Definition: str.h:3265
String & set()
Set as null and empty.
Definition: string.h:995
Punctuation used before a word begins, break words before this ( ([{< )
Definition: str.h:63
Align right by adding filler on left side.
Definition: str.h:2360
String & addn(float num, int precision=fPREC_AUTO)
Append formatted floating point number (modifier).
Definition: string.h:2855
String & operator<<(const FmtStringWrap &fmt)
Append operator to append formatted wrapped string column.
Definition: string.h:3159
static const String & digits()
Get string of all ASCII alphanumeric digits with uppercase letters (0-9, A-Z).
Definition: string.h:5051
StringInt()
Constructor intializes to null.
Definition: string.h:66
static const int BUF_SIZE
Buffer size.
Definition: string.h:58
String & operator<<(const FmtPtr &fmtptr)
Append operator to append formatted pointer field.
Definition: string.h:3272
String & operator<<(const ListType &str)
Append operator.
Definition: string.h:2915
Base managed pointer.
Definition: type.h:1562
This & operator<<(const FmtSetField &field)
Set field attributes to use.
Definition: string.h:3372
FmtSetInt num_int
Integer attributes.
Definition: str.h:2888
int utf16_compare8(const wchar16 *str1, ulong len1, const char *str2, ulong len2)
Compare a non-terminated UTF-16 string to a non-terminated UTF-8 string.
Definition: str.h:842
char ch
Character to format.
Definition: str.h:2915
FmtSetField fmt
Definition: str.h:2937
String & stripr(const char *str, Size strsize, Size max=ALL)
Strip right (ending) occurences of string.
Definition: string.h:2534
String & prepend(const StringBase &str)
Prepend from another string (modifier).
Definition: string.h:3637
String & stripr_newlines()
Strip all right (ending) newlines from string.
Definition: string.h:2652
char * write_direct_flush(Size &available, Size written_size, Size reserve_size)
Flush data written directly to buffer and get pointer for appending more.
Definition: string.h:4390
String & operator<<(ulongl num)
Append operator to append formatted number.
Definition: string.h:3093
ListBase< wchar16, Size > UnicodeStringBase
Base for UnicodeString.
Definition: string.h:681
String & convert_add(C value)
Convert value to string, appending to current string.
Definition: string.h:4796
This & operator<<(Flush)
Flush output buffer – no-op for string.
Definition: string.h:3389
String(const char *str, Size size)
Constructor for string pointer.
Definition: string.h:739
Out & write_out()
Get parent output string.
Definition: string.h:4256
bool starts(char ch) const
Check if this starts with given character.
Definition: string.h:1687
Base for all Evo list types (used internally).
Definition: sys.h:976
String & insertn(Key index, ldouble num, int precision=fPREC_AUTO)
Insert formatted floating point number (modifier).
Definition: string.h:3870
Explicitly format a floating pointer number.
Definition: str.h:3148
T & min(T &a, T &b)
Returns lowest of given values.
Definition: alg.h:26
bool token(StringT &value, char delim)
Extract next token from string.
Definition: string.h:1318
Holds field and alignment formatting attributes.
Definition: str.h:2481
This & operator<<(short num)
Append a formatted signed integer.
Definition: string.h:3494
Key find(StringSearchAlg alg, const char *pattern, uint pattern_size, Key start=0, Key end=END) const
Find first occurrence of pattern string using specified algorithm.
Definition: string.h:1824
Key findr(char ch, Key start, Key end=END) const
Find last occurrence of character with reverse search.
Definition: string.h:1904
String & prepend(const char *str)
Prepend null terminated string (modifier).
Definition: string.h:3652
#define STATIC_ASSERT(EXP, TOKEN)
Assert compile-time expression is true or trigger compiler error.
Definition: meta.h:54
T num
Number to format.
Definition: str.h:3071
NewlineValue newline
Definition: str.h:3009
Key findany(const StringBase &chars, Key start=0, Key end=END) const
Find first occurrence of any given characters with forward search.
Definition: string.h:2046
String & setn(uint num, int base=fDEC)
Set as formatted unsigned number (modifier).
Definition: string.h:1141
Float numf() const
Convert to number value (floating point).
Definition: string.h:4222
bool tokenr(StringT &value, char delim)
Extract next token from string in reverse (from end of string).
Definition: string.h:1349
FmtSetNull null
String to use for null values from strings (like String) or primitives (like Int) ...
Definition: str.h:2887
String & compact()
Reduce capacity to fit current size (modifier).
Definition: string.h:5023
bool split(char delim, T1 &left) const
Split at first occurrence of delimiter into left substring.
Definition: string.h:2301
String & capacity(Size size)
Set new capacity (modifier).
Definition: string.h:5011
String(const std::initializer_list< char > &init)
Sequence constructor (C++11).
Definition: string.h:820
Data not quotable (invalid text)
Definition: strscan.h:1905
Size size() const
Get formatting string size.
Definition: string.h:93
String & prependn(ldouble num, int precision=fPREC_AUTO)
Prepend formatted floating point number (modifier).
Definition: string.h:3733
String & add(const StringBase &str)
Append from another string (modifier).
Definition: string.h:2771
String & set_win32(const WCHAR *str, int size)
Set as normal (UTF-8) string converted from a Windows UTF-16 (WCHAR) string (Windows only)...
Definition: string.h:1255
Explicitly format a hex dump from buffer.
Definition: str.h:3294
FmtBase
Formatting integer base.
Definition: str.h:2318
Key find(StringSearchAlg alg, const StringBase &pattern, Key start=0, Key end=END) const
Find first occurrence of pattern string using specified algorithm.
Definition: string.h:1863
#define EVO_PARAM_UNUSED(NAME)
Mark function parameter as unused to suppress "unreferenced parameter" compiler warnings on it...
Definition: sys.h:427
bool operator==(const char *str) const
Equality operator.
Definition: string.h:1639
Current alignment (i.e. unspecified/default)
Definition: str.h:2357
FmtSetFloat num_flt
Floating point attributes.
Definition: str.h:2889
bool writenum(TNum num, int base=fDEC)
Write (append) formatted signed number.
Definition: string.h:4418
String & operator<<(int num)
Append operator to append formatted number.
Definition: string.h:3018
ulong utf16_to8(const wchar16 *&str, const wchar16 *end, char *outbuf=NULL, ulong outsize=0, UtfMode mode=umREPLACE_INVALID)
Convert UTF-16 string to UTF-8 string.
Definition: str.h:1053
Type
Quoting type.
Definition: strscan.h:1897
String & operator=(const ListType &str)
Assignment operator.
Definition: string.h:877
String & reserve(Size size, bool prefer_realloc=false)
Reserve capacity for additional items (modifier).
Definition: string.h:5027
bool writenumf(TNum num, int precision=fPREC_AUTO)
Write (append) formatted floating-point number.
Definition: string.h:4448