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