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