libStatGen Software
1
|
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