libStatGen Software  1
StringArray.cpp
1 /*
2  * Copyright (C) 2010 Regents of the University of Michigan
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "StringArray.h"
19 #include "InputFile.h"
20 #include "Sort.h"
21 #include "Error.h"
22 
23 #include <string.h>
24 
25 int StringArray::alloc = 32;
26 bool StringArray::lazyMemoryManagement = false;
27 
28 StringArray::StringArray(int startsize)
29 {
30  count = startsize;
31  size = (startsize + alloc) / alloc * alloc;
32  strings = new String * [size];
33  for (int i = 0; i < count; i++)
34  strings[i] = new String;
35  for (int i = count; i < size; i++)
36  strings[i] = NULL;
37 };
38 
39 StringArray::StringArray(StringArray & rhs)
40 {
41  count = rhs.count;
42  size = (rhs.count + alloc) / alloc * alloc;
43  strings = new String * [size];
44 
45  for (int i = 0; i < count; i++)
46  strings[i] = new String(rhs[i]);;
47  for (int i = count; i < size; i++)
48  strings[i] = NULL;
49 }
50 
51 StringArray::~StringArray()
52 {
53  for (int i = 0; i < size; i++)
54  if (strings[i] != NULL)
55  delete strings[i];
56  else
57  break;
58 
59  delete [] strings;
60 }
61 
62 int StringArray::CharLength()
63 {
64  int charlen = 0;
65  for (int i = 0; i < count; i++)
66  charlen += strings[i]->Length();
67  return charlen;
68 }
69 
70 void StringArray::Read(const char * filename)
71 {
72  IFILE f = ifopen(filename, "rb");
73  if (f == NULL) return;
74  Read(f);
75  ifclose(f);
76 }
77 
78 void StringArray::Write(const char * filename)
79 {
80  FILE * f = fopen(filename, "wt");
81  if (f == NULL) return;
82  Write(f);
83  fclose(f);
84 }
85 
86 void StringArray::WriteLine(const char * filename)
87 {
88  FILE * f = fopen(filename, "wt");
89  if (f == NULL) return;
90  WriteLine(f);
91  fclose(f);
92 }
93 
94 void StringArray::Read(FILE * f)
95 {
96  while (!feof(f))
97  {
98  Grow(count + 1);
99  if (strings[count] == NULL)
100  strings[count] = new String;
101  strings[count]->ReadLine(f);
102  count++;
103  }
104 }
105 
106 void StringArray::Write(FILE * f)
107 {
108  for (int i = 0; i < count; i++)
109  strings[i]->WriteLine(f);
110 }
111 
112 void StringArray::WriteLine(FILE * f)
113 {
114  for (int i = 0; i < count; i++)
115  fprintf(f, "%s%c", (const char *)(*strings[i]), i == count-1 ? '\n' : '\t');
116 }
117 
118 void StringArray::Read(IFILE & f)
119 {
120  while (!ifeof(f))
121  {
122  Grow(count + 1);
123  if (strings[count] == NULL)
124  strings[count] = new String;
125  strings[count]->ReadLine(f);
126  if (ifeof(f) && strings[count]->Length()==0)
127  {
128  return;
129  }
130  count++;
131  }
132 }
133 
134 void StringArray::Grow(int newsize)
135 {
136  if (newsize >= size)
137  {
138  int oldsize = size;
139 
140  if ((newsize >> 1) >= size)
141  size = (newsize + alloc) / alloc * alloc;
142  else
143  {
144  size = alloc;
145  while (size <= newsize)
146  size *= 2;
147  }
148  String ** tmp = new String * [size];
149  for (int i = 0; i < oldsize; i++)
150  tmp[i] = strings[i];
151  for (int i = oldsize; i < size; i++)
152  tmp[i] = NULL;
153  delete [] strings;
154  strings = tmp;
155  }
156 }
157 
158 void StringArray::Clear()
159 {
160  if (!lazyMemoryManagement)
161  {
162  for (int i = 0; i < size; i++)
163  {
164  if (strings[i] != NULL)
165  {
166  delete strings[i];
167  strings[i] = NULL;
168  }
169  else
170  {
171  break;
172  }
173  }
174  }
175  count = 0;
176 }
177 
178 int StringArray::AddColumns(const String & s, char ch)
179 {
180  if (s.Length() > 0)
181  for (int pos = 0; pos <= s.Length(); pos++)
182  {
183  int oldpos = pos;
184  pos = s.FindChar(ch, pos);
185  if (pos == -1) pos = s.Length();
186  Grow(count + 1);
187 
188  if (strings[count] == NULL)
189  {
190  strings[count] = new String(pos - oldpos);
191  }
192  strings[count]->SetLength(pos - oldpos);
193  memcpy((char *) *strings[count++], ((const char *) s) + oldpos, pos - oldpos);
194  }
195 
196  return count;
197 }
198 
199 int StringArray::AddColumns(const String & s, char ch, int maxColumns)
200 {
201  maxColumns += count;
202 
203  if (s.Length() > 0)
204  for (int pos = 0; pos <= s.Length() && maxColumns != count; pos++)
205  {
206  int oldpos = pos;
207  pos = s.FindChar(ch, pos);
208  if (pos == -1) pos = s.Length();
209  Grow(count + 1);
210 
211  if (strings[count] == NULL)
212  strings[count] = new String(pos - oldpos);
213  strings[count]->SetLength(pos - oldpos);
214  memcpy((char *) *strings[count++], ((const char *) s) + oldpos, pos - oldpos);
215  };
216 
217  return count;
218 }
219 
220 int StringArray::AddTokens(const String & s, char ch)
221 {
222  for (int pos = 0; pos < s.Length(); pos++)
223  {
224  while (pos < s.Length() && s[pos] == ch) pos++;
225  int oldpos = pos;
226 
227  while (pos < s.Length() && s[pos] != ch) pos++;
228 
229  if (oldpos < s.Length())
230  {
231  Grow(count + 1);
232  if (strings[count] == NULL)
233  {
234  strings[count] = new String(pos - oldpos);
235  }
236  strings[count]->SetLength(pos - oldpos);
237  memcpy((char *) *strings[count++], (const char *) s + oldpos, pos - oldpos);
238  }
239  }
240 
241  return count;
242 }
243 
244 int StringArray::AddTokens(const String & s, const String & separators)
245 {
246  for (int pos = 0; pos < s.Length(); pos++)
247  {
248  while (pos < s.Length() && separators.FindChar(s[pos]) != -1) pos++;
249  int oldpos = pos;
250 
251  while (pos < s.Length() && separators.FindChar(s[pos]) == -1) pos++;
252 
253  if (oldpos < s.Length())
254  {
255  Grow(count + 1);
256  if (strings[count] == NULL)
257  strings[count] = new String(pos - oldpos);
258  strings[count]->SetLength(pos - oldpos);
259  memcpy((char *) *strings[count++], ((const char *) s) + oldpos, pos - oldpos);
260  }
261  }
262 
263  return count;
264 }
265 
266 int StringArray::Dimension(int newcount)
267 {
268  if (newcount > count)
269  {
270  Grow(newcount);
271  for (int i = count; i < newcount; i++)
272  {
273  if (strings[i] == NULL)
274  strings[i] = new String;
275  else
276  strings[i]->Clear();
277  }
278  count = newcount;
279  }
280  else if (newcount < count)
281  {
282  if (!lazyMemoryManagement)
283  {
284  for (int i = newcount; i < size; i++)
285  {
286  if (strings[i] != NULL)
287  {
288  delete strings[i];
289  strings[i] = NULL;
290  }
291  else
292  {
293  break;
294  }
295  }
296  }
297  count = newcount;
298  }
299 
300  return count;
301 }
302 
303 int StringArray::Find(const String & s) const
304 {
305  for (int i = 0; i < count; i++)
306  if (*(strings[i]) == s)
307  return i;
308  return -1;
309 }
310 
311 int StringArray::FastFind(const String & s) const
312 {
313  for (int i = 0; i < count; i++)
314  if (strings[i]->FastCompare(s) == 0)
315  return i;
316  return -1;
317 }
318 
319 int StringArray::SlowFind(const String & s) const
320 {
321  for (int i = 0; i < count; i++)
322  if (strings[i]->SlowCompare(s) == 0)
323  return i;
324  return -1;
325 }
326 
327 int StringArray::Add(const String & s)
328 {
329  Grow(count + 1);
330  if (strings[count] == NULL)
331  {
332  strings[count] = new String(s);
333  }
334  else
335  {
336  *strings[count] = s;
337  }
338  return ++count;
339 }
340 
341 void StringArray::InsertAt(int position, const String & s)
342 {
343  Grow(count + 1);
344 
345  String * newString = strings[count];
346  if (newString == NULL)
347  newString = new String(s);
348  else
349  *newString = s;
350 
351  for (int i = count; i > position; i--)
352  strings[i] = strings[i - 1];
353  strings[position] = newString;
354  count++;
355 }
356 
357 String & StringArray::Last() const
358 {
359  if (!count) error("StringArray: Null String Access");
360  return *(strings[count - 1]);
361 }
362 
363 void StringArray::Delete(int index)
364 {
365  String * oldString = strings[index];
366 
367  count--;
368  for (; index < count; index++)
369  strings[index] = strings[index + 1];
370  strings[count] = oldString;
371 }
372 
373 StringArray & StringArray::operator = (const StringArray & rhs)
374 {
375  Dimension(rhs.count);
376  for (int i = 0; i < rhs.count; i++)
377  *strings[i] = *rhs.strings[i];
378  return *this;
379 }
380 
381 bool StringArray::operator == (const StringArray & rhs) const
382 {
383  if (count != rhs.count) return false;
384  for (int i = 0; i < rhs.count; i++)
385  if (*strings[i] != *rhs.strings[i])
386  return false;
387  return true;
388 }
389 
390 void StringArray::Sort()
391 {
392  QuickSort(strings, count, sizeof(String *), ComparisonForSort);
393 }
394 
395 int StringArray::ComparisonForSort(const void * a, const void * b)
396 {
397  String * string1 = *(String **) a;
398  String * string2 = *(String **) b;
399 
400  return Compare(*string1, *string2);
401 }
402 
403 String StringArray::Pop()
404 {
405  String result = *(strings[count - 1]);
406 
407  Dimension(count - 1);
408 
409  return result;
410 }
411 
412 void StringArray::Trim()
413 {
414  for (int i = 0; i < count; i++)
415  strings[i]->Trim();
416 }
417 
418 void StringArray::Print()
419 {
420  Print(stdout);
421 }
422 
423 void StringArray::Print(FILE * output)
424 {
425  for (int i = 0; i < count; i++)
426  fprintf(output, "%s\n", (const char *)(*strings[i]));
427 }
428 
429 void StringArray::PrintLine()
430 {
431  PrintLine(stdout);
432 }
433 
434 void StringArray::PrintLine(FILE * output)
435 {
436  for (int i = 0; i < count; i++)
437  fprintf(output, "%s%c", (const char *)(*strings[i]), i == count - 1 ? '\n' : '\t');
438 }
439 
440 void StringArray::Swap(StringArray & s)
441 {
442  String ** temp = s.strings;
443  s.strings = strings;
444  strings = temp;
445 
446  int swap = s.size;
447  s.size = size;
448  size = swap;
449 
450  swap = s.count;
451  s.count = count;
452  count = swap;
453 }
454 
String
Definition: StringBasics.h:39
ifopen
IFILE ifopen(const char *filename, const char *mode, InputFile::ifileCompression compressionMode=InputFile::DEFAULT)
Open a file with the specified name and mode, using a filename of "-" to indicate stdin/stdout.
Definition: InputFile.h:562
ifeof
int ifeof(IFILE file)
Check to see if we have reached the EOF (returns 0 if not EOF).
Definition: InputFile.h:654
InputFile.h
InputFile
Class for easily reading/writing files without having to worry about file type (uncompressed,...
Definition: InputFile.h:37
ifclose
int ifclose(IFILE &file)
Close the file.
Definition: InputFile.h:580
StringArray
Definition: StringArray.h:24