ucommon  7.0.0
About: GNU uCommon C++ is a portable and optimized class framework for writing C++ applications that need to use threads and support concurrent synchronization, and that use sockets, XML parsing, object serialization, thread-optimized string and data structure classes, etc..
  Fossies Dox: ucommon-7.0.0.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

string.cpp
Go to the documentation of this file.
1 // Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
2 // Copyright (C) 2015 Cherokees of Idaho.
3 //
4 // This file is part of GNU uCommon C++.
5 //
6 // GNU uCommon C++ is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU Lesser General Public License as published
8 // by the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // GNU uCommon C++ is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public License
17 // along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
18 
19 #include <ucommon-config.h>
20 #include <ucommon/export.h>
21 #include <ucommon/string.h>
22 #include <stdarg.h>
23 #include <ctype.h>
24 #include <stdio.h>
25 #ifdef HAVE_FCNTL_H
26 #include <fcntl.h>
27 #endif
28 #include <limits.h>
29 
30 namespace ucommon {
31 
34 {
35  max = size;
36  len = 0;
37  text[0] = 0;
38 }
39 
41 {
42  text[len] = 0;
43 }
44 
46 {
47  if(offset >= len)
48  return;
49 
50  text[offset] = 0;
51  len = offset;
52 }
53 
55 {
56  if(!len)
57  return;
58 
59  if(offset >= len) {
60  text[0] = 0;
61  len = 0;
62  fix();
63  return;
64  }
65 
66  text[--len] = 0;
67 }
68 
70 {
71  if(!offset)
72  ++offset;
73 
74  if(offset >= len) {
75  text[0] = 0;
76  len = 0;
77  fix();
78  return;
79  }
80 
81  memmove(text, text + offset, len - offset);
82  len -= offset;
83  fix();
84 }
85 
86 void String::cstring::add(const char *str)
87 {
88  size_t size = strlen(str);
89 
90  if(!size)
91  return;
92 
93  if(len + size > max)
94  size = max - len;
95 
96  if(size < 1)
97  return;
98 
99  memcpy(text + len, str, size);
100  len += size;
101  fix();
102 }
103 
105 {
106  if(!ch)
107  return;
108 
109  if(len == max)
110  return;
111 
112  text[len++] = ch;
113  fix();
114 }
115 
116 void String::cstring::set(size_t offset, const char *str, size_t size)
117 {
118  assert(str != NULL);
119 
120  if(offset >= max || offset > len)
121  return;
122 
123  if(offset + size > max)
124  size = max - offset;
125 
126  while(*str && size) {
127  text[offset++] = *(str++);
128  --size;
129  }
130 
131  if(offset > len) {
132  len = offset;
133  text[len] = 0;
134  }
135 }
136 
137 size_t String::size(void) const
138 {
139  if(!str)
140  return 0;
141 
142  return str->max;
143 }
144 
145 size_t String::len(void) const
146 {
147  if(!str)
148  return 0;
149 
150  return str->len;
151 }
152 
153 void String::cstring::set(const char *str)
154 {
155  assert(str != NULL);
156 
157  size_t size = strlen(str);
158  if(size > max)
159  size = max;
160 
161  if(str < text || str > text + len)
162  memcpy(text, str, size);
163  else if(str != text)
164  memmove(text, str, size);
165  len = size;
166  fix();
167 }
168 
170 {
171  str = NULL;
172 }
173 
174 String::String(const char *s, const char *end)
175 {
176  size_t size = 0;
177 
178  if(!s)
179  s = "";
180  else if(!end)
181  size = strlen(s);
182  else if(end > s)
183  size = (size_t)(end - s);
184  str = create(size);
185  str->retain();
186  str->set(s);
187 }
188 
189 String::String(const char *s)
190 {
191  size_t size = count(s);
192  if(!s)
193  s = "";
194  str = create(size);
195  str->retain();
196  str->set(s);
197 }
198 
199 String::String(const char *s, size_t size)
200 {
201  if(!s)
202  s = "";
203  if(!size)
204  size = strlen(s);
205  str = create(size);
206  str->retain();
207  str->set(s);
208 }
209 
211 {
212  str = create(size);
213  str->retain();
214 }
215 
216 String::String(size_t size, const char *format, ...)
217 {
218  assert(format != NULL);
219 
220  va_list args;
221  va_start(args, format);
222 
223  str = create(size);
224  str->retain();
225  vsnprintf(str->text, size + 1, format, args);
226  va_end(args);
227 }
228 
230 {
231  str = dup.c_copy();
232  if(str)
233  str->retain();
234 }
235 
237 {
238  String::release();
239 }
240 
242 {
243  return str;
244 }
245 
246 String String::get(size_t offset, size_t len) const
247 {
248  if(!str || offset >= str->len)
249  return String("");
250 
251  if(!len)
252  len = str->len - offset;
253  return String(str->text + offset, len);
254 }
255 
257 {
258  void *mem = ::malloc(size + sizeof(cstring));
259  return new(mem) cstring(size);
260 }
261 
263 {
264  this->cstring::~cstring();
265  ::free(this);
266 }
267 
268 void String::retain(void)
269 {
270  if(str)
271  str->retain();
272 }
273 
274 void String::release(void)
275 {
276  if(str)
277  str->release();
278  str = NULL;
279 }
280 
281 char *String::data(void)
282 {
283  if(!str)
284  return NULL;
285 
286  return str->text;
287 }
288 
289 const char *String::c_str(void) const
290 {
291  if(!str)
292  return "";
293 
294  return str->text;
295 }
296 
297 bool String::equal(const char *s) const
298 {
299 #ifdef HAVE_STRCOLL
300  const char *mystr = "";
301 
302  if(str)
303  mystr = str->text;
304 
305  if(!s)
306  s = "";
307 
308  return strcmp(mystr, s) == 0;
309 #else
310  return compare(s) == 0;
311 #endif
312 }
313 
314 int String::compare(const char *s) const
315 {
316  const char *mystr = "";
317 
318  if(str)
319  mystr = str->text;
320 
321  if(!s)
322  s = "";
323 
324 #ifdef HAVE_STRCOLL
325  return strcoll(mystr, s);
326 #else
327  return strcmp(mystr, s);
328 #endif
329 }
330 
331 const char *String::begin(void) const
332 {
333  if(!str)
334  return NULL;
335 
336  return str->text;
337 }
338 
339 const char *String::end(void) const
340 {
341  if(!str)
342  return NULL;
343 
344  return str->text + str->len;
345 }
346 
347 const char *String::chr(char ch) const
348 {
349  assert(ch != 0);
350 
351  if(!str)
352  return NULL;
353 
354  return ::strchr(str->text, ch);
355 }
356 
357 const char *String::rchr(char ch) const
358 {
359  assert(ch != 0);
360 
361  if(!str)
362  return NULL;
363 
364  return ::strrchr(str->text, ch);
365 }
366 
367 const char *String::skip(const char *clist, size_t offset) const
368 {
369  if(!str || !clist || !*clist || !str->len || offset > str->len)
370  return NULL;
371 
372  while(offset < str->len) {
373  if(!strchr(clist, str->text[offset]))
374  return str->text + offset;
375  ++offset;
376  }
377  return NULL;
378 }
379 
380 const char *String::rskip(const char *clist, size_t offset) const
381 {
382  if(!str || !clist || !*clist)
383  return NULL;
384 
385  if(!str->len)
386  return NULL;
387 
388  if(offset > str->len)
389  offset = str->len;
390 
391  while(offset--) {
392  if(!strchr(clist, str->text[offset]))
393  return str->text + offset;
394  }
395  return NULL;
396 }
397 
398 const char *String::rfind(const char *clist, size_t offset) const
399 {
400  if(!str || !clist || !*clist)
401  return NULL;
402 
403  if(!str->len)
404  return str->text;
405 
406  if(offset > str->len)
407  offset = str->len;
408 
409  while(offset--) {
410  if(strchr(clist, str->text[offset]))
411  return str->text + offset;
412  }
413  return NULL;
414 }
415 
416 void String::chop(const char *clist)
417 {
418  size_t offset;
419 
420  if(!str)
421  return;
422 
423  if(!str->len)
424  return;
425 
426  offset = str->len;
427  while(offset) {
428  if(!strchr(clist, str->text[offset - 1]))
429  break;
430  --offset;
431  }
432 
433  if(!offset) {
434  clear();
435  return;
436  }
437 
438  if(offset == str->len)
439  return;
440 
441  str->len = offset;
442  str->fix();
443 }
444 
445 void String::strip(const char *clist)
446 {
447  trim(clist);
448  chop(clist);
449 }
450 
451 void String::trim(const char *clist)
452 {
453  unsigned offset = 0;
454 
455  if(!str)
456  return;
457 
458  while(offset < str->len) {
459  if(!strchr(clist, str->text[offset]))
460  break;
461  ++offset;
462  }
463 
464  if(!offset)
465  return;
466 
467  if(offset == str->len) {
468  clear();
469  return;
470  }
471 
472  memmove(str->text, str->text + offset, str->len - offset);
473  str->len -= offset;
474  str->fix();
475 }
476 
477 unsigned String::replace(const char *substring, const char *cp, unsigned flags)
478 {
479  const char *result = "";
480  unsigned count = 0;
481  size_t cpl = 0;
482 
483  if(cp)
484  cpl = strlen(cp);
485 
486  if(!str || !substring || str->len == 0)
487  return 0;
488 
489  size_t offset = 0;
490 
491  size_t tcl = strlen(substring);
492 
493  while(result) {
494  const char *text = str->text + offset;
495 #if defined(_MSWINDOWS_)
496  if((flags & 0x01) == INSENSITIVE)
497  result = strstr(text, substring);
498 #elif defined(HAVE_STRICMP)
499  if((flags & 0x01) == INSENSITIVE)
500  result = stristr(text, substring);
501 #else
502  if((flags & 0x01) == INSENSITIVE)
503  result = strcasestr(text, substring);
504 #endif
505  else
506  result = strstr(text, substring);
507 
508  if(result) {
509  ++count;
510  offset = (size_t)(text - str->text);
511  cut(offset, tcl);
512  if(cpl) {
513  paste(offset, cp);
514  offset += cpl;
515  }
516  }
517  }
518  return count;
519 }
520 
521 const char *String::search(const char *substring, unsigned instance, unsigned flags) const
522 {
523  const char *result = "";
524 
525  if(!str || !substring || str->len == 0)
526  return NULL;
527 
528  const char *text = str->text;
529 
530  if(!instance)
531  ++instance;
532  while(instance-- && result) {
533 #if defined(_MSWINDOWS_)
534  if((flags & 0x01) == INSENSITIVE)
535  result = strstr(text, substring);
536 #elif defined(HAVE_STRICMP)
537  if((flags & 0x01) == INSENSITIVE)
538  result = stristr(text, substring);
539 #else
540  if((flags & 0x01) == INSENSITIVE)
541  result = strcasestr(text, substring);
542 #endif
543  else
544  result = strstr(text, substring);
545 
546  if(result)
547  text = result + strlen(result);
548  }
549  return result;
550 }
551 
552 const char *String::find(const char *clist, size_t offset) const
553 {
554  if(!str || !clist || !*clist || !str->len || offset > str->len)
555  return NULL;
556 
557  while(offset < str->len) {
558  if(strchr(clist, str->text[offset]))
559  return str->text + offset;
560  ++offset;
561  }
562  return NULL;
563 }
564 
565 bool String::unquote(const char *clist)
566 {
567  assert(clist != NULL);
568 
569  char *s;
570 
571  if(!str)
572  return false;
573 
574  s = unquote(str->text, clist);
575  if(!s) {
576  str->fix();
577  return false;
578  }
579 
580  set(s);
581  return true;
582 }
583 
584 void String::upper(void)
585 {
586  if(str)
587  upper(str->text);
588 }
589 
590 void String::lower(void)
591 {
592  if(str)
593  lower(str->text);
594 }
595 
596 void String::erase(void)
597 {
598  if(str) {
599  memset(str->text, 0, str->max);
600  str->fix();
601  }
602 }
603 
604 size_t String::offset(const char *s) const
605 {
606  if(!str || !s)
607  return npos;
608 
609  if(s < str->text || s > str->text + str->max)
610  return npos;
611 
612  if((size_t)(s - str->text) > str->len)
613  return str->len;
614 
615  return (size_t)(s - str->text);
616 }
617 
618 size_t String::count(void) const
619 {
620  if(!str)
621  return 0;
622  return str->len;
623 }
624 
625 size_t String::ccount(const char *clist) const
626 {
627  if(!str)
628  return 0;
629 
630  return ccount(str->text, clist);
631 }
632 
633 size_t String::printf(const char *format, ...)
634 {
635  assert(format != NULL);
636 
637  va_list args;
638  va_start(args, format);
639  if(str) {
640  vsnprintf(str->text, str->max + 1, format, args);
641  str->len = strlen(str->text);
642  str->fix();
643  }
644  va_end(args);
645  return len();
646 }
647 
648 size_t String::vprintf(const char *format, va_list args)
649 {
650  assert(format != NULL);
651 
652  if(str) {
653  vsnprintf(str->text, str->max + 1, format, args);
654  str->len = strlen(str->text);
655  str->fix();
656  }
657  return len();
658 }
659 
660 #if !defined(_MSC_VER)
661 int String::vscanf(const char *format, va_list args)
662 {
663  assert(format != NULL);
664 
665  if(str)
666  return vsscanf(str->text, format, args);
667  return -1;
668 }
669 
670 int String::scanf(const char *format, ...)
671 {
672  assert(format != NULL);
673 
674  va_list args;
675  int rtn = -1;
676 
677  va_start(args, format);
678  if(str)
679  rtn = vsscanf(str->text, format, args);
680  va_end(args);
681  return rtn;
682 }
683 #else
684 int String::vscanf(const char *format, va_list args)
685 {
686  return 0;
687 }
688 
689 int String::scanf(const char *format, ...)
690 {
691  return 0;
692 }
693 #endif
694 
695 void String::rsplit(const char *s)
696 {
697  if(!str || !s || s <= str->text || s > str->text + str->len)
698  return;
699 
700  str->set(s);
701 }
702 
703 void String::rsplit(size_t pos)
704 {
705  if(!str || pos > str->len || !pos)
706  return;
707 
708  str->set(str->text + pos);
709 }
710 
711 void String::split(const char *s)
712 {
713  size_t pos;
714 
715  if(!s || !*s || !str)
716  return;
717 
718  if(s < str->text || s >= str->text + str->len)
719  return;
720 
721  pos = s - str->text;
722  str->text[pos] = 0;
723  str->fix();
724 }
725 
726 void String::split(size_t pos)
727 {
728  if(!str || pos >= str->len)
729  return;
730 
731  str->text[pos] = 0;
732  str->fix();
733 }
734 
735 void String::fill(size_t size, char fill)
736 {
737  if(!str) {
738  str = create(size);
739  str->retain();
740  }
741  while(str->len < str->max && size--)
742  str->text[str->len++] = fill;
743  str->fix();
744 }
745 
746 void String::set(size_t offset, const char *s, size_t size)
747 {
748  if(!s || !*s || !str)
749  return;
750 
751  if(!size)
752  size = strlen(s);
753 
754  if(str)
755  str->set(offset, s, size);
756 }
757 
758 void String::set(const char *s, char overflow, size_t offset, size_t size)
759 {
760  size_t len = count(s);
761 
762  if(!s || !*s || !str)
763  return;
764 
765  if(offset >= str->max)
766  return;
767 
768  if(!size || size > str->max - offset)
769  size = str->max - offset;
770 
771  if(len <= size) {
772  set(offset, s, size);
773  return;
774  }
775 
776  set(offset, s, size);
777 
778  if(len > size && overflow)
779  str->text[offset + size - 1] = overflow;
780 }
781 
782 void String::rset(const char *s, char overflow, size_t offset, size_t size)
783 {
784  size_t len = count(s);
785 
786  if(!s || !*s || !str)
787  return;
788 
789  if(offset >= str->max)
790  return;
791 
792  if(!size || size > str->max - offset)
793  size = str->max - offset;
794 
795  if(len > size)
796  s += len - size;
797  set(offset, s, size);
798  if(overflow && len > size)
799  str->text[offset] = overflow;
800 }
801 
802 void String::set(const char *s)
803 {
804  size_t len;
805 
806  if(!s)
807  s = "";
808 
809  if(!str) {
810  len = strlen(s);
811  str = create(len);
812  str->retain();
813  }
814 
815  str->set(s);
816 }
817 
818 void String::paste(size_t offset, const char *cp, size_t size)
819 {
820  if(!cp)
821  return;
822 
823  if(!size)
824  size = strlen(cp);
825 
826  if(!size)
827  return;
828 
829  if(!str) {
830  str = create(size);
831  String::set(str->text, ++size, cp);
832  str->len = --size;
833  str->fix();
834  return;
835  }
836 
837  cow(size);
838 
839  if(offset >= str->len)
840  String::set(str->text + str->len, size + 1, cp);
841  else {
842  memmove(str->text + offset + size, str->text + offset, str->len - offset);
843  memmove(str->text + offset, cp, size);
844  }
845  str->len += size;
846  str->fix();
847 }
848 
849 void String::cut(size_t offset, size_t size)
850 {
851  if(!str || offset >= str->len)
852  return;
853 
854  if(!size)
855  size = str->len;
856 
857  if(offset + size >= str->len) {
858  str->len = offset;
859  str->fix();
860  return;
861  }
862 
863  memmove(str->text + offset, str->text + offset + size, str->len - offset - size);
864  str->len -= size;
865  str->fix();
866 }
867 
868 void String::paste(char *text, size_t max, size_t offset, const char *cp, size_t size)
869 {
870  if(!cp || !text)
871  return;
872 
873  if(!size)
874  size = strlen(cp);
875 
876  if(!size)
877  return;
878 
879  size_t len = strlen(text);
880  if(len <= max)
881  return;
882 
883  if(len + size >= max)
884  size = max - len;
885 
886  if(offset >= len)
887  String::set(text + len, size + 1, cp);
888  else {
889  memmove(text + offset + size, text + offset, len - offset);
890  memmove(text + offset, cp, size);
891  }
892 }
893 
894 void String::cut(char *text, size_t offset, size_t size)
895 {
896  if(!text)
897  return;
898 
899  size_t len = strlen(text);
900  if(!len || offset >= len)
901  return;
902 
903  if(offset + size >= len) {
904  text[offset] = 0;
905  return;
906  }
907 
908  memmove(text + offset, text + offset + size, len - offset - size);
909  len -= size;
910  text[len] = 0;
911 }
912 
913 bool String::resize(size_t size)
914 {
915  if(!size) {
916  release();
917  str = NULL;
918  return true;
919  }
920 
921  if(!str) {
922  str = create(size);
923  str->retain();
924  }
925  else if(str->is_copied() || str->max < size) {
926  str->release();
927  str = create(size);
928  str->retain();
929  }
930  return true;
931 }
932 
933 void String::clear(size_t offset)
934 {
935  if(!str)
936  return;
937 
938  str->clear(offset);
939 }
940 
941 void String::clear(void)
942 {
943  if(str)
944  str->set("");
945 }
946 
947 void String::cow(size_t size)
948 {
949  if(str)
950  size += str->len;
951 
952  if(!size)
953  return;
954 
955  if(!str || !str->max || str->is_copied() || size > str->max) {
956  cstring *s = create(size);
957  if (!s)
958  return;
959 
960  if (str) {
961  s->len = str->len;
962  String::set(s->text, s->max + 1, str->text);
963  }
964  else
965  s->len = 0;
966  s->retain();
967  if (str)
968  str->release();
969  str = s;
970  }
971 }
972 
973 void String::add(char ch)
974 {
975  char buf[2];
976 
977  if(ch == 0)
978  return;
979 
980  buf[0] = ch;
981  buf[1] = 0;
982 
983  if(!str) {
984  set(buf);
985  return;
986  }
987 
988  cow(1);
989  str->add(buf);
990 }
991 
992 void String::add(const char *s)
993 {
994  if(!s || !*s)
995  return;
996 
997  if(!str) {
998  set(s);
999  return;
1000  }
1001 
1002  cow(strlen(s));
1003  str->add(s);
1004 }
1005 
1006 char String::at(int offset) const
1007 {
1008  if(!str)
1009  return 0;
1010 
1011  if(offset >= (int)str->len)
1012  return 0;
1013 
1014  if(offset > -1)
1015  return str->text[offset];
1016 
1017  if((size_t)(-offset) >= str->len)
1018  return str->text[0];
1019 
1020  return str->text[(int)(str->len) + offset];
1021 }
1022 
1024 {
1025  const char *cp = operator()(offset);
1026  if(!cp)
1027  cp = "";
1028 
1029  if(!len)
1030  len = strlen(cp);
1031 
1032  return String(cp, len);
1033 }
1034 
1035 const char *String::operator()(int offset) const
1036 {
1037  if(!str)
1038  return NULL;
1039 
1040  if(offset >= (int)str->len)
1041  return NULL;
1042 
1043  if(offset > -1)
1044  return str->text + offset;
1045 
1046  if((size_t)(-offset) >= str->len)
1047  return str->text;
1048 
1049  return str->text + str->len + offset;
1050 }
1051 
1052 const char String::operator[](int offset) const
1053 {
1054  if(!str)
1055  return 0;
1056 
1057  if(offset >= (int)str->len)
1058  return 0;
1059 
1060  if(offset > -1)
1061  return str->text[offset];
1062 
1063  if((size_t)(-offset) >= str->len)
1064  return *str->text;
1065 
1066  return str->text[str->len + offset];
1067 }
1068 
1070 {
1071  if(str)
1072  str->inc(1);
1073  return *this;
1074 }
1075 
1077 {
1078  if(str)
1079  str->dec(1);
1080  return *this;
1081 }
1082 
1084 {
1085  if(str)
1086  str->inc(offset);
1087  return *this;
1088 }
1089 
1091 {
1092  if(str)
1093  str->dec(offset);
1094  return *this;
1095 }
1096 
1097 bool String::operator*=(const char *substr)
1098 {
1099  if(search(substr))
1100  return true;
1101 
1102  return false;
1103 }
1104 
1106 {
1107  release();
1108  set(s);
1109  return *this;
1110 }
1111 
1112 String &String::operator=(const char *s)
1113 {
1114  release();
1115  set(s);
1116  return *this;
1117 }
1118 
1120 {
1121  set(s);
1122  return *this;
1123 }
1124 
1126 {
1127  set(s);
1128  return *this;
1129 }
1130 
1132 {
1133  release();
1134  set(s.c_str());
1135  return *this;
1136 }
1137 
1139 {
1140  if(str == s.str)
1141  return *this;
1142 
1143  if(s.str)
1144  s.str->retain();
1145 
1146  if(str)
1147  str->release();
1148 
1149  str = s.str;
1150  return *this;
1151 }
1152 
1153 bool String::full(void) const
1154 {
1155  if(!str)
1156  return false;
1157 
1158  if(str->len == str->max)
1159  return true;
1160 
1161  return false;
1162 }
1163 
1164 bool String::operator!() const
1165 {
1166  bool rtn = false;
1167  if(!str)
1168  return true;
1169 
1170  if(!str->len)
1171  rtn = true;
1172 
1173  str->fix();
1174  return rtn;
1175 }
1176 
1177 String::operator bool() const
1178 {
1179  bool rtn = false;
1180 
1181  if(!str)
1182  return false;
1183 
1184  if(str->len)
1185  rtn = true;
1186  str->fix();
1187  return rtn;
1188 }
1189 
1190 bool String::operator==(const char *s) const
1191 {
1192  return (compare(s) == 0);
1193 }
1194 
1195 bool String::operator!=(const char *s) const
1196 {
1197  return (compare(s) != 0);
1198 }
1199 
1200 bool String::operator<(const char *s) const
1201 {
1202  return (compare(s) < 0);
1203 }
1204 
1205 bool String::operator<=(const char *s) const
1206 {
1207  return (compare(s) <= 0);
1208 }
1209 
1210 bool String::operator>(const char *s) const
1211 {
1212  return (compare(s) > 0);
1213 }
1214 
1215 bool String::operator>=(const char *s) const
1216 {
1217  return (compare(s) >= 0);
1218 }
1219 
1220 String &String::operator&(const char *s)
1221 {
1222  add(s);
1223  return *this;
1224 }
1225 
1226 String &String::operator|(const char *s)
1227 {
1228  if(!s || !*s)
1229  return *this;
1230 
1231  if(!str) {
1232  set(s);
1233  return *this;
1234  }
1235 
1236  str->add(s);
1237  return *this;
1238 }
1239 
1240 const String String::operator+(const char *s) const
1241 {
1242  String tmp;
1243  if(str && str->text[0])
1244  tmp.set(str->text);
1245 
1246  if(s && *s)
1247  tmp.add(s);
1248 
1249  return tmp;
1250 }
1251 
1253 {
1254  if(!s || !*s)
1255  return *this;
1256 
1257  add(s);
1258  return *this;
1259 }
1260 
1261 memstring::memstring(void *mem, size_t size)
1262 {
1263  assert(mem != NULL);
1264  assert(size > 0);
1265 
1266  str = new(mem) cstring(size);
1267  str->set("");
1268 }
1269 
1271 {
1272  str = NULL;
1273 }
1274 
1276 {
1277  assert(size > 0);
1278 
1279  void *mem = ::malloc(size + sizeof(memstring) + sizeof(cstring));
1280  return new(mem) memstring((caddr_t)mem + sizeof(memstring), size);
1281 }
1282 
1284 {
1285  assert(size > 0);
1286 
1287  void *mem = mpager->alloc(size + sizeof(memstring) + sizeof(cstring));
1288  return new(mem) memstring((caddr_t)mem + sizeof(memstring), size);
1289 }
1290 
1292 {
1293  str = NULL;
1294 }
1295 
1297 {
1298  return false;
1299 }
1300 
1301 void memstring::cow(size_t adj)
1302 {
1303 }
1304 
1305 char *String::token(char *text, char **token, const char *clist, const char *quote, const char *eol)
1306 {
1307  char *result;
1308 
1309  if(!eol)
1310  eol = "";
1311 
1312  if(!token || !clist)
1313  return NULL;
1314 
1315  if(!*token)
1316  *token = text;
1317 
1318  if(!**token) {
1319  *token = text;
1320  return NULL;
1321  }
1322 
1323  while(**token && strchr(clist, **token))
1324  ++*token;
1325 
1326  result = *token;
1327 
1328  if(*result && *eol && NULL != (eol = strchr(eol, *result))) {
1329  if(eol[0] != eol[1] || *result == eol[1]) {
1330  *token = text;
1331  return NULL;
1332  }
1333  }
1334 
1335  if(!*result) {
1336  *token = text;
1337  return NULL;
1338  }
1339 
1340  while(quote && *quote && *result != *quote) {
1341  quote += 2;
1342  }
1343 
1344  if(quote && *quote) {
1345  ++result;
1346  ++quote;
1347  *token = strchr(result, *quote);
1348  if(!*token)
1349  *token = result + strlen(result);
1350  else {
1351  **token = 0;
1352  ++(*token);
1353  }
1354  return result;
1355  }
1356 
1357  while(**token && !strchr(clist, **token))
1358  ++(*token);
1359 
1360  if(**token) {
1361  **token = 0;
1362  ++(*token);
1363  }
1364 
1365  return result;
1366 }
1367 
1369 {
1370  cstring *tmp = String::create(str->max);
1371  tmp->set(str->text);
1372  return tmp;
1373 }
1374 
1376 {
1377  if(s.str) {
1378  s.str->len = strlen(s.str->text);
1379  s.str->fix();
1380  }
1381 }
1382 
1384 {
1385  String::cstring *s = s1.str;
1386  s1.str = s2.str;
1387  s2.str = s;
1388 }
1389 
1390 char *String::dup(const char *cp)
1391 {
1392  char *mem;
1393 
1394  if(!cp)
1395  return NULL;
1396 
1397  size_t len = strlen(cp) + 1;
1398  mem = (char *)malloc(len);
1399  if(!mem)
1400  __THROW_ALLOC();
1401  String::set(mem, len, cp);
1402  return mem;
1403 }
1404 
1405 char *String::left(const char *cp, size_t size)
1406 {
1407  char *mem;
1408 
1409  if(!cp)
1410  return NULL;
1411 
1412  if(!size)
1413  size = strlen(cp);
1414 
1415  mem = (char *)malloc(++size);
1416  if(!mem)
1417  __THROW_ALLOC();
1418  String::set(mem, size, cp);
1419  return mem;
1420 }
1421 
1422 const char *String::pos(const char *cp, ssize_t offset)
1423 {
1424  if(!cp)
1425  return NULL;
1426 
1427  size_t len = strlen(cp);
1428  if(!len)
1429  return cp;
1430 
1431  if(offset >= 0) {
1432  if((size_t)offset > len)
1433  offset = (ssize_t)len;
1434  return cp + offset;
1435  }
1436 
1437  offset = -offset;
1438  if((size_t)offset >= len)
1439  return cp;
1440 
1441  return cp + len - offset;
1442 }
1443 
1444 size_t String::count(const char *cp)
1445 {
1446  if(!cp)
1447  return 0;
1448 
1449  return strlen(cp);
1450 }
1451 
1452 const char *String::find(const char *str, const char *key, const char *delim)
1453 {
1454  size_t l1 = strlen(str);
1455  size_t l2 = strlen(key);
1456 
1457  if(!delim[0])
1458  delim = NULL;
1459 
1460  while(l1 >= l2) {
1461  if(!strncmp(key, str, l2)) {
1462  if(l1 == l2 || !delim || strchr(delim, str[l2]))
1463  return str;
1464  }
1465  if(!delim) {
1466  ++str;
1467  --l1;
1468  continue;
1469  }
1470  while(l1 >= l2 && !strchr(delim, *str)) {
1471  ++str;
1472  --l1;
1473  }
1474  while(l1 >= l2 && strchr(delim, *str)) {
1475  ++str;
1476  --l1;
1477  }
1478  }
1479  return NULL;
1480 }
1481 
1482 const char *String::ifind(const char *str, const char *key, const char *delim)
1483 {
1484  size_t l1 = strlen(str);
1485  size_t l2 = strlen(key);
1486 
1487  if(!delim[0])
1488  delim = NULL;
1489 
1490  while(l1 >= l2) {
1491  if(!strnicmp(key, str, l2)) {
1492  if(l1 == l2 || !delim || strchr(delim, str[l2]))
1493  return str;
1494  }
1495  if(!delim) {
1496  ++str;
1497  --l1;
1498  continue;
1499  }
1500  while(l1 >= l2 && !strchr(delim, *str)) {
1501  ++str;
1502  --l1;
1503  }
1504  while(l1 >= l2 && strchr(delim, *str)) {
1505  ++str;
1506  --l1;
1507  }
1508  }
1509  return NULL;
1510 }
1511 
1512 char *String::set(char *str, size_t size, const char *s, size_t len)
1513 {
1514  if(!str)
1515  return NULL;
1516 
1517  if(size < 2)
1518  return str;
1519 
1520  if(!s)
1521  s = "";
1522 
1523  size_t l = strlen(s);
1524  if(l >= size)
1525  l = size - 1;
1526 
1527  if(l > len)
1528  l = len;
1529 
1530  if(!l) {
1531  *str = 0;
1532  return str;
1533  }
1534 
1535  memmove(str, s, l);
1536  str[l] = 0;
1537  return str;
1538 }
1539 
1540 char *String::rset(char *str, size_t size, const char *s)
1541 {
1542  size_t len = count(s);
1543  if(len > size)
1544  s += len - size;
1545  return set(str, size, s);
1546 }
1547 
1548 char *String::set(char *str, size_t size, const char *s)
1549 {
1550  if(!str)
1551  return NULL;
1552 
1553  if(size < 2)
1554  return str;
1555 
1556  if(!s)
1557  s = "";
1558 
1559  size_t l = strlen(s);
1560 
1561  if(l >= size)
1562  l = size - 1;
1563 
1564  if(!l) {
1565  *str = 0;
1566  return str;
1567  }
1568 
1569  memmove(str, s, l);
1570  str[l] = 0;
1571  return str;
1572 }
1573 
1574 char *String::add(char *str, size_t size, const char *s, size_t len)
1575 {
1576  if(!str)
1577  return NULL;
1578 
1579  if(!s)
1580  return str;
1581 
1582  size_t l = strlen(s);
1583  size_t o = strlen(str);
1584 
1585  if(o >= (size - 1))
1586  return str;
1587  set(str + o, size - o, s, l);
1588  return str;
1589 }
1590 
1591 char *String::add(char *str, size_t size, const char *s)
1592 {
1593  if(!str)
1594  return NULL;
1595 
1596  if(!s)
1597  return str;
1598 
1599  size_t o = strlen(str);
1600 
1601  if(o >= (size - 1))
1602  return str;
1603 
1604  set(str + o, size - o, s);
1605  return str;
1606 }
1607 
1608 char *String::trim(char *str, const char *clist)
1609 {
1610  if(!str)
1611  return NULL;
1612 
1613  if(!clist)
1614  return str;
1615 
1616  while(*str && strchr(clist, *str))
1617  ++str;
1618 
1619  return str;
1620 }
1621 
1622 char *String::chop(char *str, const char *clist)
1623 {
1624  if(!str)
1625  return NULL;
1626 
1627  if(!clist)
1628  return str;
1629 
1630  size_t offset = strlen(str);
1631  while(offset && strchr(clist, str[offset - 1]))
1632  str[--offset] = 0;
1633  return str;
1634 }
1635 
1636 char *String::strip(char *str, const char *clist)
1637 {
1638  str = trim(str, clist);
1639  chop(str, clist);
1640  return str;
1641 }
1642 
1643 bool String::check(const char *str, size_t max, size_t min)
1644 {
1645  size_t count = 0;
1646 
1647  if(!str)
1648  return false;
1649 
1650  while(*str) {
1651  if(++count > max)
1652  return false;
1653  ++str;
1654  }
1655  if(count < min)
1656  return false;
1657  return true;
1658 }
1659 
1660 void String::upper(char *str)
1661 {
1662  while(str && *str) {
1663  *str = toupper(*str);
1664  ++str;
1665  }
1666 }
1667 
1668 void String::lower(char *str)
1669 {
1670  while(str && *str) {
1671  *str = tolower(*str);
1672  ++str;
1673  }
1674 }
1675 
1676 void String::erase(char *str)
1677 {
1678  if(!str || *str == 0)
1679  return;
1680 
1681  memset(str, 0, strlen(str));
1682 }
1683 
1684 unsigned String::ccount(const char *str, const char *clist)
1685 {
1686  unsigned count = 0;
1687  while(str && *str) {
1688  if(strchr(clist, *(str++)))
1689  ++count;
1690  }
1691  return count;
1692 }
1693 
1694 char *String::skip(char *str, const char *clist)
1695 {
1696  if(!str || !clist)
1697  return NULL;
1698 
1699  while(*str && strchr(clist, *str))
1700  ++str;
1701 
1702  if(*str)
1703  return str;
1704 
1705  return NULL;
1706 }
1707 
1708 char *String::rskip(char *str, const char *clist)
1709 {
1710  size_t len = count(str);
1711 
1712  if(!len || !clist)
1713  return NULL;
1714 
1715  while(len > 0) {
1716  if(!strchr(clist, str[--len]))
1717  return str;
1718  }
1719  return NULL;
1720 }
1721 
1722 size_t String::seek(char *str, const char *clist)
1723 {
1724  size_t pos = 0;
1725 
1726  if(!str)
1727  return 0;
1728 
1729  if(!clist)
1730  return strlen(str);
1731 
1732  while(str[pos]) {
1733  if(strchr(clist, str[pos]))
1734  return pos;
1735  ++pos;
1736  }
1737  return pos;
1738 }
1739 
1740 char *String::find(char *str, const char *clist)
1741 {
1742  if(!str)
1743  return NULL;
1744 
1745  if(!clist)
1746  return str;
1747 
1748  while(str && *str) {
1749  if(strchr(clist, *str))
1750  return str;
1751  }
1752  return NULL;
1753 }
1754 
1755 char *String::rfind(char *str, const char *clist)
1756 {
1757  if(!str)
1758  return NULL;
1759 
1760  if(!clist)
1761  return str + strlen(str);
1762 
1763  char *s = str + strlen(str);
1764 
1765  while(s > str) {
1766  if(strchr(clist, *(--s)))
1767  return s;
1768  }
1769  return NULL;
1770 }
1771 
1772 bool String::eq_case(const char *s1, const char *s2)
1773 {
1774  if(!s1)
1775  s1 = "";
1776 
1777  if(!s2)
1778  s2 = "";
1779 
1780 #ifdef HAVE_STRICMP
1781  return stricmp(s1, s2) == 0;
1782 #else
1783  return strcasecmp(s1, s2) == 0;
1784 #endif
1785 }
1786 
1787 bool String::eq_case(const char *s1, const char *s2, size_t size)
1788 {
1789  if(!s1)
1790  s1 = "";
1791 
1792  if(!s2)
1793  s2 = "";
1794 
1795 #ifdef HAVE_STRICMP
1796  return strnicmp(s1, s2, size) == 0;
1797 #else
1798  return strncasecmp(s1, s2, size) == 0;
1799 #endif
1800 }
1801 
1802 bool String::equal(const char *s1, const char *s2)
1803 {
1804  if(!s1)
1805  s1 = "";
1806  if(!s2)
1807  s2 = "";
1808 
1809  return strcmp(s1, s2) == 0;
1810 }
1811 
1812 bool String::equal(const char *s1, const char *s2, size_t size)
1813 {
1814  if(!s1)
1815  s1 = "";
1816  if(!s2)
1817  s2 = "";
1818 
1819  return strncmp(s1, s2, size) == 0;
1820 }
1821 
1822 int String::compare(const char *s1, const char *s2)
1823 {
1824  if(!s1)
1825  s1 = "";
1826  if(!s2)
1827  s2 = "";
1828 
1829 #ifdef HAVE_STRCOLL
1830  return strcoll(s1, s2);
1831 #else
1832  return strcmp(s1, s2);
1833 #endif
1834 }
1835 
1836 
1837 char *String::unquote(char *str, const char *clist)
1838 {
1839  assert(clist != NULL);
1840 
1841  size_t len = count(str);
1842  if(!len || !str)
1843  return NULL;
1844 
1845  while(clist[0]) {
1846  if(*str == clist[0] && str[len - 1] == clist[1]) {
1847  str[len - 1] = 0;
1848  return ++str;
1849  }
1850  clist += 2;
1851  }
1852  return str;
1853 }
1854 
1855 char *String::fill(char *str, size_t size, char fill)
1856 {
1857  if(!str)
1858  return NULL;
1859 
1860  memset(str, fill, size - 1);
1861  str[size - 1] = 0;
1862  return str;
1863 }
1864 
1865 static int hexcode(char ch)
1866 {
1867  ch = toupper(ch);
1868  if(ch >= '0' && ch <= '9')
1869  return ch - '0';
1870  else if(ch >= 'A' && ch <= 'F')
1871  return ch - 'A' + 10;
1872  return -1; // error flag
1873 }
1874 
1875 size_t String::hexcount(const char *str, bool ws)
1876 {
1877  size_t count = 0;
1878 
1879  while(str && *str) {
1880  if(ws && isspace(*str)) {
1881  ++str;
1882  continue;
1883  }
1884  if(hexcode(str[0]) < 0 || hexcode(str[1]) < 0)
1885  break;
1886  str += 2;
1887  ++count;
1888  }
1889 
1890  return count;
1891 }
1892 
1893 size_t String::hexsize(const char *format)
1894 {
1895  size_t count = 0;
1896  char *ep;
1897  unsigned skip;
1898 
1899  while(format && *format) {
1900  while(*format && !isdigit(*format)) {
1901  ++format;
1902  ++count;
1903  }
1904  if(isdigit(*format)) {
1905  skip = (unsigned)strtol(format, &ep, 10);
1906  format = ep;
1907  count += skip * 2;
1908  }
1909  }
1910  return count;
1911 }
1912 
1913 String String::hex(const uint8_t *binary, size_t size)
1914 {
1915  String out(size * 2);
1916  char *buf = out.data();
1917  while(size--) {
1918  snprintf(buf, 3, "%02x", *(binary++));
1919  buf += 2;
1920  }
1921  return out;
1922 }
1923 
1924 size_t String::hexdump(const uint8_t *binary, char *string, const char *format)
1925 {
1926  size_t count = 0;
1927  char *ep;
1928  unsigned skip;
1929 
1930  while(format && *format) {
1931  while(*format && !isdigit(*format)) {
1932  *(string++) = *(format++);
1933  ++count;
1934  }
1935  if(isdigit(*format)) {
1936  skip = (unsigned)strtol(format, &ep, 10);
1937  format = ep;
1938  count += skip * 2;
1939  while(skip--) {
1940  snprintf(string, 3, "%02x", *(binary++));
1941  string += 2;
1942  }
1943  }
1944  }
1945  *string = 0;
1946  return count;
1947 }
1948 
1949 size_t String::hex2bin(const char *str, uint8_t *bin, size_t max, bool ws)
1950 {
1951  size_t count = 0;
1952  size_t out = 0;
1953  int hi, lo;
1954  while(str && *str) {
1955  if(ws && isspace(*str)) {
1956  ++count;
1957  ++str;
1958  continue;
1959  }
1960  hi = hexcode(str[0]);
1961  lo = hexcode(str[1]);
1962  if(hi < 0 || lo < 0)
1963  break;
1964  *(bin++) = (hi << 4) | lo;
1965  str += 2;
1966  count += 2;
1967  if(++out > max)
1968  break;
1969  }
1970  return count;
1971 }
1972 
1973 size_t String::hexpack(uint8_t *binary, const char *string, const char *format)
1974 {
1975  size_t count = 0;
1976  char *ep;
1977  unsigned skip;
1978 
1979  while(format && *format) {
1980  while(*format && !isdigit(*format)) {
1981  if(*(string++) != *(format++))
1982  return count;
1983  ++count;
1984  }
1985  if(isdigit(*format)) {
1986  skip = (unsigned)strtol(format, &ep, 10);
1987  format = ep;
1988  count += skip * 2;
1989  while(skip--) {
1990  *(binary++) = hexcode(string[0]) * 16 + hexcode(string[1]);
1991  string += 2;
1992  }
1993  }
1994  }
1995  return count;
1996 }
1997 
1998 String &String::operator%(unsigned short& value)
1999 {
2000  unsigned long temp = USHRT_MAX + 1;
2001  char *ep;
2002  if(!str || !str->text[0])
2003  return *this;
2004 
2005  value = 0;
2006  temp = strtoul(str->text, &ep, 0);
2007  if(temp > USHRT_MAX)
2008  goto failed;
2009 
2010  value = (unsigned short)temp;
2011 
2012  if(ep)
2013  set(ep);
2014  else
2015  set("");
2016 
2017 failed:
2018  return *this;
2019 }
2020 
2022 {
2023  long temp = SHRT_MAX + 1;
2024  char *ep;
2025  if(!str || !str->text[0])
2026  return *this;
2027 
2028  value = 0;
2029  temp = strtol(str->text, &ep, 0);
2030  if(temp < 0 && temp < SHRT_MIN)
2031  goto failed;
2032 
2033  if(temp > SHRT_MAX)
2034  goto failed;
2035 
2036  value = (short)temp;
2037 
2038  if(ep)
2039  set(ep);
2040  else
2041  set("");
2042 
2043 failed:
2044  return *this;
2045 }
2046 
2048 {
2049  value = 0;
2050  char *ep;
2051  if(!str || !str->text[0])
2052  return *this;
2053 
2054  value = strtol(str->text, &ep, 0);
2055  if(ep)
2056  set(ep);
2057  else
2058  set("");
2059 
2060  return *this;
2061 }
2062 
2063 String &String::operator%(unsigned long& value)
2064 {
2065  value = 0;
2066  char *ep;
2067  if(!str || !str->text[0])
2068  return *this;
2069 
2070  value = strtoul(str->text, &ep, 0);
2071  if(ep)
2072  set(ep);
2073  else
2074  set("");
2075 
2076  return *this;
2077 }
2078 
2079 String &String::operator%(double& value)
2080 {
2081  value = 0;
2082  char *ep;
2083  if(!str || !str->text[0])
2084  return *this;
2085 
2086  value = strtod(str->text, &ep);
2087  if(ep)
2088  set(ep);
2089  else
2090  set("");
2091 
2092  return *this;
2093 }
2094 
2096 {
2097  if(!str || !str->text[0] || !get)
2098  return *this;
2099 
2100  size_t len = strlen(get);
2101  const char *cp = str->text;
2102 
2103  while(isspace(*cp))
2104  ++cp;
2105 
2106  if(eq(cp, get, len))
2107  set(cp + len);
2108  else if(cp != str->text)
2109  set(cp);
2110 
2111  return *this;
2112 }
2113 
2114 static const uint8_t alphabet[65] =
2115  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2116 
2117 String String::b64(const uint8_t *bin, size_t size)
2118 {
2119  size_t dsize = (size * 4 / 3) + 1;
2120  String out(dsize);
2121 
2122  b64encode(out.data(), bin, size);
2123  return out;
2124 }
2125 
2126 size_t String::b64encode(char *dest, const uint8_t *bin, size_t size, size_t dsize)
2127 {
2128  assert(dest != NULL && bin != NULL);
2129 
2130  size_t count = 0;
2131 
2132  if(!dsize)
2133  dsize = b64size(size);
2134 
2135  if (!dsize || !size)
2136  goto end;
2137 
2138  unsigned bits;
2139 
2140  while(size >= 3 && dsize > 4) {
2141  bits = (((unsigned)bin[0])<<16) | (((unsigned)bin[1])<<8)
2142  | ((unsigned)bin[2]);
2143  bin += 3;
2144  size -= 3;
2145  count += 3;
2146  *(dest++) = alphabet[bits >> 18];
2147  *(dest++) = alphabet[(bits >> 12) & 0x3f];
2148  *(dest++) = alphabet[(bits >> 6) & 0x3f];
2149  *(dest++) = alphabet[bits & 0x3f];
2150  dsize -= 4;
2151  }
2152 
2153  if (size && dsize > 4) {
2154  bits = ((unsigned)bin[0])<<16;
2155  *(dest++) = alphabet[bits >> 18];
2156  ++count;
2157  if (size == 1) {
2158  *(dest++) = alphabet[(bits >> 12) & 0x3f];
2159  *(dest++) = '=';
2160  }
2161  else {
2162  ++count;
2163  bits |= ((unsigned)bin[1])<<8;
2164  *(dest++) = alphabet[(bits >> 12) & 0x3f];
2165  *(dest++) = alphabet[(bits >> 6) & 0x3f];
2166  }
2167  *(dest++) = '=';
2168  }
2169 
2170 end:
2171  *dest = 0;
2172  return count;
2173 }
2174 
2175 size_t String::b64size(size_t size)
2176 {
2177  return (size * 4 / 3) + 4;
2178 }
2179 
2180 size_t String::b64count(const char *src, bool ws)
2181 {
2182  char decoder[256];
2183  unsigned long bits;
2184  uint8_t c;
2185  unsigned i;
2186  size_t count = 0;
2187 
2188  for (i = 0; i < 256; ++i)
2189  decoder[i] = 64;
2190 
2191  for (i = 0; i < 64 ; ++i)
2192  decoder[alphabet[i]] = i;
2193 
2194  bits = 1;
2195 
2196  while(*src) {
2197  if(isspace(*src)) {
2198  if(ws) {
2199  ++src;
2200  continue;
2201  }
2202  break;
2203  }
2204  c = (uint8_t)(*(src++));
2205  if (c == '=')
2206  break;
2207  // end on invalid chars
2208  if (decoder[c] == 64) {
2209  break;
2210  }
2211  bits = (bits << 6) + decoder[c];
2212  if (bits & 0x1000000) {
2213  bits = 1;
2214  count += 3;
2215  }
2216  }
2217 
2218  if (bits & 0x40000)
2219  count += 2;
2220  else if (bits & 0x1000)
2221  ++count;
2222 
2223  return count;
2224 }
2225 
2226 size_t String::b64decode(uint8_t *dest, const char *src, size_t size, bool ws)
2227 {
2228  char decoder[256];
2229  unsigned long bits;
2230  uint8_t c;
2231  unsigned i;
2232  size_t count = 0;
2233 
2234  for (i = 0; i < 256; ++i)
2235  decoder[i] = 64;
2236 
2237  for (i = 0; i < 64 ; ++i)
2238  decoder[alphabet[i]] = i;
2239 
2240  bits = 1;
2241 
2242  while(*src) {
2243  if(isspace(*src)) {
2244  if(ws) {
2245  ++count;
2246  ++src;
2247  continue;
2248  }
2249  break;
2250  }
2251  c = (uint8_t)(*(src++));
2252  if (c == '=') {
2253  ++count;
2254  if(*src == '=')
2255  ++count;
2256  break;
2257  }
2258  // end on invalid chars
2259  if (decoder[c] == 64) {
2260  break;
2261  }
2262  ++count;
2263  bits = (bits << 6) + decoder[c];
2264  if (bits & 0x1000000) {
2265  if (size < 3) {
2266  bits = 1;
2267  break;
2268  }
2269  *(dest++) = (uint8_t)((bits >> 16) & 0xff);
2270  *(dest++) = (uint8_t)((bits >> 8) & 0xff);
2271  *(dest++) = (uint8_t)((bits & 0xff));
2272  bits = 1;
2273  size -= 3;
2274  }
2275  }
2276  if (bits & 0x40000) {
2277  if (size >= 2) {
2278  *(dest++) = (uint8_t)((bits >> 10) & 0xff);
2279  *(dest++) = (uint8_t)((bits >> 2) & 0xff);
2280  }
2281  }
2282  else if ((bits & 0x1000) && size) {
2283  *(dest++) = (uint8_t)((bits >> 4) & 0xff);
2284  }
2285  return count;
2286 }
2287 
2288 #define CRC24_INIT 0xb704ceL
2289 #define CRC24_POLY 0x1864cfbL
2290 
2291 uint32_t String::crc24(uint8_t *binary, size_t size)
2292 {
2293  uint32_t crc = CRC24_INIT;
2294  unsigned i;
2295 
2296  while (size--) {
2297  crc ^= (*binary++) << 16;
2298  for (i = 0; i < 8; i++) {
2299  crc <<= 1;
2300  if (crc & 0x1000000)
2301  crc ^= CRC24_POLY;
2302  }
2303  }
2304  return crc & 0xffffffL;
2305 }
2306 
2307 uint16_t String::crc16(uint8_t *binary, size_t size)
2308 {
2309  uint16_t crc = 0xffff;
2310  unsigned i;
2311 
2312  while (size--) {
2313  crc ^= (*binary++);
2314  for (i = 0; i < 8; i++) {
2315  if(crc & 1)
2316  crc = (crc >> 1) ^ 0xa001;
2317  else
2318  crc = (crc >> 1);
2319  }
2320  }
2321  return crc;
2322 }
2323 
2324 } // namespace ucommon
ucommon::String::trim
void trim(const char *list)
Definition: string.cpp:451
ucommon::String::operator++
String & operator++(void)
Definition: string.cpp:1069
ucommon::String::b64encode
static size_t b64encode(char *string, const uint8_t *binary, size_t size, size_t width=0)
Definition: string.cpp:2126
ucommon::String::b64decode
static size_t b64decode(uint8_t *binary, const char *string, size_t size, bool ws=false)
Definition: string.cpp:2226
ucommon::String::len
size_t len(void) const
Definition: string.cpp:145
ucommon::String::b64size
static size_t b64size(size_t size)
Definition: string.cpp:2175
delim
static shell::charopt delim('d', "--delim", _TEXT("set deliminter between arguments"))
ucommon::String::clear
void clear(void)
Definition: string.cpp:941
ucommon::memstring::create
static memstring * create(size_t size)
Definition: string.cpp:1275
ucommon::String::c_copy
virtual cstring * c_copy(void) const
Definition: string.cpp:241
ucommon::String::upper
void upper(void)
Definition: string.cpp:584
ucommon::String::cut
void cut(size_t offset, size_t size=0)
Definition: string.cpp:849
ucommon::String::scanf
int scanf(const char *format,...) __SCANF(2
Definition: string.cpp:670
ucommon::String::cstring::set
void set(size_t offset, const char *text, size_t size)
Definition: string.cpp:116
strnicmp
int strnicmp(const char *s1, const char *s2, size_t size)
Definition: cpr.cpp:104
export.h
ucommon::String::hexcount
static size_t hexcount(const char *str, bool ws=false)
Definition: string.cpp:1875
ucommon::String::crc16
static uint16_t crc16(uint8_t *binary, size_t size)
Definition: string.cpp:2307
ucommon::String::b64
static String b64(const uint8_t *binary, size_t size)
Definition: string.cpp:2117
ucommon::String::at
char at(int position) const
Definition: string.cpp:1006
out
static shell::stringopt out('o', "--output", _TEXT("output file"), "filename", "-")
ucommon::String::hex2bin
static size_t hex2bin(const char *string, uint8_t *binary, size_t maxsize, bool wsflag=false)
Definition: string.cpp:1949
ucommon::String::offset
size_t offset(const char *pointer) const
Definition: string.cpp:604
ucommon::String::left
String left(size_t size) const
Definition: string.h:693
ucommon::CountedObject::is_copied
bool is_copied(void) const
Definition: object.h:95
ucommon::String::operator<=
bool operator<=(const char *text) const
Definition: string.cpp:1205
ucommon::String::fix
static void fix(String &object)
Definition: string.cpp:1375
ucommon
Definition: access.cpp:23
ucommon::String::operator==
bool operator==(const char *text) const
Definition: string.cpp:1190
ucommon::memstring::release
void release(void) __FINAL
Definition: string.cpp:1291
ucommon::String::operator!
bool operator!() const
Definition: string.cpp:1164
ucommon::String::swap
static void swap(String &object1, String &object2)
Definition: string.cpp:1383
ucommon::String::operator[]
const char operator[](int offset) const
Definition: string.cpp:1052
ucommon::String::erase
void erase(void)
Definition: string.cpp:596
ucommon::String::rfind
const char * rfind(const char *list, size_t offset=npos) const
Definition: string.cpp:398
ucommon::hexcode
static int hexcode(char ch)
Definition: string.cpp:1865
ucommon::String::rskip
const char * rskip(const char *list, size_t offset=npos) const
Definition: string.cpp:380
ucommon::String::cstring
Definition: string.h:134
ucommon::String::cstring::dec
void dec(size_t number)
Definition: string.cpp:54
ucommon::String::chop
void chop(const char *list)
Definition: string.cpp:416
ucommon::String::operator%
String & operator%(short &value)
Definition: string.cpp:2021
ucommon::String
Definition: string.h:78
result
static void result(const char *path, int code)
Definition: mdsum.cpp:35
ucommon::String::rset
void rset(const char *text, char overflow, size_t offset, size_t size=0)
Definition: string.cpp:782
__THROW_ALLOC
#define __THROW_ALLOC()
Definition: platform.h:52
ucommon::String::begin
const char * begin(void) const
Definition: string.cpp:331
ucommon::adj
static void adj(struct timeval *ts)
Definition: timer.cpp:51
ucommon::String::vprintf
int int size_t size_t vprintf(const char *format, va_list args) __PRINTF(2
Definition: string.cpp:648
ucommon::String::lower
void lower(void)
Definition: string.cpp:590
ucommon::String::replace
unsigned replace(const char *string, const char *text=NULL, unsigned flags=0)
Definition: string.cpp:477
ucommon::String::release
virtual void release(void) __OVERRIDE
Definition: string.cpp:274
ucommon::min
T &() min(T &o1, T &o2)
Definition: generics.h:456
ucommon::String::find
const char * find(const char *list, size_t offset=0) const
Definition: string.cpp:552
ucommon::String::str
cstring * str
Definition: string.h:209
ucommon::String::search
const char * search(const char *string, unsigned instance=0, unsigned flags=0) const
Definition: string.cpp:521
caddr_t
#define caddr_t
Definition: file.h:86
ucommon::String::cstring::text
char text[1]
Definition: string.h:146
ucommon::String::vscanf
int int vscanf(const char *format, va_list args) __SCANF(2
Definition: string.cpp:661
ucommon::String::pos
static const char * pos(const char *text, ssize_t offset)
Definition: string.cpp:1422
ucommon::String::cstring::len
size_t len
Definition: string.h:145
ucommon::String::npos
const static size_t npos
Definition: string.h:265
ucommon::String::eq_case
static bool eq_case(const char *text1, const char *text2)
Definition: string.cpp:1772
quote
static shell::stringopt quote('q', "--quote", _TEXT("set quote for each argument"), "string", "")
ucommon::String::operator-=
String & operator-=(size_t number)
Definition: string.cpp:1090
temp
static bool temp
Definition: zerofill.cpp:29
decoder
static enum @30 decoder
CRC24_POLY
#define CRC24_POLY
Definition: string.cpp:2289
CRC24_INIT
#define CRC24_INIT
Definition: string.cpp:2288
ucommon::max
T &() max(T &o1, T &o2)
Definition: generics.h:445
ucommon::String::INSENSITIVE
Definition: string.h:95
ucommon::String::operator=
String & operator=(const String &object)
Definition: string.cpp:1138
ucommon::String::get
String get(size_t offset, size_t size=0) const
Definition: string.cpp:246
ucommon::String::operator!=
bool operator!=(const char *text) const
Definition: string.cpp:1195
ucommon::String::check
static bool check(const char *string, size_t maximum, size_t minimum=0)
Definition: string.cpp:1643
ucommon::String::skip
const char * skip(const char *list, size_t offset=0) const
Definition: string.cpp:367
ucommon::String::size
size_t size(void) const
Definition: string.cpp:137
ucommon::String::strip
void strip(const char *list)
Definition: string.cpp:445
ucommon::memstring::cow
void cow(size_t adj=0) __FINAL
Definition: string.cpp:1301
ucommon::MemoryProtocol
Definition: protocols.h:43
ucommon::String::data
int int size_t size_t char * data(void)
Definition: string.cpp:281
ucommon::String::hex
static String hex(const uint8_t *binary, size_t size)
Definition: string.cpp:1913
ucommon::String::retain
virtual void retain(void) __OVERRIDE
Definition: string.cpp:268
ucommon::String::operator&=
String & operator&=(const char *text)
Definition: string.cpp:1125
ucommon::String::split
void split(const char *pointer)
Definition: string.cpp:711
ucommon::String::end
const char * end(void) const
Definition: string.cpp:339
stricmp
int stricmp(const char *s1, const char *s2)
Definition: cpr.cpp:95
ucommon::String::operator|=
String & operator|=(const char *text)
Definition: string.cpp:1119
ucommon::String::token
static char * token(char *text, char **last, const char *list, const char *quote=NULL, const char *end=NULL)
Definition: string.cpp:1305
ucommon::eq
bool eq(const struct sockaddr *s1, const struct sockaddr *s2)
Definition: socket.h:2100
ucommon::String::resize
virtual bool resize(size_t size)
Definition: string.cpp:913
ucommon::String::cstring::add
void add(const char *text)
Definition: string.cpp:86
ucommon::String::set
void set(const char *text)
Definition: string.cpp:802
ucommon::String::operator+
const String operator+(const char *text) const
Definition: string.cpp:1240
ucommon::String::hexdump
static size_t hexdump(const uint8_t *binary, char *string, const char *format)
Definition: string.cpp:1924
ch
#define ch(x, y, z)
Definition: sha2.cpp:120
ucommon::String::full
bool full(void) const
Definition: string.cpp:1153
ucommon::String::cstring::inc
void inc(size_t number)
Definition: string.cpp:69
ucommon::String::cstring::fix
void fix(void)
Definition: string.cpp:40
ucommon::memstring
Definition: string.h:1395
ucommon::memstring::memstring
memstring(void *memory, size_t size)
Definition: string.cpp:1261
ucommon::String::cstring::cstring
cstring(size_t size)
Definition: string.cpp:32
ucommon::String::equal
bool equal(const char *string) const
Definition: string.cpp:297
ucommon::String::operator>=
bool operator>=(const char *text) const
Definition: string.cpp:1215
ucommon::CountedObject::retain
void retain(void) __OVERRIDE
Definition: object.cpp:43
ucommon::String::rchr
const char * rchr(char character) const
Definition: string.cpp:357
ucommon::memstring::c_copy
cstring * c_copy(void) const __OVERRIDE
Definition: string.cpp:1368
ucommon::String::operator&
String & operator&(const char *text)
Definition: string.cpp:1220
ucommon::String::cstring::max
size_t max
Definition: string.h:144
ucommon::String::fill
void fill(size_t size, char fill)
Definition: string.cpp:735
ucommon::String::operator--
String & operator--(void)
Definition: string.cpp:1076
ucommon::String::printf
int int size_t printf(const char *format,...) __PRINTF(2
Definition: string.cpp:633
ucommon::String::operator<
bool operator<(const char *text) const
Definition: string.cpp:1200
ucommon::String::chr
const char * chr(char character) const
Definition: string.cpp:347
ucommon::String::add
void add(const char *text)
Definition: string.cpp:992
ucommon::String::compare
virtual int compare(const char *string) const
Definition: string.cpp:314
ucommon::String::hexsize
static size_t hexsize(const char *format)
Definition: string.cpp:1893
ucommon::MemoryProtocol::alloc
void * alloc(size_t size)
Definition: protocols.h:65
ucommon::alphabet
static const uint8_t alphabet[65]
Definition: string.cpp:2114
ucommon::String::ifind
static const char * ifind(const char *text, const char *key, const char *optional)
Definition: string.cpp:1482
ucommon::memstring::~memstring
~memstring()
Definition: string.cpp:1270
ucommon::memstring::resize
bool resize(size_t size) __FINAL
Definition: string.cpp:1296
ucommon::String::b64count
static size_t b64count(const char *str, bool ws=false)
Definition: string.cpp:2180
ucommon::String::cow
virtual void cow(size_t size=0)
Definition: string.cpp:947
ucommon::String::seek
static size_t seek(char *text, const char *list)
Definition: string.cpp:1722
string.h
ucommon::String::crc24
static uint32_t crc24(uint8_t *binary, size_t size)
Definition: string.cpp:2291
ucommon::String::rsplit
void rsplit(const char *pointer)
Definition: string.cpp:695
ucommon::String::String
String()
Definition: string.cpp:169
ucommon::String::unquote
bool unquote(const char *quote)
Definition: string.cpp:565
ucommon::String::c_str
const char * c_str(void) const
Definition: string.cpp:289
binary
static bool binary
Definition: car.cpp:38
ucommon::String::ccount
size_t ccount(const char *list) const
Definition: string.cpp:625
ucommon::String::operator+=
String & operator+=(const char *text)
Definition: string.cpp:1252
ucommon::String::~String
virtual ~String()
Definition: string.cpp:236
ucommon::String::paste
void paste(size_t offset, const char *text, size_t size=0)
Definition: string.cpp:818
ucommon::String::dup
static char * dup(const char *text)
Definition: string.cpp:1390
ucommon::String::cstring::clear
void clear(size_t offset)
Definition: string.cpp:45
ucommon::String::operator()
String operator()(int offset, size_t size) const
Definition: string.cpp:1023
ucommon::CountedObject::release
void release(void) __OVERRIDE
Definition: object.cpp:48
ucommon::String::hexpack
static size_t hexpack(uint8_t *binary, const char *string, const char *format)
Definition: string.cpp:1973
ucommon::String::operator>
bool operator>(const char *text) const
Definition: string.cpp:1210
ucommon::String::operator*=
bool operator*=(const char *substring)
Definition: string.cpp:1097
ucommon::String::count
size_t count(void) const
Definition: string.cpp:618
ucommon::String::create
cstring * create(size_t size) const
Definition: string.cpp:256
ucommon::String::operator^=
String & operator^=(const String &object)
Definition: string.cpp:1131
ucommon::String::cstring::dealloc
virtual void dealloc(void) __OVERRIDE
Definition: string.cpp:262
ucommon::CountedObject
Definition: object.h:56
ucommon::String::operator|
String & operator|(const char *text)
Definition: string.cpp:1226