libStatGen Software 1
Loading...
Searching...
No Matches
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
25int StringArray::alloc = 32;
26bool StringArray::lazyMemoryManagement = false;
27
28StringArray::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
39StringArray::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
51StringArray::~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
62int 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
70void 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
78void 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
86void 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
94void 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
106void StringArray::Write(FILE * f)
107{
108 for (int i = 0; i < count; i++)
109 strings[i]->WriteLine(f);
110}
111
112void 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
118void 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
134void 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
158void 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
178int 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
199int 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
220int 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
244int 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
266int 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
303int 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
311int 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
319int 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
327int 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
341void 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
357String & StringArray::Last() const
358{
359 if (!count) error("StringArray: Null String Access");
360 return *(strings[count - 1]);
361}
362
363void 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
373StringArray & 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
381bool 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
390void StringArray::Sort()
391{
392 QuickSort(strings, count, sizeof(String *), ComparisonForSort);
393}
394
395int 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
403String StringArray::Pop()
404{
405 String result = *(strings[count - 1]);
406
407 Dimension(count - 1);
408
409 return result;
410}
411
412void StringArray::Trim()
413{
414 for (int i = 0; i < count; i++)
415 strings[i]->Trim();
416}
417
418void StringArray::Print()
419{
420 Print(stdout);
421}
422
423void StringArray::Print(FILE * output)
424{
425 for (int i = 0; i < count; i++)
426 fprintf(output, "%s\n", (const char *)(*strings[i]));
427}
428
429void StringArray::PrintLine()
430{
431 PrintLine(stdout);
432}
433
434void 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
440void 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
int ifeof(IFILE file)
Check to see if we have reached the EOF (returns 0 if not EOF).
Definition InputFile.h:654
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
int ifclose(IFILE &file)
Close the file.
Definition InputFile.h:580
Class for easily reading/writing files without having to worry about file type (uncompressed,...
Definition InputFile.h:37