00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "StringBasics.h"
00019 #include "Error.h"
00020 #include "Constant.h"
00021 #include "MathConstant.h"
00022
00023 #include <string.h>
00024 #include <ctype.h>
00025 #include <stdarg.h>
00026
00027 #define SWP(A,B) {int tmp=a; a=b; b=tmp;}
00028
00029 #ifdef _MSC_VER
00030 #ifndef snprintf
00031 #define vsnprintf _vsnprintf
00032 #define snprintf _snprintf
00033 #endif
00034 #endif
00035
00036
00037
00038
00039
00040 #define NATURAL_ORDERING 1
00041
00042 int String::alloc = 8;
00043 bool String::caseSensitive = true;
00044
00045 void String::NewString(int startsize)
00046 {
00047 len = 0;
00048 size = (startsize + alloc) / alloc * alloc;
00049 buffer = new char [size];
00050 buffer[0] = 0;
00051 }
00052
00053 String::String(const char * s)
00054 {
00055 int clen = s == NULL ? 0 : strlen(s);
00056 NewString(clen);
00057 if (clen)
00058 {
00059 len = clen;
00060 memcpy(buffer, s, len + 1);
00061 }
00062 }
00063
00064 String::String(char ch, int count)
00065 {
00066 NewString(count);
00067 memset(buffer, ch, count);
00068 buffer[count] = 0;
00069 len = count;
00070 }
00071
00072 String::String(const String & s)
00073 {
00074 len = s.len;
00075 size = (s.len + alloc) / alloc * alloc;;
00076 buffer = new char [size];
00077 memcpy(buffer, s.buffer, len + 1);
00078 }
00079
00080 void String::Grow(int newSize)
00081 {
00082 if (newSize >= size)
00083 {
00084 if ((newSize >> 1) >= size)
00085 size = (newSize + alloc) / alloc * alloc;
00086 else
00087 {
00088 size = alloc;
00089 while (size <= newSize)
00090 size *= 2;
00091 }
00092
00093 char * tmp = new char [size];
00094
00095 memcpy(tmp, buffer, len + 1);
00096 delete [] buffer;
00097 buffer = tmp;
00098 }
00099 }
00100
00101 void String::Swap(String & s)
00102 {
00103 char * temp = s.buffer;
00104 s.buffer = buffer;
00105 buffer = temp;
00106
00107 int swap = s.size;
00108 s.size = size;
00109 size = swap;
00110
00111 swap = s.len;
00112 s.len = len;
00113 len = swap;
00114 }
00115
00116 String & String::Copy(const String & s)
00117 {
00118 Grow(s.len);
00119 len = s.len;
00120 memcpy(buffer, s.buffer, len + 1);
00121 return *this;
00122 }
00123
00124 String & String::Copy(const String & s, int start, int n)
00125 {
00126 if (s.len <= start) return Clear();
00127 if (s.len < start + n) n = s.len - start;
00128 Grow(n);
00129 memcpy(buffer, s.buffer + start, n);
00130 buffer[len = n] = 0;
00131 return *this;
00132 }
00133
00134 String & String::Copy(const char * s)
00135 {
00136 if (s == NULL)
00137 {
00138 len = 0;
00139 buffer[0] = 0;
00140 }
00141 else
00142 {
00143 int clen = strlen(s);
00144 Grow(clen);
00145 len = clen;
00146 memcpy(buffer, s, len + 1);
00147 }
00148 return *this;
00149 }
00150
00151 String & String::ToUpper()
00152 {
00153 for (int i = 0; i < len; i++)
00154 buffer[i] = (char) toupper(buffer[i]);
00155 return *this;
00156 }
00157
00158 String & String::ToLower()
00159 {
00160 for (int i = 0; i < len; i++)
00161 buffer[i] = (char) tolower(buffer[i]);
00162 return *this;
00163 }
00164
00165 String String::AsUpper()
00166 {
00167 String temp;
00168 temp = *this;
00169 return temp.ToUpper();
00170 }
00171
00172 String String::AsLower()
00173 {
00174 String temp;
00175 temp = *this;
00176 return temp.ToLower();
00177 }
00178
00179 String String::Capitalize()
00180 {
00181 String temp;
00182 temp = *this;
00183 temp.buffer[0] = (char) toupper(temp.buffer[0]);
00184 return temp;
00185 }
00186
00187 String & String::operator = (const String & rhs)
00188 {
00189 Copy(rhs);
00190 return *this;
00191 }
00192
00193 String & String::operator = (const char * rhs)
00194 {
00195 Copy(rhs);
00196 return * this;
00197 }
00198
00199 String & String::operator += (const String & rhs)
00200 {
00201 Grow(len + rhs.len);
00202 memcpy(buffer + len, rhs.buffer, rhs.len + 1);
00203 len += rhs.len;
00204 return *this;
00205 }
00206
00207 String & String::operator += (const char * rhs)
00208 {
00209 if (rhs != NULL)
00210 {
00211 int clen = strlen(rhs);
00212 Grow(len + clen);
00213 memcpy(buffer + len, rhs, clen + 1);
00214 len += clen;
00215 }
00216 return *this;
00217 }
00218
00219 String String::operator + (const String & rhs) const
00220 {
00221 String result(len + rhs.len);
00222 memcpy(result.buffer, buffer, len);
00223 memcpy(result.buffer + len, rhs.buffer, rhs.len + 1);
00224 result.len = len + rhs.len;
00225 return result;
00226 }
00227
00228 String String::operator + (const char * rhs) const
00229 {
00230 if (rhs != NULL)
00231 {
00232 int clen = strlen(rhs);
00233 String result(len + clen);
00234 memcpy(result.buffer, buffer, len);
00235 memcpy(result.buffer + len, rhs, clen + 1);
00236 result.len = len + clen;
00237 return result;
00238 }
00239 return *this;
00240 }
00241
00242 String & String::operator = (char ch)
00243 {
00244 if (ch)
00245 {
00246 Grow(1);
00247 buffer[0] = ch;
00248 buffer[1] = 0;
00249 len = 1;
00250 }
00251 else
00252 len = buffer[0] = 0;
00253 return *this;
00254 }
00255
00256 String & String::operator += (char ch)
00257 {
00258 if (ch)
00259 {
00260 Grow(len + 1);
00261 buffer[len] = ch;
00262 buffer[++len] = 0;
00263 }
00264 return *this;
00265 }
00266
00267 String String::operator + (char ch) const
00268 {
00269 String result(*this);
00270 result += ch;
00271 return result;
00272 }
00273
00274 String & String::operator = (int rhs)
00275 {
00276 Clear();
00277
00278 if (rhs < 0)
00279 {
00280 Add('-');
00281 *this += (unsigned int) -rhs;
00282 }
00283 else
00284 *this = (unsigned int) rhs;
00285 return *this;
00286 }
00287
00288 String & String::operator = (unsigned int rhs)
00289 {
00290 Clear();
00291
00292 unsigned long long base = 10;
00293 int digits = 1;
00294
00295 while (rhs >= base)
00296 {
00297 base *= 10;
00298 digits++;
00299 }
00300
00301 Grow(digits);
00302
00303 while (base /= 10)
00304 {
00305 char ch = char(rhs / base);
00306 rhs = rhs - ch * base;
00307 buffer[len++] = char(ch + '0');
00308 }
00309 buffer[len] = 0;
00310 return *this;
00311 };
00312
00313 String String::operator + (int rhs) const
00314 {
00315 String result(*this);
00316 result += rhs;
00317 return result;
00318 };
00319
00320 String String::operator + (unsigned int rhs) const
00321 {
00322 String result(*this);
00323 result += rhs;
00324 return result;
00325 };
00326
00327 String & String::operator += (int rhs)
00328 {
00329 String temp;
00330 temp = rhs;
00331 return *this += temp;
00332 }
00333
00334 String & String::operator += (unsigned int rhs)
00335 {
00336 String temp;
00337 temp = rhs;
00338 return *this += temp;
00339 }
00340
00341 String & String::operator *= (unsigned int rhs)
00342 {
00343 if (rhs == 0)
00344 Clear();
00345 else
00346 {
00347 String original(*this);
00348
00349 Grow(len * rhs);
00350
00351 for (unsigned int i = 1; i < rhs; i++)
00352 *this += original;
00353 }
00354 return *this;
00355 }
00356
00357 String & String::operator = (double rhs)
00358 {
00359 LockBuffer(32);
00360 sprintf(buffer, "%.3f", rhs);
00361 UnlockBuffer();
00362 return *this;
00363 }
00364
00365 String String::operator + (double rhs) const
00366 {
00367 String result(*this);
00368 result += rhs;
00369 return result;
00370 }
00371
00372 String & String::operator += (double rhs)
00373 {
00374 String temp;
00375 temp = rhs;
00376 return *this += temp;
00377 }
00378
00379 char * String::LockBuffer(int min)
00380 {
00381 if (min > 0) Grow(min);
00382 return buffer;
00383 }
00384
00385 String & String::UnlockBuffer()
00386 {
00387 for (len = 0; len < size; len++)
00388 if (buffer[len] == 0)
00389 return *this;
00390 error("BasicString - direct access overflowed buffer");
00391 return *this;
00392 }
00393
00394 int String::Compare(const String & s) const
00395 {
00396 if (caseSensitive)
00397 return String::FastCompare(s);
00398 else
00399 return String::SlowCompare(s);
00400 }
00401
00402 int String::Compare(const char * s) const
00403 {
00404 return caseSensitive ? FastCompare(s) : SlowCompare(s);
00405 }
00406
00407 int String::FastCompare(const String & s) const
00408 {
00409 for (int i = 0; i <= len; i++)
00410 if (buffer[i] - s.buffer[i])
00411 {
00412 #ifdef NATURAL_ORDERING
00413 int d = i;
00414 while (isdigit(buffer[d]) && isdigit(s.buffer[d]))
00415 d++;
00416 if (isdigit(buffer[d]))
00417 return 1;
00418 if (isdigit(s.buffer[d]))
00419 return -1;
00420 #endif
00421 return buffer[i] - s.buffer[i];
00422 }
00423 return 0;
00424 }
00425
00426 int String::FastCompare(const char * s) const
00427 {
00428 if (s == NULL)
00429 return -len;
00430
00431 for (int i = 0; i <= len; i++)
00432 if (buffer[i] - s[i])
00433 {
00434 #ifdef NATURAL_ORDERING
00435 int d = i;
00436 while (isdigit(buffer[d]) && isdigit(s[d]))
00437 d++;
00438 if (isdigit(buffer[d]))
00439 return 1;
00440 if (isdigit(s[d]))
00441 return -1;
00442 #endif
00443 return buffer[i] - s[i];
00444 }
00445 return 0;
00446 }
00447
00448 int String::SlowCompare(const String & s) const
00449 {
00450 for (int i = 0; i <= len; i++)
00451 if (toupper(buffer[i]) - toupper(s.buffer[i]))
00452 {
00453 #ifdef NATURAL_ORDERING
00454 int d = i;
00455 while (isdigit(buffer[d]) && isdigit(s[d]))
00456 d++;
00457 if (isdigit(buffer[d]))
00458 return 1;
00459 if (isdigit(s.buffer[d]))
00460 return -1;
00461 #endif
00462 return toupper(buffer[i]) - toupper(s.buffer[i]);
00463 }
00464 return 0;
00465 }
00466
00467 int String::SlowCompare(const char * s) const
00468 {
00469 if (s == NULL)
00470 return -len;
00471
00472 for (int i = 0; i <= len; i++)
00473 if (toupper(buffer[i]) - toupper(s[i]))
00474 {
00475 #ifdef NATURAL_ORDERING
00476 int d = i;
00477 while (isdigit(buffer[d]) && isdigit(s[d]))
00478 d++;
00479 if (isdigit(buffer[d]))
00480 return 1;
00481 if (isdigit(s[d]))
00482 return -1;
00483 #endif
00484 return toupper(buffer[i]) - toupper(s[i]);
00485 }
00486 return 0;
00487 }
00488
00489 int String::ReadLine(FILE * f)
00490 {
00491 len = 0;
00492 buffer[len] = 0;
00493
00494 if (f == NULL) return -1;
00495
00496 int clen = 0;
00497 char check[2] = {0, 0};
00498
00499 int step = 128;
00500 String format("%128[^\n\r]%1[\n\r]");
00501
00502 int returnValue = 1;
00503
00504 int io = 0;
00505
00506 while (check[0] != '\n' && check[0] != '\r')
00507 {
00508 if (clen)
00509 {
00510 step *= 2;
00511 format.printf("%%%d%s", step, "[^\n\r]%1[\n\r]");
00512 }
00513 clen += step;
00514
00515 io = fscanf(f, format, LockBuffer(clen) + len, check);
00516 UnlockBuffer();
00517
00518 if (io == 0 && check[0] != '\n' && check[0] != '\r')
00519 io = fscanf(f, "%1[\n\r]", check);
00520 if (io == 0 || io == EOF)
00521 {
00522
00523 returnValue = -1;
00524 break;
00525 }
00526 }
00527
00528 if (check[0] == '\n') io = fscanf(f, "%*1[\r]");
00529 if (check[0] == '\r') io = fscanf(f, "%*1[\n]");
00530
00531 return returnValue;
00532 }
00533
00534
00535 String & String::Read(FILE * f)
00536 {
00537 len = 0;
00538 buffer[len] = 0;
00539
00540 if (f == NULL) return *this;
00541
00542 int clen = 0;
00543 char check[2] = {'G', 0};
00544
00545 while (strchr(WHITESPACE, check[0]) == NULL)
00546 {
00547 clen += READBUF;
00548 int io = fscanf(f, " %" READBUFSTR "[^" WHITESPACE "]"
00549 "%1[" WHITESPACE "]", LockBuffer(clen) + len, check);
00550 if (io == 0 || io == EOF) break;
00551 UnlockBuffer();
00552 }
00553
00554 return *this;
00555 }
00556
00557 String & String::Read()
00558 {
00559 return Read(stdin);
00560 }
00561
00562 String & String::Read(IFILE & f)
00563 {
00564 len = 0;
00565 buffer[len] = 0;
00566
00567 if (f == NULL) return *this;
00568
00569 bool leading = true;
00570
00571 while (true)
00572 {
00573 int ch = ifgetc(f);
00574
00575 if (ch == -1) break;
00576
00577 if (strchr(WHITESPACE, ch) != NULL)
00578 {
00579 if (leading)
00580 {
00581 continue;
00582 }
00583 else
00584 {
00585 break;
00586 }
00587 }
00588
00589 if (len + 1 == size)
00590 Grow(len + 1);
00591
00592 buffer[len++] = (char) ch;
00593 buffer[len] = 0;
00594
00595 leading = false;
00596 }
00597
00598 return *this;
00599 }
00600
00601 int String::ReadLine()
00602 {
00603 static int last = 0;
00604 int ch;
00605
00606 len = 0;
00607 buffer[len] = 0;
00608
00609 while (true)
00610 {
00611 ch = getchar();
00612
00613 if (ch == EOF)
00614 {
00615 break;
00616 }
00617
00618 if (ch == 10)
00619 {
00620 if (last == 13)
00621 {
00622 last = 0;
00623 continue;
00624 }
00625 else
00626 {
00627 last = 10;
00628 break;
00629 }
00630 }
00631
00632 if (ch == 13)
00633 {
00634 if (last == 10)
00635 {
00636 last = 0;
00637 continue;
00638 }
00639 else
00640 {
00641 last = 13;
00642 break;
00643 }
00644 }
00645
00646 if (len + 1 == size)
00647 {
00648 Grow(len + 1);
00649 }
00650
00651 last = ch;
00652 buffer[len++] = (char) last;
00653 buffer[len] = 0;
00654 }
00655
00656 if ((ch == EOF) && (len == 0))
00657 {
00658
00659 return -1;
00660 }
00661
00662
00663 return 1;
00664 }
00665
00666
00667
00668
00669 #if defined(WIN32)
00670 int String::ReadLine(IFILE & f)
00671 {
00672 static int last = 0;
00673 int ch;
00674
00675 len = 0;
00676 buffer[len] = 0;
00677
00678 while (true)
00679 {
00680 ch = f->ifgetc();
00681
00682 if (ch == EOF)
00683 {
00684 break;
00685 }
00686
00687 if (ch == 10)
00688 {
00689 if (last == 13)
00690 {
00691 last = 0;
00692 continue;
00693 }
00694 else
00695 {
00696 last = 10;
00697 break;
00698 }
00699 }
00700
00701 if (ch == 13)
00702 {
00703 if (last == 10)
00704 {
00705 last = 0;
00706 continue;
00707 }
00708 else
00709 {
00710 last = 13;
00711 break;
00712 }
00713 }
00714
00715 if (len + 1 == size)
00716 {
00717 Grow(len + 1);
00718 }
00719
00720 last = ch;
00721 buffer[len++] = (char) last;
00722 buffer[len] = 0;
00723 }
00724
00725 if ((ch == EOF) && (len == 0))
00726 {
00727
00728 return -1;
00729 }
00730 return 1;
00731 }
00732 #else
00733 int String::ReadLine(IFILE & f)
00734 {
00735 int ch;
00736 char *ptr = buffer;
00737 char *endBuffer = buffer + size;
00738 len = 0;
00739
00740 while ( ((ch = f->ifgetc()) != EOF) && (ch != '\n'))
00741 {
00742 if (ptr == endBuffer)
00743 {
00744
00745
00746 Grow(len + 2);
00747 endBuffer = buffer + size;
00748 ptr = buffer + len;
00749 }
00750
00751 *ptr++ = ch;
00752 len++;
00753 }
00754
00755
00756 buffer[len] = 0;
00757
00758 if ((ch == EOF) && (len == 0))
00759 {
00760
00761 return -1;
00762 }
00763 return 1;
00764 }
00765 #endif
00766
00767 void String::Write(FILE * f)
00768 {
00769 fprintf(f, "%s", buffer);
00770 }
00771
00772 void String::Write()
00773 {
00774 Write(stdout);
00775 }
00776
00777 void String::WriteLine()
00778 {
00779 WriteLine(stdout);
00780 }
00781
00782 void String::WriteLine(FILE * f)
00783 {
00784 if (f == NULL) return;
00785 fprintf(f, "%s\n", buffer);
00786 }
00787
00788 std::ostream& operator << (std::ostream& os, const String& s)
00789 {
00790 return os << s.c_str();
00791 }
00792
00793 String String::Left(int n) const
00794 {
00795 if (n < 0) n = 0;
00796 if (len < n) n = len;
00797 String result(n);
00798 memcpy(result.buffer, buffer, n);
00799 result.buffer[result.len = n] = 0;
00800 return result;
00801 }
00802
00803 String String::Right(int n) const
00804 {
00805 if (n < 0) n = 0;
00806 if (len < n) n = len;
00807 String result(n);
00808 memcpy(result.buffer, buffer + len - n, n);
00809 result.buffer[result.len = n] = 0;
00810 return result;
00811 }
00812
00813 String String::SubStr(int start, int n) const
00814 {
00815 if (start < 0)
00816 {
00817 n += start;
00818 start = 0;
00819 };
00820 n = min(len - start, n);
00821 n = max(n, 0);
00822 String result(n);
00823 if (start > len) return result;
00824 memcpy(result.buffer, buffer + start, n);
00825 result.buffer[result.len = n] = 0;
00826 return result;
00827 }
00828
00829 String String::SubStr(int start) const
00830 {
00831 return SubStr(start, len - start);
00832 }
00833
00834 String String::Mid(int start, int end) const
00835 {
00836 return SubStr(start, end - start + 1);
00837 }
00838
00839 int String::FindChar(char ch, int start) const
00840 {
00841 return caseSensitive ? FastFindChar(ch, start) : SlowFindChar(ch, start);
00842 }
00843
00844 int String::FastFindChar(char ch, int start) const
00845 {
00846 for (; start < len; start++)
00847 if (buffer[start] == ch)
00848 return start;
00849 return -1;
00850 }
00851
00852 int String::SlowFindChar(char ch, int start) const
00853 {
00854 ch = (char) toupper(ch);
00855 for (; start < len; start++)
00856 if (toupper(buffer[start]) == ch)
00857 return start;
00858 return -1;
00859 }
00860
00861 int String::FindLastChar(char ch) const
00862 {
00863 return caseSensitive ? FastFindLastChar(ch) : SlowFindLastChar(ch);
00864 }
00865
00866 int String::FastFindLastChar(char ch) const
00867 {
00868 for (int start = len-1; start >= 0; start--)
00869 if (buffer[start] == ch)
00870 return start;
00871 return -1;
00872 }
00873
00874 int String::SlowFindLastChar(char ch) const
00875 {
00876 ch = (char) toupper(ch);
00877 for (int start = len-1 ; start >= 0; start--)
00878 if (toupper(buffer[start]) == ch)
00879 return start;
00880 return -1;
00881 }
00882
00883 int String::Find(const String & pattern, int start) const
00884 {
00885 return caseSensitive ? FastFind(pattern, start) : SlowFind(pattern, start);
00886 }
00887
00888
00889
00890 int String::FastFind(const String & pattern, int start) const
00891 {
00892 for (int i ; start <= len - pattern.Length(); start++)
00893 if (buffer[start] == pattern[0])
00894 {
00895 for (i = 1; i < pattern.Length(); i++)
00896 if (pattern[i] != buffer[start + i])
00897 break;
00898 if (i == pattern.Length()) return start;
00899 }
00900 return -1;
00901 }
00902
00903 int String::SlowFind(const String & pattern, int start) const
00904 {
00905 int firstchar = toupper(pattern[0]);
00906
00907 for (int i ; start <= len - pattern.Length(); start++)
00908 if (toupper(buffer[start]) == firstchar)
00909 {
00910 for (i = 1; i < pattern.Length(); i++)
00911 if (toupper(pattern[i]) != toupper(buffer[start + i]))
00912 break;
00913 if (i == pattern.Length()) return start;
00914 }
00915 return -1;
00916 }
00917
00918 int String::SetLength(int newlen)
00919 {
00920 if (newlen > len)
00921 {
00922 Grow(newlen);
00923 memset(buffer + len, ' ', newlen - len);
00924 }
00925 buffer[newlen] = 0;
00926 return len = newlen;
00927 }
00928
00929 String & String::Filter(const String & s)
00930 {
00931 int to = 0;
00932 for (int from = 0; from < len; from++)
00933 if (s.FindChar(buffer[from]) != -1)
00934 buffer[to++] = buffer[from];
00935 buffer[len = to] = 0;
00936 return *this;
00937 }
00938
00939 String & String::Filter(const char * s)
00940 {
00941 String filter(s);
00942 return Filter(filter);
00943 }
00944
00945 String & String::ExcludeCharacters(const String & s)
00946 {
00947 int to = 0;
00948 for (int from = 0; from < len; from++)
00949 if (s.FindChar(buffer[from]) == -1)
00950 buffer[to++] = buffer[from];
00951 buffer[len = to] = 0;
00952 return *this;
00953 }
00954
00955 String & String::ExcludeCharacters(const char * s)
00956 {
00957 String excluded(s);
00958 return ExcludeCharacters(excluded);
00959 }
00960
00961 String operator + (const char * lhs, const String & rhs)
00962 {
00963 String result(lhs);
00964 result += rhs;
00965 return result;
00966 }
00967
00968 String operator + (char lhs, const String & rhs)
00969 {
00970 String result(lhs);
00971 result += rhs;
00972 return result;
00973 }
00974
00975 String operator + (int lhs, const String & rhs)
00976 {
00977 String result;
00978 result = lhs;
00979 result += rhs;
00980 return result;
00981 }
00982
00983 String operator + (unsigned int lhs, const String & rhs)
00984 {
00985 String result;
00986 result = lhs;
00987 result += rhs;
00988 return result;
00989 }
00990
00991 long String::AsInteger() const
00992 {
00993 long returnValue = 0;
00994 if(!AsInteger(returnValue))
00995 {
00996
00997 }
00998 return(returnValue);
00999 }
01000
01001
01002
01003
01004 bool String::AsInteger(long& intValue) const
01005 {
01006 long integer = 0;
01007 int base = 10;
01008 int pos = 0;
01009 int sign = 1;
01010 bool isInt = true;
01011
01012 if (buffer[pos] == '-')
01013 {
01014 sign = -1, pos++;
01015 }
01016
01017 if ((len > pos + 2) && (buffer[pos] == '0') &&
01018 ((buffer[pos+1] == 'x') || (buffer[pos+1] == 'X')))
01019 {
01020 base = 16, pos += 2;
01021 }
01022
01023
01024 if (pos == len)
01025 {
01026 return(false);
01027 }
01028
01029 for (; pos < len; pos++)
01030 {
01031 char digit = (char) toupper(buffer[pos]);
01032
01033 if (digit >= '0' && digit <= '9')
01034 {
01035 integer = integer * base + digit - '0';
01036 }
01037 else if (digit >= 'A' && digit <= 'F' && base == 16)
01038 {
01039 integer = integer * base + digit - 'A' + 10;
01040 }
01041 else
01042 {
01043 isInt = false;
01044 break;
01045 }
01046 }
01047
01048 intValue = sign*integer;
01049
01050 return(isInt);
01051 }
01052
01053
01054
01055
01056 bool String::AsInteger(int& intValue) const
01057 {
01058 int integer = 0;
01059 int base = 10;
01060 int pos = 0;
01061 int sign = 1;
01062 bool isInt = true;
01063
01064 if (buffer[pos] == '-')
01065 {
01066 sign = -1, pos++;
01067 }
01068
01069 if ((len > pos + 2) && (buffer[pos] == '0') &&
01070 ((buffer[pos+1] == 'x') || (buffer[pos+1] == 'X')))
01071 {
01072 base = 16, pos += 2;
01073 }
01074
01075
01076 if (pos == len)
01077 {
01078 return(false);
01079 }
01080
01081 for (; pos < len; pos++)
01082 {
01083 char digit = (char) toupper(buffer[pos]);
01084
01085 if (digit >= '0' && digit <= '9')
01086 {
01087 integer = integer * base + digit - '0';
01088 }
01089 else if (digit >= 'A' && digit <= 'F' && base == 16)
01090 {
01091 integer = integer * base + digit - 'A' + 10;
01092 }
01093 else
01094 {
01095 isInt = false;
01096 break;
01097 }
01098 }
01099
01100 intValue = sign*integer;
01101
01102 return(isInt);
01103 }
01104
01105
01106 String & String::Invert()
01107 {
01108 for (int i = 0, j = len - 1; i < j; i++, j--)
01109 {
01110 char tmp = buffer[i];
01111 buffer[i] = buffer[j];
01112 buffer[j] = tmp;
01113 }
01114 return *this;
01115 }
01116
01117 String String::RightToLeft()
01118 {
01119 String result(*this);
01120 result.Invert();
01121 return result;
01122 }
01123
01124 String & String::Invert(const String & s)
01125 {
01126 Copy(s);
01127 return Invert();
01128 }
01129
01130 int String::CompareToStem(const String & stem) const
01131 {
01132 if (caseSensitive)
01133 return String::FastCompareToStem(stem);
01134 else
01135 return String::SlowCompareToStem(stem);
01136 }
01137
01138 int String::FastCompareToStem(const String & stem) const
01139 {
01140 for (int i = 0; i < stem.len; i++)
01141 if (buffer[i] - stem.buffer[i])
01142 {
01143 #ifdef NATURAL_ORDERING
01144 int d = i;
01145 while (isdigit(buffer[d]) && isdigit(stem.buffer[d]) && d < stem.len)
01146 d++;
01147 if (isdigit(buffer[d]) && d < stem.len)
01148 return 1;
01149 if (isdigit(stem.buffer[d]))
01150 return -1;
01151 #endif
01152 return buffer[i] - stem.buffer[i];
01153 }
01154 return 0;
01155 }
01156
01157 int String::SlowCompareToStem(const String & stem) const
01158 {
01159 for (int i = 0; i < stem.len; i++)
01160 if (toupper(buffer[i]) - toupper(stem.buffer[i]))
01161 {
01162 #ifdef NATURAL_ORDERING
01163 int d = i;
01164 while (isdigit(buffer[d]) && isdigit(stem.buffer[d]) && d < stem.len)
01165 d++;
01166 if (isdigit(buffer[d]) && d < stem.len)
01167 return 1;
01168 if (isdigit(stem.buffer[d]))
01169 return -1;
01170 #endif
01171 return toupper(buffer[i]) - toupper(stem.buffer[i]);
01172 }
01173 return 0;
01174 }
01175
01176 int String::CompareToStem(const char * stem) const
01177 {
01178 if (caseSensitive)
01179 return String::FastCompareToStem(stem);
01180 else
01181 return String::SlowCompareToStem(stem);
01182 }
01183
01184 int String::FastCompareToStem(const char * stem) const
01185 {
01186 for (int i = 0; stem[i] != 0; i++)
01187 if (buffer[i] - stem[i])
01188 return buffer[i] - stem[i];
01189 return 0;
01190 }
01191
01192 int String::SlowCompareToStem(const char * stem) const
01193 {
01194 for (int i = 0; stem[i] != 0; i++)
01195 if (toupper(buffer[i]) - toupper(stem[i]))
01196 return toupper(buffer[i]) - toupper(stem[i]);
01197 return 0;
01198 }
01199
01200 int String::MatchesBeginningOf(const String & stem) const
01201 {
01202 if (caseSensitive)
01203 return String::FastMatchesBeginningOf(stem);
01204 else
01205 return String::SlowMatchesBeginningOf(stem);
01206 }
01207
01208 int String::FastMatchesBeginningOf(const String & stem) const
01209 {
01210 for (int i = 0; i < len; i++)
01211 if (buffer[i] - stem.buffer[i])
01212 return buffer[i] - stem.buffer[i];
01213 return 0;
01214 }
01215
01216 int String::SlowMatchesBeginningOf(const String & stem) const
01217 {
01218 for (int i = 0; i < len; i++)
01219 if (toupper(buffer[i]) - toupper(stem.buffer[i]))
01220 return toupper(buffer[i]) - toupper(stem.buffer[i]);
01221 return 0;
01222 }
01223
01224 int String::MatchesBeginningOf(const char * stem) const
01225 {
01226 if (caseSensitive)
01227 return String::FastMatchesBeginningOf(stem);
01228 else
01229 return String::SlowMatchesBeginningOf(stem);
01230 }
01231
01232 int String::FastMatchesBeginningOf(const char * stem) const
01233 {
01234 for (int i = 0; i < len; i++)
01235 if (buffer[i] - stem[i])
01236 return buffer[i] - stem[i];
01237 return 0;
01238 }
01239
01240 int String::SlowMatchesBeginningOf(const char * stem) const
01241 {
01242 for (int i = 0; i < len; i++)
01243 if (toupper(buffer[i]) - toupper(stem[i]))
01244 return toupper(buffer[i]) - toupper(stem[i]);
01245 return 0;
01246 }
01247
01248 String & String::Trim(char character)
01249 {
01250 int first = 0;
01251 while (buffer[first] && buffer[first] == character)
01252 first++;
01253
01254 int last = len - 1;
01255 while (last >= 0 && buffer[last] == character)
01256 last--;
01257
01258 int out = 0;
01259 while (first <= last)
01260 buffer[out++] = buffer[first++];
01261
01262 buffer[len = out] = 0;
01263
01264 return *this;
01265 }
01266
01267 String & String::Trim()
01268 {
01269 int first = 0;
01270 while (buffer[first] && isspace(buffer[first]))
01271 first++;
01272
01273 int last = len - 1;
01274 while (last >= 0 && isspace(buffer[last]))
01275 last--;
01276
01277 int out = 0;
01278 while (first <= last)
01279 buffer[out++] = buffer[first++];
01280
01281 buffer[len = out] = 0;
01282
01283 return *this;
01284 }
01285
01286 vector<String> *String::Split(char splitChar)
01287 {
01288 vector<String> *result = new vector<String>;
01289 String word;
01290
01291 for (int i = 0; i<Length(); i++)
01292 {
01293 if ((*this)[i]==splitChar)
01294 {
01295 result->push_back(word);
01296 word.Clear();
01297 }
01298 else
01299 word.Add((*this)[i]);
01300 }
01301 if (word.Length()>0) result->push_back(word);
01302 return result;
01303 }
01304
01305
01306 #define VSNPRINTF_NOT_CHECKED 0
01307 #define VSNPRINTF_IS_OK 1
01308 #define VSNPRINTF_NOT_OK 2
01309
01310 int String::vsnprintfChecked = 0;
01311
01312 int String::printf(const char * format, ...)
01313 {
01314 va_list ap;
01315 va_start(ap, format);
01316
01317 vprintf(format, ap);
01318
01319 va_end(ap);
01320 return len;
01321 }
01322
01323 int String::catprintf(const char * format, ...)
01324 {
01325 va_list ap;
01326 va_start(ap, format);
01327
01328 vcatprintf(format, ap);
01329
01330 va_end(ap);
01331 return len;
01332 }
01333
01334 int String::vprintf(const char * format, va_list ap)
01335 {
01336 check_vsnprintf();
01337
01338 while (true)
01339 {
01340 int bytes_needed;
01341 #ifdef va_copy
01342 va_list arguments;
01343 va_copy(arguments, ap);
01344 #else
01345 va_list & arguments = ap;
01346 #endif
01347
01348 if (vsnprintfChecked == VSNPRINTF_IS_OK)
01349 bytes_needed = vsnprintf(buffer, size, format, arguments);
01350 else
01351 bytes_needed = my_vsnprintf(buffer, size, format, arguments);
01352
01353 #ifdef va_copy
01354 va_end(arguments);
01355 #endif
01356
01357 if (bytes_needed >= size)
01358 Grow(bytes_needed);
01359 else if (bytes_needed == -1)
01360 Grow(size * 2);
01361 else
01362 {
01363 return len = bytes_needed;
01364 }
01365 }
01366 }
01367
01368 void String::check_vsnprintf()
01369 {
01370 if (vsnprintfChecked == VSNPRINTF_NOT_CHECKED)
01371 {
01372 char temp[100];
01373
01374 memset(temp, 0, 100);
01375 int check = snprintf(temp, 5, "%5s", "VSNPRINTF");
01376
01377 if (temp[6] != 0 || temp[7] != 0 || (check != 9 && check != -1))
01378
01379
01380
01381
01382
01383
01384 vsnprintfChecked = VSNPRINTF_NOT_OK;
01385 else
01386 vsnprintfChecked = VSNPRINTF_IS_OK;
01387 }
01388 }
01389
01390 int String::vcatprintf(const char * format, va_list ap)
01391 {
01392 check_vsnprintf();
01393
01394 if (len == size)
01395 Grow(size * 2);
01396
01397 while (true)
01398 {
01399 int bytes_needed;
01400 #ifdef va_copy
01401 va_list arguments;
01402 va_copy(arguments, ap);
01403 #else
01404 va_list & arguments = ap;
01405 #endif
01406
01407 if (vsnprintfChecked == VSNPRINTF_IS_OK)
01408 bytes_needed = len + vsnprintf(buffer + len, size - len, format, arguments);
01409 else
01410 bytes_needed = len + my_vsnprintf(buffer + len, size - len, format, arguments);
01411
01412 #ifdef va_copy
01413 va_end(arguments);
01414 #endif
01415
01416 if (bytes_needed >= size)
01417 Grow(bytes_needed);
01418 else if (bytes_needed < len)
01419 Grow(size * 2);
01420 else
01421 {
01422 return len = bytes_needed;
01423 }
01424 }
01425 }
01426
01427 FILE * String::my_vsnprintf_file = NULL;
01428
01429 int String::my_vsnprintf(char * buffer, int bufsize, const char * format, va_list args)
01430 {
01431 if (my_vsnprintf_file == NULL)
01432 {
01433 my_vsnprintf_file = tmpfile();
01434 atexit(my_vsnprintf_close_file);
01435 }
01436
01437 rewind(my_vsnprintf_file);
01438
01439 int len = vfprintf(my_vsnprintf_file, format, args);
01440
01441 rewind(my_vsnprintf_file);
01442
01443 if (len < bufsize)
01444 buffer[bufsize = len] = 0;
01445 int numRead = fread(buffer, 1, bufsize, my_vsnprintf_file);
01446 if(numRead != bufsize)
01447 {
01448 std::cerr
01449 << "Warning, StringBasics failed reading stream in my_vsnprintf\n";
01450 }
01451 return len;
01452 }
01453
01454 int String::my_snprintf(char * buffer, int bufsize, const char * format, ...)
01455 {
01456 va_list ap;
01457 va_start(ap, format);
01458
01459 int bytes = my_vsnprintf(buffer, bufsize, format, ap);
01460
01461 va_end(ap);
01462
01463 return bytes;
01464 }
01465
01466 void String::my_vsnprintf_close_file()
01467 {
01468 fclose(my_vsnprintf_file);
01469 }
01470
01471 bool String::IsNumber()
01472 {
01473 int pos = 0;
01474 bool digits = false;
01475
01476
01477 if (buffer[pos] == '-' || buffer[pos] == '+')
01478 pos++;
01479
01480
01481 while (buffer[pos] >= '0' && buffer[pos] <= '9')
01482 pos++, digits = true;
01483
01484
01485 if (buffer[pos] == '.')
01486 {
01487 pos++;
01488
01489
01490 while (buffer[pos] >= '0' && buffer[pos] <= '9')
01491 pos++, digits = true;
01492 }
01493
01494 if (!digits) return false;
01495
01496
01497 if (buffer[pos] == 'E' || buffer[pos] == 'e')
01498 {
01499 pos++;
01500
01501
01502 if (buffer[pos] == '-' || buffer[pos] == '+')
01503 pos++;
01504
01505 digits = false;
01506
01507
01508 while (buffer[pos] >= '0' && buffer[pos] <= '9')
01509 pos++, digits = true;
01510 }
01511
01512 return (pos == len) && digits;
01513 }
01514
01515 void String::Fill(char ch, int length)
01516 {
01517 if (length >= 0)
01518 SetLength(length);
01519
01520 for (int i = 0; i < len; i++)
01521 buffer[i] = ch;
01522 }
01523
01524 String & String::Reverse()
01525 {
01526 for (int i = 0, j = len - 1; i < j; i++, j--)
01527 {
01528 int tmp = buffer[i];
01529 buffer[i] = buffer[j];
01530 buffer[j] = tmp;
01531 }
01532
01533 return *this;
01534 }
01535
01536
01537
01538 String & String::LeftClip(int clipAmount)
01539 {
01540 if (clipAmount == 0)
01541 return *this;
01542
01543 if (clipAmount > Length())
01544 {
01545 len = 0;
01546 return *this;
01547 }
01548
01549
01550 memmove(buffer, buffer + clipAmount, len - clipAmount);
01551 buffer[len -= clipAmount] = 0;
01552
01553 return *this;
01554 }
01555
01556 String & String::RightClip(int clipAmount)
01557 {
01558 if (clipAmount == 0) return *this;
01559
01560 if (clipAmount > Length())
01561 {
01562 len = 0;
01563 return *this;
01564 }
01565
01566 len -= clipAmount;
01567 buffer[len] = 0;
01568
01569 return *this;
01570 }
01571
01572
01573
01574 #ifdef __GNUC__
01575 String::operator long double() const
01576 {
01577 return strtold(buffer, NULL);
01578 }
01579 #else
01580 #ifdef __BORLANDC__
01581 String::operator long double() const
01582 {
01583 return _strtold(buffer, NULL);
01584 }
01585 #else
01586 String::operator long double() const
01587 {
01588 return atof(buffer);
01589 }
01590 #endif
01591 #endif
01592
01593