libStatGen Software  1
StringBasics.cpp
1 /*
2  * Copyright (C) 2010 Regents of the University of Michigan
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "StringBasics.h"
19 #include "Error.h"
20 #include "Constant.h"
21 #include "MathConstant.h"
22 
23 #include <string.h>
24 #include <ctype.h>
25 #include <stdarg.h>
26 #include <sstream>
27 
28 #define SWP(A,B) {int tmp=a; a=b; b=tmp;}
29 
30 #ifdef _MSC_VER
31 #ifndef snprintf
32 #define vsnprintf _vsnprintf
33 #define snprintf _snprintf
34 #endif
35 #endif
36 
37 // If natural ordering is defined, comparisons will
38 // order strings including numbers correctly
39 // (eg, ... "8", "9", "10" ...) rather than using
40 // ASCII ordering (... "10", "8", "9", ...)
41 #define NATURAL_ORDERING 1
42 
43 int String::alloc = 8;
44 bool String::caseSensitive = true;
45 
46 void String::NewString(int startsize)
47 {
48  len = 0;
49  size = (startsize + alloc) / alloc * alloc;
50  buffer = new char [size];
51  buffer[0] = 0;
52 }
53 
54 String::String(const char * s)
55 {
56  int clen = s == NULL ? 0 : strlen(s);
57  NewString(clen);
58  if (clen)
59  {
60  len = clen;
61  memcpy(buffer, s, len + 1);
62  }
63 }
64 
65 String::String(char ch, int count)
66 {
67  NewString(count);
68  memset(buffer, ch, count);
69  buffer[count] = 0;
70  len = count;
71 }
72 
73 String::String(const String & s)
74 {
75  len = s.len;
76  size = (s.len + alloc) / alloc * alloc;;
77  buffer = new char [size];
78  memcpy(buffer, s.buffer, len + 1);
79 }
80 
81 void String::Grow(int newSize)
82 {
83  if (newSize >= size)
84  {
85  if ((newSize >> 1) >= size)
86  size = (newSize + alloc) / alloc * alloc;
87  else
88  {
89  size = alloc;
90  while (size <= newSize)
91  size *= 2;
92  }
93 
94  char * tmp = new char [size];
95  // // len + 1 due to terminating NUL which is not counted in len
96  // memcpy(tmp, buffer, len + 1);
97  memcpy(tmp, buffer, len);
98  tmp[len] = '\0';
99  delete [] buffer;
100  buffer = tmp;
101  }
102 }
103 
104 void String::Swap(String & s)
105 {
106  char * temp = s.buffer;
107  s.buffer = buffer;
108  buffer = temp;
109 
110  int swap = s.size;
111  s.size = size;
112  size = swap;
113 
114  swap = s.len;
115  s.len = len;
116  len = swap;
117 }
118 
119 String & String::Copy(const String & s)
120 {
121  Grow(s.len);
122  len = s.len;
123  memcpy(buffer, s.buffer, len + 1);
124  return *this;
125 }
126 
127 String & String::Copy(const String & s, int start, int n)
128 {
129  if (s.len <= start) return Clear();
130  if (s.len < start + n) n = s.len - start;
131  Grow(n);
132  memcpy(buffer, s.buffer + start, n);
133  buffer[len = n] = 0;
134  return *this;
135 }
136 
137 String & String::Copy(const char * s)
138 {
139  if (s == NULL)
140  {
141  len = 0;
142  buffer[0] = 0;
143  }
144  else
145  {
146  int clen = strlen(s);
147  Grow(clen);
148  len = clen;
149  memcpy(buffer, s, len + 1);
150  }
151  return *this;
152 }
153 
154 String & String::ToUpper()
155 {
156  for (int i = 0; i < len; i++)
157  buffer[i] = (char) toupper(buffer[i]);
158  return *this;
159 }
160 
161 String & String::ToLower()
162 {
163  for (int i = 0; i < len; i++)
164  buffer[i] = (char) tolower(buffer[i]);
165  return *this;
166 }
167 
168 String String::AsUpper()
169 {
170  String temp;
171  temp = *this;
172  return temp.ToUpper();
173 }
174 
175 String String::AsLower()
176 {
177  String temp;
178  temp = *this;
179  return temp.ToLower();
180 }
181 
182 String String::Capitalize()
183 {
184  String temp;
185  temp = *this;
186  temp.buffer[0] = (char) toupper(temp.buffer[0]);
187  return temp;
188 }
189 
190 String & String::operator = (const String & rhs)
191 {
192  Copy(rhs);
193  return *this;
194 }
195 
196 String & String::operator = (const char * rhs)
197 {
198  Copy(rhs);
199  return * this;
200 }
201 
202 String & String::operator += (const String & rhs)
203 {
204  Grow(len + rhs.len);
205  memcpy(buffer + len, rhs.buffer, rhs.len + 1);
206  len += rhs.len;
207  return *this;
208 }
209 
210 String & String::operator += (const char * rhs)
211 {
212  if (rhs != NULL)
213  {
214  int clen = strlen(rhs);
215  Grow(len + clen);
216  memcpy(buffer + len, rhs, clen + 1);
217  len += clen;
218  }
219  return *this;
220 }
221 
222 String String::operator + (const String & rhs) const
223 {
224  String result(len + rhs.len);
225  memcpy(result.buffer, buffer, len);
226  memcpy(result.buffer + len, rhs.buffer, rhs.len + 1);
227  result.len = len + rhs.len;
228  return result;
229 }
230 
231 String String::operator + (const char * rhs) const
232 {
233  if (rhs != NULL)
234  {
235  int clen = strlen(rhs);
236  String result(len + clen);
237  memcpy(result.buffer, buffer, len);
238  memcpy(result.buffer + len, rhs, clen + 1);
239  result.len = len + clen;
240  return result;
241  }
242  return *this;
243 }
244 
245 String & String::operator = (char ch)
246 {
247  if (ch)
248  {
249  Grow(1);
250  buffer[0] = ch;
251  buffer[1] = 0;
252  len = 1;
253  }
254  else
255  len = buffer[0] = 0;
256  return *this;
257 }
258 
259 String & String::operator += (char ch)
260 {
261  if (ch)
262  {
263  Grow(len + 1);
264  buffer[len] = ch;
265  buffer[++len] = 0;
266  }
267  return *this;
268 }
269 
270 String String::operator + (char ch) const
271 {
272  String result(*this);
273  result += ch;
274  return result;
275 }
276 
277 String & String::operator = (int rhs)
278 {
279  Clear();
280 
281  if (rhs < 0)
282  {
283  Add('-');
284  *this += (unsigned int) -rhs;
285  }
286  else
287  *this = (unsigned int) rhs;
288  return *this;
289 }
290 
291 String & String::operator = (unsigned int rhs)
292 {
293  Clear();
294 
295  unsigned long long base = 10;
296  int digits = 1;
297 
298  while (rhs >= base)
299  {
300  base *= 10;
301  digits++;
302  }
303 
304  Grow(digits);
305 
306  while (base /= 10)
307  {
308  char ch = char(rhs / base);
309  rhs = rhs - ch * base;
310  buffer[len++] = char(ch + '0');
311  }
312  buffer[len] = 0;
313  return *this;
314 };
315 
316 String String::operator + (int rhs) const
317 {
318  String result(*this);
319  result += rhs;
320  return result;
321 };
322 
323 String String::operator + (unsigned int rhs) const
324 {
325  String result(*this);
326  result += rhs;
327  return result;
328 };
329 
330 String & String::operator += (int rhs)
331 {
332  String temp;
333  temp = rhs;
334  return *this += temp;
335 }
336 
337 String & String::operator += (unsigned int rhs)
338 {
339  String temp;
340  temp = rhs;
341  return *this += temp;
342 }
343 
344 String & String::operator *= (unsigned int rhs)
345 {
346  if (rhs == 0)
347  Clear();
348  else
349  {
350  String original(*this);
351 
352  Grow(len * rhs);
353 
354  for (unsigned int i = 1; i < rhs; i++)
355  *this += original;
356  }
357  return *this;
358 }
359 
360 String & String::operator = (double rhs)
361 {
362  LockBuffer(32);
363  sprintf(buffer, "%.3f", rhs);
364  UnlockBuffer();
365  return *this;
366 }
367 
368 String String::operator + (double rhs) const
369 {
370  String result(*this);
371  result += rhs;
372  return result;
373 }
374 
375 String & String::operator += (double rhs)
376 {
377  String temp;
378  temp = rhs;
379  return *this += temp;
380 }
381 
382 
383 void String::appendFullFloat(float rhs)
384 {
385  std::ostringstream os;
386  os << rhs;
387  *this += os.str().c_str();
388 }
389 
390 char * String::LockBuffer(int min)
391 {
392  if (min > 0) Grow(min);
393  return buffer;
394 }
395 
396 String & String::UnlockBuffer()
397 {
398  for (len = 0; len < size; len++)
399  if (buffer[len] == 0)
400  return *this;
401  error("BasicString - direct access overflowed buffer");
402  return *this;
403 }
404 
405 int String::Compare(const String & s) const
406 {
407  if (caseSensitive)
408  return String::FastCompare(s);
409  else
410  return String::SlowCompare(s);
411 }
412 
413 int String::Compare(const char * s) const
414 {
415  return caseSensitive ? FastCompare(s) : SlowCompare(s);
416 }
417 
418 int String::FastCompare(const String & s) const
419 {
420  for (int i = 0; i <= len; i++)
421  if (buffer[i] - s.buffer[i])
422  {
423 #ifdef NATURAL_ORDERING
424  int d = i;
425  while (isdigit(buffer[d]) && isdigit(s.buffer[d]))
426  d++;
427  if (isdigit(buffer[d]))
428  return 1;
429  if (isdigit(s.buffer[d]))
430  return -1;
431 #endif
432  return buffer[i] - s.buffer[i];
433  }
434  return 0;
435 }
436 
437 int String::FastCompare(const char * s) const
438 {
439  if (s == NULL)
440  return -len;
441 
442  for (int i = 0; i <= len; i++)
443  if (buffer[i] - s[i])
444  {
445 #ifdef NATURAL_ORDERING
446  int d = i;
447  while (isdigit(buffer[d]) && isdigit(s[d]))
448  d++;
449  if (isdigit(buffer[d]))
450  return 1;
451  if (isdigit(s[d]))
452  return -1;
453 #endif
454  return buffer[i] - s[i];
455  }
456  return 0;
457 }
458 
459 int String::SlowCompare(const String & s) const
460 {
461  for (int i = 0; i <= len; i++)
462  if (toupper(buffer[i]) - toupper(s.buffer[i]))
463  {
464 #ifdef NATURAL_ORDERING
465  int d = i;
466  while (isdigit(buffer[d]) && isdigit(s[d]))
467  d++;
468  if (isdigit(buffer[d]))
469  return 1;
470  if (isdigit(s.buffer[d]))
471  return -1;
472 #endif
473  return toupper(buffer[i]) - toupper(s.buffer[i]);
474  }
475  return 0;
476 }
477 
478 int String::SlowCompare(const char * s) const
479 {
480  if (s == NULL)
481  return -len;
482 
483  for (int i = 0; i <= len; i++)
484  if (toupper(buffer[i]) - toupper(s[i]))
485  {
486 #ifdef NATURAL_ORDERING
487  int d = i;
488  while (isdigit(buffer[d]) && isdigit(s[d]))
489  d++;
490  if (isdigit(buffer[d]))
491  return 1;
492  if (isdigit(s[d]))
493  return -1;
494 #endif
495  return toupper(buffer[i]) - toupper(s[i]);
496  }
497  return 0;
498 }
499 
500 int String::ReadLine(FILE * f)
501 {
502  len = 0;
503  buffer[len] = 0;
504 
505  if (f == NULL) return -1;
506 
507  int clen = 0;
508  char check[2] = {0, 0};
509 
510  int step = 128;
511  String format("%128[^\n\r]%1[\n\r]");
512 
513  int returnValue = 1;
514 
515  int io = 0;
516 
517  while (check[0] != '\n' && check[0] != '\r')
518  {
519  if (clen)
520  {
521  step *= 2;
522  format.printf("%%%d%s", step, "[^\n\r]%1[\n\r]");
523  }
524  clen += step;
525 
526  io = fscanf(f, format, LockBuffer(clen) + len, check);
527  UnlockBuffer();
528  // Avoid getting stuck on zero length lines (system specific!)
529  if (io == 0 && check[0] != '\n' && check[0] != '\r')
530  io = fscanf(f, "%1[\n\r]", check);
531  if (io == 0 || io == EOF)
532  {
533  // Set return value to indicate error/EOF
534  returnValue = -1;
535  break;
536  }
537  }
538 
539  if (check[0] == '\n') io = fscanf(f, "%*1[\r]");
540  if (check[0] == '\r') io = fscanf(f, "%*1[\n]");
541 
542  return returnValue;
543 }
544 
545 
546 String & String::Read(FILE * f)
547 {
548  len = 0;
549  buffer[len] = 0;
550 
551  if (f == NULL) return *this;
552 
553  int clen = 0;
554  char check[2] = {'G', 0};
555 
556  while (strchr(WHITESPACE, check[0]) == NULL)
557  {
558  clen += READBUF;
559  int io = fscanf(f, " %" READBUFSTR "[^" WHITESPACE "]"
560  "%1[" WHITESPACE "]", LockBuffer(clen) + len, check);
561  if (io == 0 || io == EOF) break;
562  UnlockBuffer();
563  }
564 
565  return *this;
566 }
567 
568 String & String::Read()
569 {
570  return Read(stdin);
571 }
572 
573 String & String::Read(IFILE & f)
574 {
575  len = 0;
576  buffer[len] = 0;
577 
578  if (f == NULL) return *this;
579 
580  bool leading = true;
581 
582  while (true)
583  {
584  int ch = ifgetc(f);
585 
586  if (ch == -1) break;
587 
588  if (strchr(WHITESPACE, ch) != NULL)
589  {
590  if (leading)
591  {
592  continue;
593  }
594  else
595  {
596  break;
597  }
598  }
599 
600  if (len + 1 == size)
601  Grow(len + 1);
602 
603  buffer[len++] = (char) ch;
604  buffer[len] = 0;
605 
606  leading = false;
607  }
608 
609  return *this;
610 }
611 
612 int String::ReadLine()
613 {
614  static int last = 0;
615  int ch;
616 
617  len = 0;
618  buffer[len] = 0;
619 
620  while (true)
621  {
622  ch = getchar();
623 
624  if (ch == EOF)
625  {
626  break;
627  }
628 
629  if (ch == 10)
630  {
631  if (last == 13)
632  {
633  last = 0;
634  continue;
635  }
636  else
637  {
638  last = 10;
639  break;
640  }
641  }
642 
643  if (ch == 13)
644  {
645  if (last == 10)
646  {
647  last = 0;
648  continue;
649  }
650  else
651  {
652  last = 13;
653  break;
654  }
655  }
656 
657  if (len + 1 == size)
658  {
659  Grow(len + 1);
660  }
661 
662  last = ch;
663  buffer[len++] = (char) last;
664  buffer[len] = 0;
665  }
666 
667  if ((ch == EOF) && (len == 0))
668  {
669  // Indicate error/EOF if nothing was read.
670  return -1;
671  }
672 
673  // Return success.
674  return 1;
675 }
676 
677 
678 // Read line using getc.
679 
680 #if defined(_WIN32)
681 int String::ReadLine(IFILE & f)
682 {
683  static int last = 0;
684  int ch;
685 
686  len = 0;
687  buffer[len] = 0;
688 
689  while (true)
690  {
691  ch = f->ifgetc();
692 
693  if (ch == EOF)
694  {
695  break;
696  }
697 
698  if (ch == 10)
699  {
700  if (last == 13)
701  {
702  last = 0;
703  continue;
704  }
705  else
706  {
707  last = 10;
708  break;
709  }
710  }
711 
712  if (ch == 13)
713  {
714  if (last == 10)
715  {
716  last = 0;
717  continue;
718  }
719  else
720  {
721  last = 13;
722  break;
723  }
724  }
725 
726  if (len + 1 == size)
727  {
728  Grow(len + 1);
729  }
730 
731  last = ch;
732  buffer[len++] = (char) last;
733  buffer[len] = 0;
734  }
735 
736  if ((ch == EOF) && (len == 0))
737  {
738  // Indicate error/EOF if nothing was read.
739  return -1;
740  }
741  return 1;
742 }
743 #else
744 int String::ReadLine(IFILE & f)
745 {
746  int ch;
747  char *ptr = buffer;
748  char *endBuffer = buffer + size;
749  len = 0;
750 
751  while ( ((ch = f->ifgetc()) != EOF) && (ch != '\n'))
752  {
753  if (ptr >= endBuffer - 1)
754  {
755  // resize: 1 byte for the next character, 1 byte
756  // for the NUL at the end.
757  Grow(len + 2);
758  endBuffer = buffer + size;
759  ptr = buffer + len;
760  }
761 
762  *ptr++ = ch;
763  len++;
764  }
765 
766  // NB: assumes that buffer is always allocated.
767  buffer[len] = 0;
768 
769  if ((ch == EOF) && (len == 0))
770  {
771  // Indicate error/EOF if nothing was read.
772  return -1;
773  }
774  return 1;
775 }
776 #endif
777 
778 void String::Write(FILE * f)
779 {
780  fprintf(f, "%s", buffer);
781 }
782 
783 void String::Write()
784 {
785  Write(stdout);
786 }
787 
788 void String::WriteLine()
789 {
790  WriteLine(stdout);
791 }
792 
793 void String::WriteLine(FILE * f)
794 {
795  if (f == NULL) return;
796  fprintf(f, "%s\n", buffer);
797 }
798 
799 std::ostream& operator << (std::ostream& os, const String& s)
800 {
801  return os << s.c_str();
802 }
803 
804 String String::Left(int n) const
805 {
806  if (n < 0) n = 0;
807  if (len < n) n = len;
808  String result(n);
809  memcpy(result.buffer, buffer, n);
810  result.buffer[result.len = n] = 0;
811  return result;
812 }
813 
814 String String::Right(int n) const
815 {
816  if (n < 0) n = 0;
817  if (len < n) n = len;
818  String result(n);
819  memcpy(result.buffer, buffer + len - n, n);
820  result.buffer[result.len = n] = 0;
821  return result;
822 }
823 
824 String String::SubStr(int start, int n) const
825 {
826  if (start < 0)
827  {
828  n += start;
829  start = 0;
830  };
831  n = min(len - start, n);
832  n = max(n, 0);
833  String result(n);
834  if (start > len) return result;
835  memcpy(result.buffer, buffer + start, n);
836  result.buffer[result.len = n] = 0;
837  return result;
838 }
839 
840 String String::SubStr(int start) const
841 {
842  return SubStr(start, len - start);
843 }
844 
845 String String::Mid(int start, int end) const
846 {
847  return SubStr(start, end - start + 1);
848 }
849 
850 int String::FindChar(char ch, int start) const
851 {
852  return caseSensitive ? FastFindChar(ch, start) : SlowFindChar(ch, start);
853 }
854 
855 int String::FastFindChar(char ch, int start) const
856 {
857  for (; start < len; start++)
858  if (buffer[start] == ch)
859  return start;
860  return -1;
861 }
862 
863 int String::SlowFindChar(char ch, int start) const
864 {
865  ch = (char) toupper(ch);
866  for (; start < len; start++)
867  if (toupper(buffer[start]) == ch)
868  return start;
869  return -1;
870 }
871 
872 int String::FindLastChar(char ch) const
873 {
874  return caseSensitive ? FastFindLastChar(ch) : SlowFindLastChar(ch);
875 }
876 
877 int String::FastFindLastChar(char ch) const
878 {
879  for (int start = len-1; start >= 0; start--)
880  if (buffer[start] == ch)
881  return start;
882  return -1;
883 }
884 
885 int String::SlowFindLastChar(char ch) const
886 {
887  ch = (char) toupper(ch);
888  for (int start = len-1 ; start >= 0; start--)
889  if (toupper(buffer[start]) == ch)
890  return start;
891  return -1;
892 }
893 
894 int String::Find(const String & pattern, int start) const
895 {
896  return caseSensitive ? FastFind(pattern, start) : SlowFind(pattern, start);
897 }
898 
899 // TODO -- We should have a better string search algorithm
900 
901 int String::FastFind(const String & pattern, int start) const
902 {
903  for (int i ; start <= len - pattern.Length(); start++)
904  if (buffer[start] == pattern[0])
905  {
906  for (i = 1; i < pattern.Length(); i++)
907  if (pattern[i] != buffer[start + i])
908  break;
909  if (i == pattern.Length()) return start;
910  }
911  return -1;
912 }
913 
914 int String::SlowFind(const String & pattern, int start) const
915 {
916  int firstchar = toupper(pattern[0]);
917 
918  for (int i ; start <= len - pattern.Length(); start++)
919  if (toupper(buffer[start]) == firstchar)
920  {
921  for (i = 1; i < pattern.Length(); i++)
922  if (toupper(pattern[i]) != toupper(buffer[start + i]))
923  break;
924  if (i == pattern.Length()) return start;
925  }
926  return -1;
927 }
928 
929 int String::SetLength(int newlen)
930 {
931  if (newlen > len)
932  {
933  Grow(newlen);
934  memset(buffer + len, ' ', newlen - len);
935  }
936  buffer[newlen] = 0;
937  return len = newlen;
938 }
939 
940 String & String::Filter(const String & s)
941 {
942  int to = 0;
943  for (int from = 0; from < len; from++)
944  if (s.FindChar(buffer[from]) != -1)
945  buffer[to++] = buffer[from];
946  buffer[len = to] = 0;
947  return *this;
948 }
949 
950 String & String::Filter(const char * s)
951 {
952  String filter(s);
953  return Filter(filter);
954 }
955 
956 String & String::ExcludeCharacters(const String & s)
957 {
958  int to = 0;
959  for (int from = 0; from < len; from++)
960  if (s.FindChar(buffer[from]) == -1)
961  buffer[to++] = buffer[from];
962  buffer[len = to] = 0;
963  return *this;
964 }
965 
966 String & String::ExcludeCharacters(const char * s)
967 {
968  String excluded(s);
969  return ExcludeCharacters(excluded);
970 }
971 
972 String operator + (const char * lhs, const String & rhs)
973 {
974  String result(lhs);
975  result += rhs;
976  return result;
977 }
978 
979 String operator + (char lhs, const String & rhs)
980 {
981  String result(lhs);
982  result += rhs;
983  return result;
984 }
985 
986 String operator + (int lhs, const String & rhs)
987 {
988  String result;
989  result = lhs;
990  result += rhs;
991  return result;
992 }
993 
994 String operator + (unsigned int lhs, const String & rhs)
995 {
996  String result;
997  result = lhs;
998  result += rhs;
999  return result;
1000 }
1001 
1002 long String::AsInteger() const
1003 {
1004  long returnValue = 0;
1005  if(!AsInteger(returnValue))
1006  {
1007  // This is not an integer, but nothing to do but return a value.
1008  }
1009  return(returnValue);
1010 }
1011 
1012 
1013 // Check that the string is an integer when converting it.
1014 // If the entire string is an integer, return true, if not, return false.
1015 bool String::AsInteger(long& intValue) const
1016 {
1017  long integer = 0;
1018  int base = 10;
1019  int pos = 0;
1020  int sign = 1;
1021  bool isInt = true;
1022 
1023  // If this is no value for this integer, return false.
1024  if (pos == len)
1025  {
1026  return(false);
1027  }
1028 
1029  if (buffer[pos] == '-')
1030  {
1031  sign = -1, pos++;
1032  }
1033 
1034  if ((len > pos + 2) && (buffer[pos] == '0') &&
1035  ((buffer[pos+1] == 'x') || (buffer[pos+1] == 'X')))
1036  {
1037  base = 16, pos += 2;
1038  }
1039 
1040  // If this is no value for this integer, return false.
1041  if (pos == len)
1042  {
1043  return(false);
1044  }
1045 
1046  for (; pos < len; pos++)
1047  {
1048  char digit = (char) toupper(buffer[pos]);
1049 
1050  if (digit >= '0' && digit <= '9')
1051  {
1052  integer = integer * base + digit - '0';
1053  }
1054  else if (digit >= 'A' && digit <= 'F' && base == 16)
1055  {
1056  integer = integer * base + digit - 'A' + 10;
1057  }
1058  else
1059  {
1060  isInt = false;
1061  break;
1062  }
1063  }
1064 
1065  intValue = sign*integer;
1066 
1067  return(isInt);
1068 }
1069 
1070 
1071 // Check that the string is an integer when converting it.
1072 // If the entire string is an integer, return true, if not, return false.
1073 bool String::AsInteger(int& intValue) const
1074 {
1075  int integer = 0;
1076  int base = 10;
1077  int pos = 0;
1078  int sign = 1;
1079  bool isInt = true;
1080 
1081  // If this is no value for this integer, return false.
1082  if (pos == len)
1083  {
1084  return(false);
1085  }
1086 
1087  if (buffer[pos] == '-')
1088  {
1089  sign = -1, pos++;
1090  }
1091 
1092  if ((len > pos + 2) && (buffer[pos] == '0') &&
1093  ((buffer[pos+1] == 'x') || (buffer[pos+1] == 'X')))
1094  {
1095  base = 16, pos += 2;
1096  }
1097 
1098  // If this is no value for this integer, return false.
1099  if (pos == len)
1100  {
1101  return(false);
1102  }
1103 
1104  for (; pos < len; pos++)
1105  {
1106  char digit = (char) toupper(buffer[pos]);
1107 
1108  if (digit >= '0' && digit <= '9')
1109  {
1110  integer = integer * base + digit - '0';
1111  }
1112  else if (digit >= 'A' && digit <= 'F' && base == 16)
1113  {
1114  integer = integer * base + digit - 'A' + 10;
1115  }
1116  else
1117  {
1118  isInt = false;
1119  break;
1120  }
1121  }
1122 
1123  intValue = sign*integer;
1124 
1125  return(isInt);
1126 }
1127 
1128 
1129 String & String::Invert()
1130 {
1131  for (int i = 0, j = len - 1; i < j; i++, j--)
1132  {
1133  char tmp = buffer[i];
1134  buffer[i] = buffer[j];
1135  buffer[j] = tmp;
1136  }
1137  return *this;
1138 }
1139 
1140 String String::RightToLeft()
1141 {
1142  String result(*this);
1143  result.Invert();
1144  return result;
1145 }
1146 
1147 String & String::Invert(const String & s)
1148 {
1149  Copy(s);
1150  return Invert();
1151 }
1152 
1153 int String::CompareToStem(const String & stem) const
1154 {
1155  if (caseSensitive)
1156  return String::FastCompareToStem(stem);
1157  else
1158  return String::SlowCompareToStem(stem);
1159 }
1160 
1161 int String::FastCompareToStem(const String & stem) const
1162 {
1163  for (int i = 0; i < stem.len; i++)
1164  if (buffer[i] - stem.buffer[i])
1165  {
1166 #ifdef NATURAL_ORDERING
1167  int d = i;
1168  while (isdigit(buffer[d]) && isdigit(stem.buffer[d]) && d < stem.len)
1169  d++;
1170  if (isdigit(buffer[d]) && d < stem.len)
1171  return 1;
1172  if (isdigit(stem.buffer[d]))
1173  return -1;
1174 #endif
1175  return buffer[i] - stem.buffer[i];
1176  }
1177  return 0;
1178 }
1179 
1180 int String::SlowCompareToStem(const String & stem) const
1181 {
1182  for (int i = 0; i < stem.len; i++)
1183  if (toupper(buffer[i]) - toupper(stem.buffer[i]))
1184  {
1185 #ifdef NATURAL_ORDERING
1186  int d = i;
1187  while (isdigit(buffer[d]) && isdigit(stem.buffer[d]) && d < stem.len)
1188  d++;
1189  if (isdigit(buffer[d]) && d < stem.len)
1190  return 1;
1191  if (isdigit(stem.buffer[d]))
1192  return -1;
1193 #endif
1194  return toupper(buffer[i]) - toupper(stem.buffer[i]);
1195  }
1196  return 0;
1197 }
1198 
1199 int String::CompareToStem(const char * stem) const
1200 {
1201  if (caseSensitive)
1202  return String::FastCompareToStem(stem);
1203  else
1204  return String::SlowCompareToStem(stem);
1205 }
1206 
1207 int String::FastCompareToStem(const char * stem) const
1208 {
1209  for (int i = 0; stem[i] != 0; i++)
1210  if (buffer[i] - stem[i])
1211  return buffer[i] - stem[i];
1212  return 0;
1213 }
1214 
1215 int String::SlowCompareToStem(const char * stem) const
1216 {
1217  for (int i = 0; stem[i] != 0; i++)
1218  if (toupper(buffer[i]) - toupper(stem[i]))
1219  return toupper(buffer[i]) - toupper(stem[i]);
1220  return 0;
1221 }
1222 
1223 int String::MatchesBeginningOf(const String & stem) const
1224 {
1225  if (caseSensitive)
1226  return String::FastMatchesBeginningOf(stem);
1227  else
1228  return String::SlowMatchesBeginningOf(stem);
1229 }
1230 
1231 int String::FastMatchesBeginningOf(const String & stem) const
1232 {
1233  for (int i = 0; i < len; i++)
1234  if (buffer[i] - stem.buffer[i])
1235  return buffer[i] - stem.buffer[i];
1236  return 0;
1237 }
1238 
1239 int String::SlowMatchesBeginningOf(const String & stem) const
1240 {
1241  for (int i = 0; i < len; i++)
1242  if (toupper(buffer[i]) - toupper(stem.buffer[i]))
1243  return toupper(buffer[i]) - toupper(stem.buffer[i]);
1244  return 0;
1245 }
1246 
1247 int String::MatchesBeginningOf(const char * stem) const
1248 {
1249  if (caseSensitive)
1250  return String::FastMatchesBeginningOf(stem);
1251  else
1252  return String::SlowMatchesBeginningOf(stem);
1253 }
1254 
1255 int String::FastMatchesBeginningOf(const char * stem) const
1256 {
1257  for (int i = 0; i < len; i++)
1258  if (buffer[i] - stem[i])
1259  return buffer[i] - stem[i];
1260  return 0;
1261 }
1262 
1263 int String::SlowMatchesBeginningOf(const char * stem) const
1264 {
1265  for (int i = 0; i < len; i++)
1266  if (toupper(buffer[i]) - toupper(stem[i]))
1267  return toupper(buffer[i]) - toupper(stem[i]);
1268  return 0;
1269 }
1270 
1271 String & String::Trim(char character)
1272 {
1273  int first = 0;
1274  while (buffer[first] && buffer[first] == character)
1275  first++;
1276 
1277  int last = len - 1;
1278  while (last >= 0 && buffer[last] == character)
1279  last--;
1280 
1281  int out = 0;
1282  while (first <= last)
1283  buffer[out++] = buffer[first++];
1284 
1285  buffer[len = out] = 0;
1286 
1287  return *this;
1288 }
1289 
1290 String & String::Trim()
1291 {
1292  int first = 0;
1293  while (buffer[first] && isspace(buffer[first]))
1294  first++;
1295 
1296  int last = len - 1;
1297  while (last >= 0 && isspace(buffer[last]))
1298  last--;
1299 
1300  int out = 0;
1301  while (first <= last)
1302  buffer[out++] = buffer[first++];
1303 
1304  buffer[len = out] = 0;
1305 
1306  return *this;
1307 }
1308 
1309 vector<String> *String::Split(char splitChar)
1310 {
1311  vector<String> *result = new vector<String>;
1312  String word;
1313 
1314  for (int i = 0; i<Length(); i++)
1315  {
1316  if ((*this)[i]==splitChar)
1317  {
1318  result->push_back(word);
1319  word.Clear();
1320  }
1321  else
1322  word.Add((*this)[i]);
1323  }
1324  if (word.Length()>0) result->push_back(word);
1325  return result;
1326 }
1327 
1328 
1329 #define VSNPRINTF_NOT_CHECKED 0
1330 #define VSNPRINTF_IS_OK 1
1331 #define VSNPRINTF_NOT_OK 2
1332 
1333 int String::vsnprintfChecked = 0;
1334 
1335 int String::printf(const char * format, ...)
1336 {
1337  va_list ap;
1338  va_start(ap, format);
1339 
1340  vprintf(format, ap);
1341 
1342  va_end(ap);
1343  return len;
1344 }
1345 
1346 int String::catprintf(const char * format, ...)
1347 {
1348  va_list ap;
1349  va_start(ap, format);
1350 
1351  vcatprintf(format, ap);
1352 
1353  va_end(ap);
1354  return len;
1355 }
1356 
1357 int String::vprintf(const char * format, va_list ap)
1358 {
1359  check_vsnprintf();
1360 
1361  while (true)
1362  {
1363  int bytes_needed;
1364 #ifdef va_copy
1365  va_list arguments;
1366  va_copy(arguments, ap);
1367 #else
1368  va_list & arguments = ap;
1369 #endif
1370 
1371  if (vsnprintfChecked == VSNPRINTF_IS_OK)
1372  bytes_needed = vsnprintf(buffer, size, format, arguments);
1373  else
1374  bytes_needed = my_vsnprintf(buffer, size, format, arguments);
1375 
1376 #ifdef va_copy
1377  va_end(arguments);
1378 #endif
1379 
1380  if (bytes_needed >= size)
1381  Grow(bytes_needed);
1382  else if (bytes_needed == -1)
1383  Grow(size * 2);
1384  else
1385  {
1386  return len = bytes_needed;
1387  }
1388  }
1389 }
1390 
1391 void String::check_vsnprintf()
1392 {
1393  if (vsnprintfChecked == VSNPRINTF_NOT_CHECKED)
1394  {
1395  char temp[100];
1396 
1397  memset(temp, 0, 100);
1398  int check = snprintf(temp, 5, "%5s", "VSNPRINTF");
1399 
1400  if (temp[6] != 0 || temp[7] != 0 || (check != 9 && check != -1))
1401  /*
1402  error("This program requires a working version of vsnprintf\n"
1403  "However, vsnprintf in the current library seems buggy\n\n"
1404  "Recompiling this program with the -D__REPLACE_SNPRINTF__ flag\n"
1405  "may solve this problem.\n\n");
1406  */
1407  vsnprintfChecked = VSNPRINTF_NOT_OK;
1408  else
1409  vsnprintfChecked = VSNPRINTF_IS_OK;
1410  }
1411 }
1412 
1413 int String::vcatprintf(const char * format, va_list ap)
1414 {
1415  check_vsnprintf();
1416 
1417  if (len == size)
1418  Grow(size * 2);
1419 
1420  while (true)
1421  {
1422  int bytes_needed;
1423 #ifdef va_copy
1424  va_list arguments;
1425  va_copy(arguments, ap);
1426 #else
1427  va_list & arguments = ap;
1428 #endif
1429 
1430  if (vsnprintfChecked == VSNPRINTF_IS_OK)
1431  bytes_needed = len + vsnprintf(buffer + len, size - len, format, arguments);
1432  else
1433  bytes_needed = len + my_vsnprintf(buffer + len, size - len, format, arguments);
1434 
1435 #ifdef va_copy
1436  va_end(arguments);
1437 #endif
1438 
1439  if (bytes_needed >= size)
1440  Grow(bytes_needed);
1441  else if (bytes_needed < len)
1442  Grow(size * 2);
1443  else
1444  {
1445  return len = bytes_needed;
1446  }
1447  }
1448 }
1449 
1450 FILE * String::my_vsnprintf_file = NULL;
1451 
1452 int String::my_vsnprintf(char * buffer, int bufsize, const char * format, va_list args)
1453 {
1454  if (my_vsnprintf_file == NULL)
1455  {
1456  my_vsnprintf_file = tmpfile();
1457  atexit(my_vsnprintf_close_file);
1458  }
1459 
1460  rewind(my_vsnprintf_file);
1461 
1462  int len = vfprintf(my_vsnprintf_file, format, args);
1463 
1464  rewind(my_vsnprintf_file);
1465 
1466  if (len < bufsize)
1467  buffer[bufsize = len] = 0;
1468  int numRead = fread(buffer, 1, bufsize, my_vsnprintf_file);
1469  if(numRead != bufsize)
1470  {
1471  std::cerr
1472  << "Warning, StringBasics failed reading stream in my_vsnprintf\n";
1473  }
1474  return len;
1475 }
1476 
1477 int String::my_snprintf(char * buffer, int bufsize, const char * format, ...)
1478 {
1479  va_list ap;
1480  va_start(ap, format);
1481 
1482  int bytes = my_vsnprintf(buffer, bufsize, format, ap);
1483 
1484  va_end(ap);
1485 
1486  return bytes;
1487 }
1488 
1489 void String::my_vsnprintf_close_file()
1490 {
1491  fclose(my_vsnprintf_file);
1492 }
1493 
1494 bool String::IsNumber()
1495 {
1496  int pos = 0;
1497  bool digits = false;
1498 
1499  // Skip leading sign
1500  if (buffer[pos] == '-' || buffer[pos] == '+')
1501  pos++;
1502 
1503  // Check integer portion
1504  while (buffer[pos] >= '0' && buffer[pos] <= '9')
1505  pos++, digits = true;
1506 
1507  // Skip decimal point
1508  if (buffer[pos] == '.')
1509  {
1510  pos++;
1511 
1512  // Check fractional portion
1513  while (buffer[pos] >= '0' && buffer[pos] <= '9')
1514  pos++, digits = true;
1515  }
1516 
1517  if (!digits) return false;
1518 
1519  // Check exponent
1520  if (buffer[pos] == 'E' || buffer[pos] == 'e')
1521  {
1522  pos++;
1523 
1524  // Skip leading sign
1525  if (buffer[pos] == '-' || buffer[pos] == '+')
1526  pos++;
1527 
1528  digits = false;
1529 
1530  // Check exponent digits
1531  while (buffer[pos] >= '0' && buffer[pos] <= '9')
1532  pos++, digits = true;
1533  }
1534 
1535  return (pos == len) && digits;
1536 }
1537 
1538 void String::Fill(char ch, int length)
1539 {
1540  if (length >= 0)
1541  SetLength(length);
1542 
1543  for (int i = 0; i < len; i++)
1544  buffer[i] = ch;
1545 }
1546 
1547 String & String::Reverse()
1548 {
1549  for (int i = 0, j = len - 1; i < j; i++, j--)
1550  {
1551  int tmp = buffer[i];
1552  buffer[i] = buffer[j];
1553  buffer[j] = tmp;
1554  }
1555 
1556  return *this;
1557 }
1558 
1559 // String::LeftClip() trims the string so only characters after clipPoint remain
1560 
1561 String & String::LeftClip(int clipAmount)
1562 {
1563  if (clipAmount == 0)
1564  return *this;
1565 
1566  if (clipAmount > Length())
1567  {
1568  len = 0;
1569  return *this;
1570  }
1571 
1572  // Use memory move, because the two blocks can overlap
1573  memmove(buffer, buffer + clipAmount, len - clipAmount);
1574  buffer[len -= clipAmount] = 0;
1575 
1576  return *this;
1577 }
1578 
1579 String & String::RightClip(int clipAmount)
1580 {
1581  if (clipAmount == 0) return *this;
1582 
1583  if (clipAmount > Length())
1584  {
1585  len = 0;
1586  return *this;
1587  }
1588 
1589  len -= clipAmount;
1590  buffer[len] = 0;
1591 
1592  return *this;
1593 }
1594 
1595 // Implementation of long double convertors is in flux across different platforms
1596 
1597 #ifdef __GNUC__
1598 String::operator long double() const
1599 {
1600  return strtold(buffer, NULL);
1601 }
1602 #else
1603 #ifdef __BORLANDC__
1604 String::operator long double() const
1605 {
1606  return _strtold(buffer, NULL);
1607 }
1608 #else
1609 String::operator long double() const
1610 {
1611  return atof(buffer);
1612 }
1613 #endif
1614 #endif
1615 
1616 
int ifgetc(IFILE file)
Get a character from the file.
Definition: InputFile.h:615
InputFile & operator<<(InputFile &stream, const std::string &str)
Write to a file using streaming.
Definition: InputFile.h:736
Class for easily reading/writing files without having to worry about file type (uncompressed,...
Definition: InputFile.h:37
int ifgetc()
Get a character from the file.
Definition: InputFile.h:324