StringBasics.cpp

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