libStatGen Software  1
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 void StringArray::Read(IFILE & f)
00119 {
00120     while (!ifeof(f))
00121     {
00122         Grow(count + 1);
00123         if (strings[count] == NULL)
00124             strings[count] = new String;
00125         strings[count]->ReadLine(f);
00126         if (ifeof(f) && strings[count]->Length()==0)
00127         {
00128             return;
00129         }
00130         count++;
00131     }
00132 }
00133 
00134 void StringArray::Grow(int newsize)
00135 {
00136     if (newsize >= size)
00137     {
00138         int oldsize = size;
00139 
00140         if ((newsize >> 1) >= size)
00141             size = (newsize + alloc) / alloc * alloc;
00142         else
00143         {
00144             size = alloc;
00145             while (size <= newsize)
00146                 size *= 2;
00147         }
00148         String ** tmp = new String * [size];
00149         for (int i = 0; i < oldsize; i++)
00150             tmp[i] = strings[i];
00151         for (int i = oldsize; i < size; i++)
00152             tmp[i] = NULL;
00153         delete [] strings;
00154         strings = tmp;
00155     }
00156 }
00157 
00158 void StringArray::Clear()
00159 {
00160     if (!lazyMemoryManagement)
00161     {
00162         for (int i = 0; i < size; i++)
00163         {
00164             if (strings[i] != NULL)
00165             {
00166                 delete strings[i];
00167                 strings[i] = NULL;
00168             }
00169             else
00170             {
00171                 break;
00172             }
00173         }
00174     }
00175     count = 0;
00176 }
00177 
00178 int StringArray::AddColumns(const String & s, char ch)
00179 {
00180     if (s.Length() > 0)
00181         for (int pos = 0; pos <= s.Length(); pos++)
00182         {
00183             int oldpos = pos;
00184             pos = s.FindChar(ch, pos);
00185             if (pos == -1) pos = s.Length();
00186             Grow(count + 1);
00187 
00188             if (strings[count] == NULL)
00189             {
00190                 strings[count] = new String(pos - oldpos);
00191             }
00192             strings[count]->SetLength(pos - oldpos);
00193             memcpy((char *) *strings[count++], ((const char *) s) + oldpos, pos - oldpos);
00194         }
00195 
00196     return count;
00197 }
00198 
00199 int StringArray::AddColumns(const String & s, char ch, int maxColumns)
00200 {
00201     maxColumns += count;
00202 
00203     if (s.Length() > 0)
00204         for (int pos = 0; pos <= s.Length() && maxColumns != count; pos++)
00205         {
00206             int oldpos = pos;
00207             pos = s.FindChar(ch, pos);
00208             if (pos == -1) pos = s.Length();
00209             Grow(count + 1);
00210 
00211             if (strings[count] == NULL)
00212                 strings[count] = new String(pos - oldpos);
00213             strings[count]->SetLength(pos - oldpos);
00214             memcpy((char *) *strings[count++], ((const char *) s) + oldpos, pos - oldpos);
00215         };
00216 
00217     return count;
00218 }
00219 
00220 int StringArray::AddTokens(const String & s, char ch)
00221 {
00222     for (int pos = 0; pos < s.Length(); pos++)
00223     {
00224         while (pos < s.Length() && s[pos] == ch) pos++;
00225         int oldpos = pos;
00226 
00227         while (pos < s.Length() && s[pos] != ch) pos++;
00228 
00229         if (oldpos < s.Length())
00230         {
00231             Grow(count + 1);
00232             if (strings[count] == NULL)
00233             {
00234                 strings[count] = new String(pos - oldpos);
00235             }
00236             strings[count]->SetLength(pos - oldpos);
00237             memcpy((char *) *strings[count++], (const char *) s + oldpos, pos - oldpos);
00238         }
00239     }
00240 
00241     return count;
00242 }
00243 
00244 int StringArray::AddTokens(const String & s, const String & separators)
00245 {
00246     for (int pos = 0; pos < s.Length(); pos++)
00247     {
00248         while (pos < s.Length() && separators.FindChar(s[pos]) != -1) pos++;
00249         int oldpos = pos;
00250 
00251         while (pos < s.Length() && separators.FindChar(s[pos]) == -1) pos++;
00252 
00253         if (oldpos < s.Length())
00254         {
00255             Grow(count + 1);
00256             if (strings[count] == NULL)
00257                 strings[count] = new String(pos - oldpos);
00258             strings[count]->SetLength(pos - oldpos);
00259             memcpy((char *) *strings[count++], ((const char *) s) + oldpos, pos - oldpos);
00260         }
00261     }
00262 
00263     return count;
00264 }
00265 
00266 int StringArray::Dimension(int newcount)
00267 {
00268     if (newcount > count)
00269     {
00270         Grow(newcount);
00271         for (int i = count; i < newcount; i++)
00272         {
00273             if (strings[i] == NULL)
00274                 strings[i] = new String;
00275             else
00276                 strings[i]->Clear();
00277         }
00278         count = newcount;
00279     }
00280     else if (newcount < count)
00281     {
00282         if (!lazyMemoryManagement)
00283         {
00284             for (int i = newcount; i < size; i++)
00285             {
00286                 if (strings[i] != NULL)
00287                 {
00288                     delete strings[i];
00289                     strings[i] = NULL;
00290                 }
00291                 else
00292                 {
00293                     break;
00294                 }
00295             }
00296         }
00297         count = newcount;
00298     }
00299 
00300     return count;
00301 }
00302 
00303 int StringArray::Find(const String & s) const
00304 {
00305     for (int i = 0; i < count; i++)
00306         if (*(strings[i]) == s)
00307             return i;
00308     return -1;
00309 }
00310 
00311 int StringArray::FastFind(const String & s) const
00312 {
00313     for (int i = 0; i < count; i++)
00314         if (strings[i]->FastCompare(s) == 0)
00315             return i;
00316     return -1;
00317 }
00318 
00319 int StringArray::SlowFind(const String & s) const
00320 {
00321     for (int i = 0; i < count; i++)
00322         if (strings[i]->SlowCompare(s) == 0)
00323             return i;
00324     return -1;
00325 }
00326 
00327 int StringArray::Add(const String & s)
00328 {
00329     Grow(count + 1);
00330     if (strings[count] == NULL)
00331     {
00332         strings[count] = new String(s);
00333     }
00334     else
00335     {
00336         *strings[count] = s;
00337     }
00338     return ++count;
00339 }
00340 
00341 void StringArray::InsertAt(int position, const String & s)
00342 {
00343     Grow(count + 1);
00344 
00345     String * newString = strings[count];
00346     if (newString == NULL)
00347         newString = new String(s);
00348     else
00349         *newString = s;
00350 
00351     for (int i = count; i > position; i--)
00352         strings[i] = strings[i - 1];
00353     strings[position] = newString;
00354     count++;
00355 }
00356 
00357 String & StringArray::Last() const
00358 {
00359     if (!count) error("StringArray: Null String Access");
00360     return *(strings[count - 1]);
00361 }
00362 
00363 void StringArray::Delete(int index)
00364 {
00365     String * oldString = strings[index];
00366 
00367     count--;
00368     for (; index < count; index++)
00369         strings[index] = strings[index + 1];
00370     strings[count] = oldString;
00371 }
00372 
00373 StringArray & StringArray::operator = (const StringArray & rhs)
00374 {
00375     Dimension(rhs.count);
00376     for (int i = 0; i < rhs.count; i++)
00377         *strings[i] = *rhs.strings[i];
00378     return *this;
00379 }
00380 
00381 bool StringArray::operator == (const StringArray & rhs) const
00382 {
00383     if (count != rhs.count) return false;
00384     for (int i = 0; i < rhs.count; i++)
00385         if (*strings[i] != *rhs.strings[i])
00386             return false;
00387     return true;
00388 }
00389 
00390 void StringArray::Sort()
00391 {
00392     QuickSort(strings, count, sizeof(String *), ComparisonForSort);
00393 }
00394 
00395 int StringArray::ComparisonForSort(const void * a, const void * b)
00396 {
00397     String * string1 = *(String **) a;
00398     String * string2 = *(String **) b;
00399 
00400     return Compare(*string1, *string2);
00401 }
00402 
00403 String StringArray::Pop()
00404 {
00405     String result = *(strings[count - 1]);
00406 
00407     Dimension(count - 1);
00408 
00409     return result;
00410 }
00411 
00412 void StringArray::Trim()
00413 {
00414     for (int i = 0; i < count; i++)
00415         strings[i]->Trim();
00416 }
00417 
00418 void StringArray::Print()
00419 {
00420     Print(stdout);
00421 }
00422 
00423 void StringArray::Print(FILE * output)
00424 {
00425     for (int i = 0; i < count; i++)
00426         fprintf(output, "%s\n", (const char *)(*strings[i]));
00427 }
00428 
00429 void StringArray::PrintLine()
00430 {
00431     PrintLine(stdout);
00432 }
00433 
00434 void StringArray::PrintLine(FILE * output)
00435 {
00436     for (int i = 0; i < count; i++)
00437         fprintf(output, "%s%c", (const char *)(*strings[i]), i == count - 1 ? '\n' : '\t');
00438 }
00439 
00440 void StringArray::Swap(StringArray & s)
00441 {
00442     String ** temp = s.strings;
00443     s.strings = strings;
00444     strings = temp;
00445 
00446     int swap = s.size;
00447     s.size = size;
00448     size = swap;
00449 
00450     swap = s.count;
00451     s.count = count;
00452     count = swap;
00453 }
00454 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends