1 /* Copyright (C) 2021 Free Software Foundation, Inc.
2 Contributed by Oracle.
3
4 This file is part of GNU Binutils.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
20
21 #include "config.h"
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <values.h>
26 #include <stdarg.h>
27
28 #include "gp-defs.h"
29 #include "StringBuilder.h"
30 #include "i18n.h"
31
StringBuilder()32 StringBuilder::StringBuilder ()
33 {
34 count = 0;
35 maxCapacity = 16;
36 value = (char *) malloc (maxCapacity);
37 memset (value, 0, maxCapacity);
38 }
39
StringBuilder(int capacity)40 StringBuilder::StringBuilder (int capacity)
41 {
42 count = 0;
43 maxCapacity = capacity;
44 value = (char *) malloc (maxCapacity);
45 memset (value, 0, maxCapacity);
46 }
47
~StringBuilder()48 StringBuilder::~StringBuilder ()
49 {
50 free (value);
51 }
52
53 void
ensureCapacity(int minimumCapacity)54 StringBuilder::ensureCapacity (int minimumCapacity)
55 {
56 if (minimumCapacity > maxCapacity)
57 expandCapacity (minimumCapacity);
58 }
59
60 void
expandCapacity(int minimumCapacity)61 StringBuilder::expandCapacity (int minimumCapacity)
62 {
63 int newCapacity = (maxCapacity + 1) * 2;
64 if (newCapacity < 0)
65 newCapacity = MAXINT;
66 else if (minimumCapacity > newCapacity)
67 newCapacity = minimumCapacity;
68 char *newValue = (char *) malloc (newCapacity);
69 maxCapacity = newCapacity;
70 memcpy (newValue, value, count);
71 memset (newValue + count, 0, maxCapacity - count);
72 free (value);
73 value = newValue;
74 }
75
76 void
trimToSize()77 StringBuilder::trimToSize ()
78 {
79 if (count < maxCapacity)
80 {
81 char *newValue = (char *) malloc (count);
82 maxCapacity = count;
83 memcpy (newValue, value, count);
84 free (value);
85 value = newValue;
86 }
87 }
88
89 void
trim()90 StringBuilder::trim ()
91 {
92 while (count > 0)
93 {
94 if (value[count - 1] != ' ')
95 break;
96 count--;
97 }
98 }
99
100 void
setLength(int newLength)101 StringBuilder::setLength (int newLength)
102 {
103 if (newLength < 0)
104 return;
105 if (newLength > maxCapacity)
106 expandCapacity (newLength);
107 if (count < newLength)
108 {
109 for (; count < newLength; count++)
110 value[count] = '\0';
111 }
112 else
113 count = newLength;
114 }
115
116 char
charAt(int index)117 StringBuilder::charAt (int index)
118 {
119 if (index < 0 || index >= count)
120 return 0;
121 return value[index];
122 }
123
124 void
getChars(int srcBegin,int srcEnd,char dst[],int dstBegin)125 StringBuilder::getChars (int srcBegin, int srcEnd, char dst[], int dstBegin)
126 {
127 if (srcBegin < 0)
128 return;
129 if (srcEnd < 0 || srcEnd > count)
130 return;
131 if (srcBegin > srcEnd)
132 return;
133 memcpy (dst + dstBegin, value + srcBegin, srcEnd - srcBegin);
134 }
135
136 void
setCharAt(int index,char ch)137 StringBuilder::setCharAt (int index, char ch)
138 {
139 if (index < 0 || index >= count)
140 return;
141 value[index] = ch;
142 }
143
144 StringBuilder *
append(StringBuilder * sb)145 StringBuilder::append (StringBuilder *sb)
146 {
147 if (sb == NULL)
148 return append (NTXT ("null"));
149 int len = sb->count;
150 int newcount = count + len;
151 if (newcount > maxCapacity)
152 expandCapacity (newcount);
153 sb->getChars (0, len, value, count);
154 count = newcount;
155 return this;
156 }
157
158 StringBuilder *
append(const char str[])159 StringBuilder::append (const char str[])
160 {
161 int len = (int) strlen (str);
162 int newCount = count + len;
163 if (newCount > maxCapacity)
164 expandCapacity (newCount);
165 memcpy (value + count, str, len);
166 count = newCount;
167 return this;
168 }
169
170 StringBuilder *
append(const char str[],int offset,int len)171 StringBuilder::append (const char str[], int offset, int len)
172 {
173 int newCount = count + len;
174 if (newCount > maxCapacity)
175 expandCapacity (newCount);
176 memcpy (value + count, str + offset, len);
177 count = newCount;
178 return this;
179 }
180
181 StringBuilder *
append(bool b)182 StringBuilder::append (bool b)
183 {
184 if (b)
185 append (NTXT ("true"));
186 else
187 append (NTXT ("false"));
188 return this;
189 }
190
191 StringBuilder *
append(char c)192 StringBuilder::append (char c)
193 {
194 int newCount = count + 1;
195 if (newCount > maxCapacity)
196 {
197 expandCapacity (newCount);
198 }
199 value[count++] = c;
200 return this;
201 }
202
203 StringBuilder *
append(int i)204 StringBuilder::append (int i)
205 {
206 char buf[16];
207 snprintf (buf, sizeof (buf), NTXT ("%d"), i);
208 append (buf);
209 return this;
210 }
211
212 StringBuilder *
append(unsigned int i)213 StringBuilder::append (unsigned int i)
214 {
215 char buf[16];
216 snprintf (buf, sizeof (buf), NTXT ("%u"), i);
217 append (buf);
218 return this;
219 }
220
221 StringBuilder *
append(long lng)222 StringBuilder::append (long lng)
223 {
224 char buf[32];
225 snprintf (buf, sizeof (buf), NTXT ("%ld"), lng);
226 append (buf);
227 return this;
228 }
229
230 StringBuilder *
append(unsigned long lng)231 StringBuilder::append (unsigned long lng)
232 {
233 char buf[32];
234 snprintf (buf, sizeof (buf), NTXT ("%lu"), lng);
235 append (buf);
236 return this;
237 }
238
239 StringBuilder *
append(long long lng)240 StringBuilder::append (long long lng)
241 {
242 char buf[32];
243 snprintf (buf, sizeof (buf), NTXT ("%lld"), lng);
244 append (buf);
245 return this;
246 }
247
248 StringBuilder *
append(unsigned long long lng)249 StringBuilder::append (unsigned long long lng)
250 {
251 char buf[32];
252 snprintf (buf, sizeof (buf), NTXT ("%llu"), lng);
253 append (buf);
254 return this;
255 }
256
257 StringBuilder *
append(float f)258 StringBuilder::append (float f)
259 {
260 char buf[32];
261 snprintf (buf, sizeof (buf), NTXT ("%f"), (double) f);
262 append (buf);
263 return this;
264 }
265
266 StringBuilder *
append(double d)267 StringBuilder::append (double d)
268 {
269 char buf[32];
270 snprintf (buf, sizeof (buf), NTXT ("%f"), d);
271 append (buf);
272 return this;
273 }
274
275 StringBuilder *
_delete(int start,int end)276 StringBuilder::_delete (int start, int end)
277 {
278 if (start < 0)
279 return this;
280 if (end > count)
281 end = count;
282 if (start > end)
283 return this;
284 int len = end - start;
285 if (len > 0)
286 {
287 memcpy (value + start, value + start + len, count - end);
288 count -= len;
289 }
290 return this;
291 }
292
293 StringBuilder *
deleteCharAt(int index)294 StringBuilder::deleteCharAt (int index)
295 {
296 if (index < 0 || index >= count)
297 return this;
298 memcpy (value + index, value + index + 1, count - index - 1);
299 count--;
300 return this;
301 }
302
303 bool
endsWith(const char str[])304 StringBuilder::endsWith (const char str[])
305 {
306 if (str == NULL)
307 {
308 if (count == 0)
309 return true;
310 return false;
311 }
312 int len = (int) strlen (str);
313 if (len == 0)
314 return true;
315 int start = count - len;
316 if (start < 0)
317 return false;
318 int res = strncmp ((const char *) (value + start), str, len);
319 if (res != 0)
320 return false;
321 return true;
322 }
323
324 StringBuilder *
insert(int index,const char str[],int offset,int len)325 StringBuilder::insert (int index, const char str[], int offset, int len)
326 {
327 if (index < 0 || index > count)
328 return this;
329 if (offset < 0 || len < 0 || offset > ((int) strlen (str)) - len)
330 return this;
331 int newCount = count + len;
332 if (newCount > maxCapacity)
333 expandCapacity (newCount);
334 memcpy (value + index + len, value + index, count - index);
335 memcpy (value + index, str + offset, len);
336 count = newCount;
337 return this;
338 }
339
340 StringBuilder *
insert(int offset,const char str[])341 StringBuilder::insert (int offset, const char str[])
342 {
343 if (offset < 0 || offset > count)
344 return this;
345 int len = (int) strlen (str);
346 int newCount = count + len;
347 if (newCount > maxCapacity)
348 expandCapacity (newCount);
349 memcpy (value + offset + len, value + offset, count - offset);
350 memcpy (value + offset, str, len);
351 count = newCount;
352 return this;
353 }
354
355 StringBuilder *
insert(int offset,bool b)356 StringBuilder::insert (int offset, bool b)
357 {
358 return insert (offset, b ? NTXT ("true") : NTXT ("false"));
359 }
360
361 StringBuilder *
insert(int offset,char c)362 StringBuilder::insert (int offset, char c)
363 {
364 int newCount = count + 1;
365 if (newCount > maxCapacity)
366 expandCapacity (newCount);
367 memcpy (value + offset + 1, value + offset, count - offset);
368 value[offset] = c;
369 count = newCount;
370 return this;
371 }
372
373 StringBuilder *
insert(int offset,int i)374 StringBuilder::insert (int offset, int i)
375 {
376 char buf[16];
377 snprintf (buf, sizeof (buf), NTXT ("%d"), i);
378 insert (offset, buf);
379 return this;
380 }
381
382 StringBuilder *
insert(int offset,long l)383 StringBuilder::insert (int offset, long l)
384 {
385 char buf[32];
386 snprintf (buf, sizeof (buf), NTXT ("%ld"), l);
387 insert (offset, buf);
388 return this;
389 }
390
391 StringBuilder *
insert(int offset,float f)392 StringBuilder::insert (int offset, float f)
393 {
394 char buf[32];
395 snprintf (buf, sizeof (buf), NTXT ("%f"), (double) f);
396 insert (offset, buf);
397 return this;
398 }
399
400 StringBuilder *
insert(int offset,double d)401 StringBuilder::insert (int offset, double d)
402 {
403 char buf[32];
404 snprintf (buf, sizeof (buf), NTXT ("%f"), d);
405 insert (offset, buf);
406 return this;
407 }
408
409 StringBuilder *
reverse()410 StringBuilder::reverse ()
411 {
412 int n = count - 1;
413 for (int j = (n - 1) >> 1; j >= 0; --j)
414 {
415 char temp = value[j];
416 char temp2 = value[n - j];
417 value[j] = temp2;
418 value[n - j] = temp;
419 }
420 return this;
421 }
422
423 //String *StringBuilder::toString();
424 char *
toString()425 StringBuilder::toString ()
426 {
427 char *str = (char *) malloc (count + 1);
428 memcpy (str, value, count);
429 str[count] = '\0';
430 return str;
431 }
432
433 void
toFile(FILE * fp)434 StringBuilder::toFile (FILE *fp)
435 {
436 append ('\0');
437 count--;
438 fprintf (fp, NTXT ("%s"), value);
439 }
440
441 void
toFileLn(FILE * fp)442 StringBuilder::toFileLn (FILE *fp)
443 {
444 trim ();
445 append ('\0');
446 count--;
447 fprintf (fp, NTXT ("%s\n"), value);
448 }
449
450 StringBuilder *
sprintf(const char * fmt,...)451 StringBuilder::sprintf (const char *fmt, ...)
452 {
453 int cnt;
454 setLength (0);
455
456 va_list vp;
457 va_start (vp, fmt);
458 cnt = vsnprintf (value, maxCapacity, fmt, vp);
459 va_end (vp);
460 if (cnt < maxCapacity)
461 {
462 count = cnt;
463 return this;
464 }
465
466 // Have to count the trailing zero
467 ensureCapacity (cnt + 1);
468 va_start (vp, fmt);
469 count = vsnprintf (value, maxCapacity, fmt, vp);
470 va_end (vp);
471 return this;
472 }
473
474 StringBuilder *
appendf(const char * fmt,...)475 StringBuilder::appendf (const char *fmt, ...)
476 {
477 va_list vp;
478 va_start (vp, fmt);
479 int cnt = vsnprintf (value + count, maxCapacity - count, fmt, vp);
480 va_end (vp);
481 if (cnt + count < maxCapacity)
482 {
483 count += cnt;
484 return this;
485 }
486
487 // Have to count the trailing zero
488 ensureCapacity (count + cnt + 1);
489 va_start (vp, fmt);
490 count += vsnprintf (value + count, maxCapacity - count, fmt, vp);
491 va_end (vp);
492 return this;
493 }
494
495 int
indexOf(const char str[])496 StringBuilder::indexOf (const char str[])
497 {
498 return indexOf (str, 0);
499 }
500
501 int
indexOf(const char str[],int fromIndex)502 StringBuilder::indexOf (const char str[], int fromIndex)
503 {
504 int len = (int) strlen (str);
505 if (fromIndex >= count)
506 return len == 0 ? count : -1;
507 if (fromIndex < 0)
508 fromIndex = 0;
509 if (len == 0)
510 return fromIndex;
511
512 char first = str[0];
513 int max = (count - len);
514
515 for (int i = fromIndex; i <= max; i++)
516 {
517 /* Look for first character. */
518 if (value[i] != first)
519 while (++i <= max && value[i] != first)
520 ;
521 /* Found first character, now look at the rest of v2 */
522 if (i <= max)
523 {
524 int j = i + 1;
525 int end = j + len - 1;
526 for (int k = 1; j < end && value[j] == str[k]; j++, k++)
527 ;
528 if (j == end) /* Found whole string. */
529 return i;
530 }
531 }
532 return -1;
533 }
534
535 int
lastIndexOf(const char str[])536 StringBuilder::lastIndexOf (const char str[])
537 {
538 return lastIndexOf (str, count);
539 }
540
541 int
lastIndexOf(const char str[],int fromIndex)542 StringBuilder::lastIndexOf (const char str[], int fromIndex)
543 {
544 /*
545 * Check arguments; return immediately where possible. For
546 * consistency, don't check for null str.
547 */
548 int len = (int) strlen (str);
549 int rightIndex = count - len;
550 if (fromIndex < 0)
551 return -1;
552 if (fromIndex > rightIndex)
553 fromIndex = rightIndex;
554 /* Empty string always matches. */
555 if (len == 0)
556 return fromIndex;
557
558 int strLastIndex = len - 1;
559 char strLastChar = str[strLastIndex];
560 int min = len - 1;
561 int i = min + fromIndex;
562
563 while (true)
564 {
565 while (i >= min && value[i] != strLastChar)
566 i--;
567 if (i < min)
568 return -1;
569
570 int j = i - 1;
571 int start = j - (len - 1);
572 int k = strLastIndex - 1;
573 while (j > start)
574 {
575 if (value[j--] != str[k--])
576 {
577 i--;
578 break;
579 }
580 }
581 if (j == start)
582 return start + 1;
583 }
584 }
585
586