StringArray.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 "StringArray.h"
00019 #include "InputFile.h"
00020 #include "Sort.h"
00021 #include "Error.h"
00022 
00023 #include <string.h>
00024 
00025 int   StringArray::alloc = 32;
00026 bool  StringArray::lazyMemoryManagement = false;
00027 
00028 StringArray::StringArray(int startsize)
00029 {
00030     count = startsize;
00031     size = (startsize + alloc) / alloc * alloc;
00032     strings = new String * [size];
00033     for (int i = 0; i < count; i++)
00034         strings[i] = new String;
00035     for (int i = count; i < size; i++)
00036         strings[i] = NULL;
00037 };
00038 
00039 StringArray::StringArray(StringArray & rhs)
00040 {
00041     count = rhs.count;
00042     size = (rhs.count + alloc) / alloc * alloc;
00043     strings = new String * [size];
00044 
00045     for (int i = 0; i < count; i++)
00046         strings[i] = new String(rhs[i]);;
00047     for (int i = count; i < size; i++)
00048         strings[i] = NULL;
00049 }
00050 
00051 StringArray::~StringArray()
00052 {
00053     for (int i = 0; i < size; i++)
00054         if (strings[i] != NULL)
00055             delete strings[i];
00056         else
00057             break;
00058 
00059     delete [] strings;
00060 }
00061 
00062 int StringArray::CharLength()
00063 {
00064     int charlen = 0;
00065     for (int i = 0; i < count; i++)
00066         charlen += strings[i]->Length();
00067     return charlen;
00068 }
00069 
00070 void StringArray::Read(const char * filename)
00071 {
00072     IFILE f = ifopen(filename, "rb");
00073     if (f == NULL) return;
00074     Read(f);
00075     ifclose(f);
00076 }
00077 
00078 void StringArray::Write(const char * filename)
00079 {
00080     FILE * f = fopen(filename, "wt");
00081     if (f == NULL) return;
00082     Write(f);
00083     fclose(f);
00084 }
00085 
00086 void StringArray::WriteLine(const char * filename)
00087 {
00088     FILE * f = fopen(filename, "wt");
00089     if (f == NULL) return;
00090     WriteLine(f);
00091     fclose(f);
00092 }
00093 
00094 void StringArray::Read(FILE * f)
00095 {
00096     while (!feof(f))
00097     {
00098         Grow(count + 1);
00099         if (strings[count] == NULL)
00100             strings[count] = new String;
00101         strings[count]->ReadLine(f);
00102         count++;
00103     }
00104 }
00105 
00106 void StringArray::Write(FILE * f)
00107 {
00108     for (int i = 0; i < count; i++)
00109         strings[i]->WriteLine(f);
00110 }
00111 
00112 void StringArray::WriteLine(FILE * f)
00113 {
00114     for (int i = 0; i < count; i++)
00115         fprintf(f, "%s%c", (const char *)(*strings[i]), i == count-1 ? '\n' : '\t');
00116 }
00117 
00118 #ifdef __ZLIB_AVAILABLE__
00119 void StringArray::Read(IFILE & f)
00120 {
00121     while (!ifeof(f))
00122     {
00123         Grow(count + 1);
00124         if (strings[count] == NULL)
00125             strings[count] = new String;
00126         strings[count]->ReadLine(f);
00127         if (ifeof(f) && strings[count]->Length()==0)
00128         {
00129             return;
00130         }
00131         count++;
00132     }
00133 }
00134 #endif
00135 
00136 void StringArray::Grow(int newsize)
00137 {
00138     if (newsize >= size)
00139     {
00140         int oldsize = size;
00141 
00142         if ((newsize >> 1) >= size)
00143             size = (newsize + alloc) / alloc * alloc;
00144         else
00145         {
00146             size = alloc;
00147             while (size <= newsize)
00148                 size *= 2;
00149         }
00150         String ** tmp = new String * [size];
00151         for (int i = 0; i < oldsize; i++)
00152             tmp[i] = strings[i];
00153         for (int i = oldsize; i < size; i++)
00154             tmp[i] = NULL;
00155         delete [] strings;
00156         strings = tmp;
00157     }
00158 }
00159 
00160 void StringArray::Clear()
00161 {
00162     if (!lazyMemoryManagement)
00163     {
00164         for (int i = 0; i < size; i++)
00165         {
00166             if (strings[i] != NULL)
00167             {
00168                 delete strings[i];
00169                 strings[i] = NULL;
00170             }
00171             else
00172             {
00173                 break;
00174             }
00175         }
00176     }
00177     count = 0;
00178 }
00179 
00180 int StringArray::AddColumns(const String & s, char ch)
00181 {
00182     if (s.Length() > 0)
00183         for (int pos = 0; pos <= s.Length(); pos++)
00184         {
00185             int oldpos = pos;
00186             pos = s.FindChar(ch, pos);
00187             if (pos == -1) pos = s.Length();
00188             Grow(count + 1);
00189 
00190             if (strings[count] == NULL)
00191             {
00192                 strings[count] = new String(pos - oldpos);
00193             }
00194             strings[count]->SetLength(pos - oldpos);
00195             memcpy((char *) *strings[count++], ((const char *) s) + oldpos, pos - oldpos);
00196         }
00197 
00198     return count;
00199 }
00200 
00201 int StringArray::AddColumns(const String & s, char ch, int maxColumns)
00202 {
00203     maxColumns += count;
00204 
00205     if (s.Length() > 0)
00206         for (int pos = 0; pos <= s.Length() && maxColumns != count; pos++)
00207         {
00208             int oldpos = pos;
00209             pos = s.FindChar(ch, pos);
00210             if (pos == -1) pos = s.Length();
00211             Grow(count + 1);
00212 
00213             if (strings[count] == NULL)
00214                 strings[count] = new String(pos - oldpos);
00215             strings[count]->SetLength(pos - oldpos);
00216             memcpy((char *) *strings[count++], ((const char *) s) + oldpos, pos - oldpos);
00217         };
00218 
00219     return count;
00220 }
00221 
00222 int StringArray::AddTokens(const String & s, char ch)
00223 {
00224     for (int pos = 0; pos < s.Length(); pos++)
00225     {
00226         while (pos < s.Length() && s[pos] == ch) pos++;
00227         int oldpos = pos;
00228 
00229         while (pos < s.Length() && s[pos] != ch) pos++;
00230 
00231         if (oldpos < s.Length())
00232         {
00233             Grow(count + 1);
00234             if (strings[count] == NULL)
00235             {
00236                 strings[count] = new String(pos - oldpos);
00237             }
00238             strings[count]->SetLength(pos - oldpos);
00239             memcpy((char *) *strings[count++], (const char *) s + oldpos, pos - oldpos);
00240         }
00241     }
00242 
00243     return count;
00244 }
00245 
00246 int StringArray::AddTokens(const String & s, const String & separators)
00247 {
00248     for (int pos = 0; pos < s.Length(); pos++)
00249     {
00250         while (pos < s.Length() && separators.FindChar(s[pos]) != -1) pos++;
00251         int oldpos = pos;
00252 
00253         while (pos < s.Length() && separators.FindChar(s[pos]) == -1) pos++;
00254 
00255         if (oldpos < s.Length())
00256         {
00257             Grow(count + 1);
00258             if (strings[count] == NULL)
00259                 strings[count] = new String(pos - oldpos);
00260             strings[count]->SetLength(pos - oldpos);
00261             memcpy((char *) *strings[count++], ((const char *) s) + oldpos, pos - oldpos);
00262         }
00263     }
00264 
00265     return count;
00266 }
00267 
00268 int StringArray::Dimension(int newcount)
00269 {
00270     if (newcount > count)
00271     {
00272         Grow(newcount);
00273         for (int i = count; i < newcount; i++)
00274         {
00275             if (strings[i] == NULL)
00276                 strings[i] = new String;
00277             else
00278                 strings[i]->Clear();
00279         }
00280         count = newcount;
00281     }
00282     else if (newcount < count)
00283     {
00284         if (!lazyMemoryManagement)
00285         {
00286             for (int i = newcount; i < size; i++)
00287             {
00288                 if (strings[i] != NULL)
00289                 {
00290                     delete strings[i];
00291                     strings[i] = NULL;
00292                 }
00293                 else
00294                 {
00295                     break;
00296                 }
00297             }
00298         }
00299         count = newcount;
00300     }
00301 
00302     return count;
00303 }
00304 
00305 int StringArray::Find(const String & s) const
00306 {
00307     for (int i = 0; i < count; i++)
00308         if (*(strings[i]) == s)
00309             return i;
00310     return -1;
00311 }
00312 
00313 int StringArray::FastFind(const String & s) const
00314 {
00315     for (int i = 0; i < count; i++)
00316         if (strings[i]->FastCompare(s) == 0)
00317             return i;
00318     return -1;
00319 }
00320 
00321 int StringArray::SlowFind(const String & s) const
00322 {
00323     for (int i = 0; i < count; i++)
00324         if (strings[i]->SlowCompare(s) == 0)
00325             return i;
00326     return -1;
00327 }
00328 
00329 int StringArray::Add(const String & s)
00330 {
00331     Grow(count + 1);
00332     if (strings[count] == NULL)
00333     {
00334         strings[count] = new String(s);
00335     }
00336     else
00337     {
00338         *strings[count] = s;
00339     }
00340     return ++count;
00341 }
00342 
00343 void StringArray::InsertAt(int position, const String & s)
00344 {
00345     Grow(count + 1);
00346 
00347     String * newString = strings[count];
00348     if (newString == NULL)
00349         newString = new String(s);
00350     else
00351         *newString = s;
00352 
00353     for (int i = count; i > position; i--)
00354         strings[i] = strings[i - 1];
00355     strings[position] = newString;
00356     count++;
00357 }
00358 
00359 String & StringArray::Last() const
00360 {
00361     if (!count) error("StringArray: Null String Access");
00362     return *(strings[count - 1]);
00363 }
00364 
00365 void StringArray::Delete(int index)
00366 {
00367     String * oldString = strings[index];
00368 
00369     count--;
00370     for (; index < count; index++)
00371         strings[index] = strings[index + 1];
00372     strings[count] = oldString;
00373 }
00374 
00375 StringArray & StringArray::operator = (const StringArray & rhs)
00376 {
00377     Dimension(rhs.count);
00378     for (int i = 0; i < rhs.count; i++)
00379         *strings[i] = *rhs.strings[i];
00380     return *this;
00381 }
00382 
00383 bool StringArray::operator == (const StringArray & rhs)
00384 {
00385     if (count != rhs.count) return false;
00386     for (int i = 0; i < rhs.count; i++)
00387         if (*strings[i] != *rhs.strings[i])
00388             return false;
00389     return true;
00390 }
00391 
00392 void StringArray::Sort()
00393 {
00394     QuickSort(strings, count, sizeof(String *), ComparisonForSort);
00395 }
00396 
00397 int StringArray::ComparisonForSort(const void * a, const void * b)
00398 {
00399     String * string1 = *(String **) a;
00400     String * string2 = *(String **) b;
00401 
00402     return Compare(*string1, *string2);
00403 }
00404 
00405 String StringArray::Pop()
00406 {
00407     String result = *(strings[count - 1]);
00408 
00409     Dimension(count - 1);
00410 
00411     return result;
00412 }
00413 
00414 void StringArray::Trim()
00415 {
00416     for (int i = 0; i < count; i++)
00417         strings[i]->Trim();
00418 }
00419 
00420 void StringArray::Print()
00421 {
00422     Print(stdout);
00423 }
00424 
00425 void StringArray::Print(FILE * output)
00426 {
00427     for (int i = 0; i < count; i++)
00428         fprintf(output, "%s\n", (const char *)(*strings[i]));
00429 }
00430 
00431 void StringArray::PrintLine()
00432 {
00433     PrintLine(stdout);
00434 }
00435 
00436 void StringArray::PrintLine(FILE * output)
00437 {
00438     for (int i = 0; i < count; i++)
00439         fprintf(output, "%s%c", (const char *)(*strings[i]), i == count - 1 ? '\n' : '\t');
00440 }
00441 
00442 void StringArray::Swap(StringArray & s)
00443 {
00444     String ** temp = s.strings;
00445     s.strings = strings;
00446     strings = temp;
00447 
00448     int swap = s.size;
00449     s.size = size;
00450     size = swap;
00451 
00452     swap = s.count;
00453     s.count = count;
00454     count = swap;
00455 }
00456 
Generated on Tue Sep 6 17:52:01 2011 for libStatGen Software by  doxygen 1.6.3