libStatGen Software  1
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 #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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends