blob: a9656d9b9aeb1ac8ff8dc1752773b98ca70f02eb [file] [log] [blame]
/* Copyright (C) 2021 Free Software Foundation, Inc.
Contributed by Oracle.
This file is part of GNU Binutils.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <values.h>
#include <stdarg.h>
#include "gp-defs.h"
#include "StringBuilder.h"
#include "i18n.h"
StringBuilder::StringBuilder ()
{
count = 0;
maxCapacity = 16;
value = (char *) malloc (maxCapacity);
memset (value, 0, maxCapacity);
}
StringBuilder::StringBuilder (int capacity)
{
count = 0;
maxCapacity = capacity;
value = (char *) malloc (maxCapacity);
memset (value, 0, maxCapacity);
}
StringBuilder::~StringBuilder ()
{
free (value);
}
void
StringBuilder::ensureCapacity (int minimumCapacity)
{
if (minimumCapacity > maxCapacity)
expandCapacity (minimumCapacity);
}
void
StringBuilder::expandCapacity (int minimumCapacity)
{
int newCapacity = (maxCapacity + 1) * 2;
if (newCapacity < 0)
newCapacity = MAXINT;
else if (minimumCapacity > newCapacity)
newCapacity = minimumCapacity;
char *newValue = (char *) malloc (newCapacity);
maxCapacity = newCapacity;
memcpy (newValue, value, count);
memset (newValue + count, 0, maxCapacity - count);
free (value);
value = newValue;
}
void
StringBuilder::trimToSize ()
{
if (count < maxCapacity)
{
char *newValue = (char *) malloc (count);
maxCapacity = count;
memcpy (newValue, value, count);
free (value);
value = newValue;
}
}
void
StringBuilder::trim ()
{
while (count > 0)
{
if (value[count - 1] != ' ')
break;
count--;
}
}
void
StringBuilder::setLength (int newLength)
{
if (newLength < 0)
return;
if (newLength > maxCapacity)
expandCapacity (newLength);
if (count < newLength)
{
for (; count < newLength; count++)
value[count] = '\0';
}
else
count = newLength;
}
char
StringBuilder::charAt (int index)
{
if (index < 0 || index >= count)
return 0;
return value[index];
}
void
StringBuilder::getChars (int srcBegin, int srcEnd, char dst[], int dstBegin)
{
if (srcBegin < 0)
return;
if (srcEnd < 0 || srcEnd > count)
return;
if (srcBegin > srcEnd)
return;
memcpy (dst + dstBegin, value + srcBegin, srcEnd - srcBegin);
}
void
StringBuilder::setCharAt (int index, char ch)
{
if (index < 0 || index >= count)
return;
value[index] = ch;
}
StringBuilder *
StringBuilder::append (StringBuilder *sb)
{
if (sb == NULL)
return append (NTXT ("null"));
int len = sb->count;
int newcount = count + len;
if (newcount > maxCapacity)
expandCapacity (newcount);
sb->getChars (0, len, value, count);
count = newcount;
return this;
}
StringBuilder *
StringBuilder::append (const char str[])
{
int len = (int) strlen (str);
int newCount = count + len;
if (newCount > maxCapacity)
expandCapacity (newCount);
memcpy (value + count, str, len);
count = newCount;
return this;
}
StringBuilder *
StringBuilder::append (const char str[], int offset, int len)
{
int newCount = count + len;
if (newCount > maxCapacity)
expandCapacity (newCount);
memcpy (value + count, str + offset, len);
count = newCount;
return this;
}
StringBuilder *
StringBuilder::append (bool b)
{
if (b)
append (NTXT ("true"));
else
append (NTXT ("false"));
return this;
}
StringBuilder *
StringBuilder::append (char c)
{
int newCount = count + 1;
if (newCount > maxCapacity)
{
expandCapacity (newCount);
}
value[count++] = c;
return this;
}
StringBuilder *
StringBuilder::append (int i)
{
char buf[16];
snprintf (buf, sizeof (buf), NTXT ("%d"), i);
append (buf);
return this;
}
StringBuilder *
StringBuilder::append (unsigned int i)
{
char buf[16];
snprintf (buf, sizeof (buf), NTXT ("%u"), i);
append (buf);
return this;
}
StringBuilder *
StringBuilder::append (long lng)
{
char buf[32];
snprintf (buf, sizeof (buf), NTXT ("%ld"), lng);
append (buf);
return this;
}
StringBuilder *
StringBuilder::append (unsigned long lng)
{
char buf[32];
snprintf (buf, sizeof (buf), NTXT ("%lu"), lng);
append (buf);
return this;
}
StringBuilder *
StringBuilder::append (long long lng)
{
char buf[32];
snprintf (buf, sizeof (buf), NTXT ("%lld"), lng);
append (buf);
return this;
}
StringBuilder *
StringBuilder::append (unsigned long long lng)
{
char buf[32];
snprintf (buf, sizeof (buf), NTXT ("%llu"), lng);
append (buf);
return this;
}
StringBuilder *
StringBuilder::append (float f)
{
char buf[32];
snprintf (buf, sizeof (buf), NTXT ("%f"), (double) f);
append (buf);
return this;
}
StringBuilder *
StringBuilder::append (double d)
{
char buf[32];
snprintf (buf, sizeof (buf), NTXT ("%f"), d);
append (buf);
return this;
}
StringBuilder *
StringBuilder::_delete (int start, int end)
{
if (start < 0)
return this;
if (end > count)
end = count;
if (start > end)
return this;
int len = end - start;
if (len > 0)
{
memcpy (value + start, value + start + len, count - end);
count -= len;
}
return this;
}
StringBuilder *
StringBuilder::deleteCharAt (int index)
{
if (index < 0 || index >= count)
return this;
memcpy (value + index, value + index + 1, count - index - 1);
count--;
return this;
}
bool
StringBuilder::endsWith (const char str[])
{
if (str == NULL)
{
if (count == 0)
return true;
return false;
}
int len = (int) strlen (str);
if (len == 0)
return true;
int start = count - len;
if (start < 0)
return false;
int res = strncmp ((const char *) (value + start), str, len);
if (res != 0)
return false;
return true;
}
StringBuilder *
StringBuilder::insert (int index, const char str[], int offset, int len)
{
if (index < 0 || index > count)
return this;
if (offset < 0 || len < 0 || offset > ((int) strlen (str)) - len)
return this;
int newCount = count + len;
if (newCount > maxCapacity)
expandCapacity (newCount);
memcpy (value + index + len, value + index, count - index);
memcpy (value + index, str + offset, len);
count = newCount;
return this;
}
StringBuilder *
StringBuilder::insert (int offset, const char str[])
{
if (offset < 0 || offset > count)
return this;
int len = (int) strlen (str);
int newCount = count + len;
if (newCount > maxCapacity)
expandCapacity (newCount);
memcpy (value + offset + len, value + offset, count - offset);
memcpy (value + offset, str, len);
count = newCount;
return this;
}
StringBuilder *
StringBuilder::insert (int offset, bool b)
{
return insert (offset, b ? NTXT ("true") : NTXT ("false"));
}
StringBuilder *
StringBuilder::insert (int offset, char c)
{
int newCount = count + 1;
if (newCount > maxCapacity)
expandCapacity (newCount);
memcpy (value + offset + 1, value + offset, count - offset);
value[offset] = c;
count = newCount;
return this;
}
StringBuilder *
StringBuilder::insert (int offset, int i)
{
char buf[16];
snprintf (buf, sizeof (buf), NTXT ("%d"), i);
insert (offset, buf);
return this;
}
StringBuilder *
StringBuilder::insert (int offset, long l)
{
char buf[32];
snprintf (buf, sizeof (buf), NTXT ("%ld"), l);
insert (offset, buf);
return this;
}
StringBuilder *
StringBuilder::insert (int offset, float f)
{
char buf[32];
snprintf (buf, sizeof (buf), NTXT ("%f"), (double) f);
insert (offset, buf);
return this;
}
StringBuilder *
StringBuilder::insert (int offset, double d)
{
char buf[32];
snprintf (buf, sizeof (buf), NTXT ("%f"), d);
insert (offset, buf);
return this;
}
StringBuilder *
StringBuilder::reverse ()
{
int n = count - 1;
for (int j = (n - 1) >> 1; j >= 0; --j)
{
char temp = value[j];
char temp2 = value[n - j];
value[j] = temp2;
value[n - j] = temp;
}
return this;
}
//String *StringBuilder::toString();
char *
StringBuilder::toString ()
{
char *str = (char *) malloc (count + 1);
memcpy (str, value, count);
str[count] = '\0';
return str;
}
void
StringBuilder::toFile (FILE *fp)
{
append ('\0');
count--;
fprintf (fp, NTXT ("%s"), value);
}
void
StringBuilder::toFileLn (FILE *fp)
{
trim ();
append ('\0');
count--;
fprintf (fp, NTXT ("%s\n"), value);
}
StringBuilder *
StringBuilder::sprintf (const char *fmt, ...)
{
int cnt;
setLength (0);
va_list vp;
va_start (vp, fmt);
cnt = vsnprintf (value, maxCapacity, fmt, vp);
va_end (vp);
if (cnt < maxCapacity)
{
count = cnt;
return this;
}
// Have to count the trailing zero
ensureCapacity (cnt + 1);
va_start (vp, fmt);
count = vsnprintf (value, maxCapacity, fmt, vp);
va_end (vp);
return this;
}
StringBuilder *
StringBuilder::appendf (const char *fmt, ...)
{
va_list vp;
va_start (vp, fmt);
int cnt = vsnprintf (value + count, maxCapacity - count, fmt, vp);
va_end (vp);
if (cnt + count < maxCapacity)
{
count += cnt;
return this;
}
// Have to count the trailing zero
ensureCapacity (count + cnt + 1);
va_start (vp, fmt);
count += vsnprintf (value + count, maxCapacity - count, fmt, vp);
va_end (vp);
return this;
}
int
StringBuilder::indexOf (const char str[])
{
return indexOf (str, 0);
}
int
StringBuilder::indexOf (const char str[], int fromIndex)
{
int len = (int) strlen (str);
if (fromIndex >= count)
return len == 0 ? count : -1;
if (fromIndex < 0)
fromIndex = 0;
if (len == 0)
return fromIndex;
char first = str[0];
int max = (count - len);
for (int i = fromIndex; i <= max; i++)
{
/* Look for first character. */
if (value[i] != first)
while (++i <= max && value[i] != first)
;
/* Found first character, now look at the rest of v2 */
if (i <= max)
{
int j = i + 1;
int end = j + len - 1;
for (int k = 1; j < end && value[j] == str[k]; j++, k++)
;
if (j == end) /* Found whole string. */
return i;
}
}
return -1;
}
int
StringBuilder::lastIndexOf (const char str[])
{
return lastIndexOf (str, count);
}
int
StringBuilder::lastIndexOf (const char str[], int fromIndex)
{
/*
* Check arguments; return immediately where possible. For
* consistency, don't check for null str.
*/
int len = (int) strlen (str);
int rightIndex = count - len;
if (fromIndex < 0)
return -1;
if (fromIndex > rightIndex)
fromIndex = rightIndex;
/* Empty string always matches. */
if (len == 0)
return fromIndex;
int strLastIndex = len - 1;
char strLastChar = str[strLastIndex];
int min = len - 1;
int i = min + fromIndex;
while (true)
{
while (i >= min && value[i] != strLastChar)
i--;
if (i < min)
return -1;
int j = i - 1;
int start = j - (len - 1);
int k = strLastIndex - 1;
while (j > start)
{
if (value[j--] != str[k--])
{
i--;
break;
}
}
if (j == start)
return start + 1;
}
}