StringArray.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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