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 32 StringBuilder::StringBuilder () 33 { 34 count = 0; 35 maxCapacity = 16; 36 value = (char *) malloc (maxCapacity); 37 memset (value, 0, maxCapacity); 38 } 39 40 StringBuilder::StringBuilder (int capacity) 41 { 42 count = 0; 43 maxCapacity = capacity; 44 value = (char *) malloc (maxCapacity); 45 memset (value, 0, maxCapacity); 46 } 47 48 StringBuilder::~StringBuilder () 49 { 50 free (value); 51 } 52 53 void 54 StringBuilder::ensureCapacity (int minimumCapacity) 55 { 56 if (minimumCapacity > maxCapacity) 57 expandCapacity (minimumCapacity); 58 } 59 60 void 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 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 90 StringBuilder::trim () 91 { 92 while (count > 0) 93 { 94 if (value[count - 1] != ' ') 95 break; 96 count--; 97 } 98 } 99 100 void 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 117 StringBuilder::charAt (int index) 118 { 119 if (index < 0 || index >= count) 120 return 0; 121 return value[index]; 122 } 123 124 void 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 137 StringBuilder::setCharAt (int index, char ch) 138 { 139 if (index < 0 || index >= count) 140 return; 141 value[index] = ch; 142 } 143 144 StringBuilder * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 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 * 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 * 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 * 356 StringBuilder::insert (int offset, bool b) 357 { 358 return insert (offset, b ? NTXT ("true") : NTXT ("false")); 359 } 360 361 StringBuilder * 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 * 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 * 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 * 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 * 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 * 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 * 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 434 StringBuilder::toFile (FILE *fp) 435 { 436 append ('\0'); 437 count--; 438 fprintf (fp, NTXT ("%s"), value); 439 } 440 441 void 442 StringBuilder::toFileLn (FILE *fp) 443 { 444 trim (); 445 append ('\0'); 446 count--; 447 fprintf (fp, NTXT ("%s\n"), value); 448 } 449 450 StringBuilder * 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 * 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 496 StringBuilder::indexOf (const char str[]) 497 { 498 return indexOf (str, 0); 499 } 500 501 int 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 536 StringBuilder::lastIndexOf (const char str[]) 537 { 538 return lastIndexOf (str, count); 539 } 540 541 int 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