diff options
author | 2007-12-17 15:19:59 +0000 | |
---|---|---|
committer | 2007-12-17 15:19:59 +0000 | |
commit | 7b77f1218624ea26dbb2efd85a19f795f5d4e02e (patch) | |
tree | 19209304095572b4fd61c2a2d6a5aa75c4e471ad /src/lib/util/astring.c | |
parent | 3da7f476068b3ffef713218ba2fc1bd5030f2c38 (diff) |
Initial checkin of MAME 0.121.mame0121
Diffstat (limited to 'src/lib/util/astring.c')
-rw-r--r-- | src/lib/util/astring.c | 596 |
1 files changed, 596 insertions, 0 deletions
diff --git a/src/lib/util/astring.c b/src/lib/util/astring.c new file mode 100644 index 00000000000..b2ae0c6c61d --- /dev/null +++ b/src/lib/util/astring.c @@ -0,0 +1,596 @@ +/*************************************************************************** + + astring.c + + Allocated string manipulation functions. + + Copyright (c) 1996-2007, Nicola Salmoria and the MAME Team. + Visit http://mamedev.org for licensing and usage restrictions. + +****************************************************************************/ + +#include "astring.h" +#include "osdcore.h" + +#include <string.h> +#include <stdarg.h> +#include <stdlib.h> +#include <ctype.h> + + + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +struct _astring +{ + char * text; + int alloclen; + char smallbuf[256 - sizeof(int) - sizeof(char *)]; +}; + + + +/*************************************************************************** + GLOBAL VARIABLES +***************************************************************************/ + +static char dummy_text[2] = { 0 }; +static astring dummy_astring = { dummy_text, 1, { 0 } }; + + + +/*************************************************************************** + INLINE FUNCTIONS +***************************************************************************/ + +/*------------------------------------------------- + ensure_room - ensure we have room for a + given string, or else reallocate our buffer +-------------------------------------------------*/ + +INLINE int ensure_room(astring *str, int length) +{ + char *newbuf, *oldbuf; + int alloclen; + + /* always fail to expand the dummy */ + if (str == &dummy_astring) + return FALSE; + + /* if we have the room, do nothing */ + if (str->alloclen >= length + 1) + return TRUE; + + /* allocate a new buffer with some slop */ + alloclen = length + 256; + newbuf = malloc(alloclen); + if (newbuf == NULL) + return FALSE; + + /* swap in the new buffer and free the old one */ + oldbuf = (str->text == str->smallbuf) ? NULL : str->text; + str->text = strcpy(newbuf, str->text); + str->alloclen = alloclen; + if (oldbuf != NULL) + free(oldbuf); + + return TRUE; +} + + +/*------------------------------------------------- + safe_string_base - return a "safe" string + base for a given start index +-------------------------------------------------*/ + +INLINE char *safe_string_base(char *base, int start) +{ + int max = strlen(base); + return (start >= 0 && start < max) ? base + start : base + max; +} + + +/*------------------------------------------------- + normalize_substr - normalize substr parameters +-------------------------------------------------*/ + +INLINE void normalize_substr(int *start, int *count, int length) +{ + /* limit start */ + if (*start < 0) + *start = 0; + else if (*start > length) + *start = length; + + /* update count */ + if (*count == -1 || *start + *count > length) + *count = length - *start; +} + + + +/*************************************************************************** + ASTRING ALLOCATION +***************************************************************************/ + +/*------------------------------------------------- + astring_alloc - allocate a new astring +-------------------------------------------------*/ + +astring *astring_alloc(void) +{ + astring *str; + + /* allocate memory; if we fail, return the dummy */ + str = malloc(sizeof(*str)); + if (str == NULL) + return &dummy_astring; + memset(str, 0, sizeof(*str)); + + /* initialize the small buffer */ + str->text = str->smallbuf; + str->alloclen = ARRAY_LENGTH(str->smallbuf); + return str; +} + + +/*------------------------------------------------- + astring_free - free an astring +-------------------------------------------------*/ + +void astring_free(astring *str) +{ + /* ignore attempts to free the dummy */ + if (str == &dummy_astring) + return; + + /* if we allocated additional memory, free that */ + if (str->text != str->smallbuf) + free(str->text); + free(str); +} + + + +/*************************************************************************** + INLINE ASTRING CHANGES +***************************************************************************/ + +/*------------------------------------------------- + astring_cpy - copy one astring into another +-------------------------------------------------*/ + +astring *astring_cpy(astring *dst, const astring *src) +{ + return astring_cpyc(dst, src->text); +} + + +/*------------------------------------------------- + astring_cpyc - copy a C string into an astring +-------------------------------------------------*/ + +astring *astring_cpyc(astring *dst, const char *src) +{ + return astring_cpych(dst, src, strlen(src)); +} + + +/*------------------------------------------------- + astring_cpych - copy a character array into + an astring +-------------------------------------------------*/ + +astring *astring_cpych(astring *dst, const char *src, int count) +{ + /* make room; if we fail or if dst is the dummy, do nothing */ + if (!ensure_room(dst, count)) + return dst; + + /* copy the raw data and NULL-terminate */ + if (count > 0) + memcpy(dst->text, src, count); + dst->text[count] = 0; + return dst; +} + + +/*------------------------------------------------- + astring_cpysubstr - copy a substring of one + string to another +-------------------------------------------------*/ + +astring *astring_cpysubstr(astring *dst, const astring *src, int start, int count) +{ + normalize_substr(&start, &count, strlen(src->text)); + return astring_cpych(dst, src->text + start, count); +} + + +/*------------------------------------------------- + astring_ins - insert one astring into another +-------------------------------------------------*/ + +astring *astring_ins(astring *dst, int insbefore, const astring *src) +{ + return astring_insc(dst, insbefore, src->text); +} + + +/*------------------------------------------------- + astring_insc - insert a C string into an + astring +-------------------------------------------------*/ + +astring *astring_insc(astring *dst, int insbefore, const char *src) +{ + return astring_insch(dst, insbefore, src, strlen(src)); +} + + +/*------------------------------------------------- + astring_insch - insert a character array + into an astring +-------------------------------------------------*/ + +astring *astring_insch(astring *dst, int insbefore, const char *src, int count) +{ + int dstlength = strlen(dst->text); + + /* make room; if we fail or if dst is the dummy, do nothing */ + if (!ensure_room(dst, dstlength + count)) + return dst; + + /* adjust insbefore to be logical */ + if (insbefore < 0 || insbefore > dstlength) + insbefore = dstlength; + + /* copy the data an NULL-terminate */ + if (insbefore < dstlength) + memmove(dst->text + insbefore + count, dst->text + insbefore, dstlength - insbefore); + memcpy(dst->text + insbefore, src, count); + dst->text[dstlength + count] = 0; + return dst; +} + + +/*------------------------------------------------- + astring_inssubstr - insert a substring of + one string to another +-------------------------------------------------*/ + +astring *astring_inssubstr(astring *dst, int insbefore, const astring *src, int start, int count) +{ + normalize_substr(&start, &count, strlen(src->text)); + return astring_insch(dst, insbefore, src->text + start, count); +} + + +/*------------------------------------------------- + astring_substr - extract a substring of + ourself, removing everything else +-------------------------------------------------*/ + +astring *astring_substr(astring *str, int start, int count) +{ + /* ignore attempts to do this on the dummy */ + if (str == &dummy_astring) + return str; + + /* normalize parameters */ + normalize_substr(&start, &count, strlen(str->text)); + + /* move the data and NULL-terminate */ + if (count > 0 && start > 0) + memmove(str->text, str->text + start, count); + str->text[count] = 0; + return str; +} + + +/*------------------------------------------------- + astring_printf - printf text into an astring +-------------------------------------------------*/ + +int astring_printf(astring *dst, const char *format, ...) +{ + char tempbuf[4096]; + va_list args; + int result; + + /* sprintf into the temporary buffer */ + va_start(args, format); + result = vsprintf(tempbuf, format, args); + va_end(args); + + /* set the result */ + astring_cpyc(dst, tempbuf); + return result; +} + + + +/*************************************************************************** + ASTRING QUERIES +***************************************************************************/ + +/*------------------------------------------------- + astring_c - return a pointer to a C string + from an astring +-------------------------------------------------*/ + +const char *astring_c(const astring *str) +{ + return str->text; +} + + +/*------------------------------------------------- + astring_len - return the length of an astring +-------------------------------------------------*/ + +int astring_len(const astring *str) +{ + return strlen(str->text); +} + + +/*------------------------------------------------- + astring_cmp - compare one astring to another +-------------------------------------------------*/ + +int astring_cmp(const astring *str1, const astring *str2) +{ + return astring_cmpc(str1, str2->text); +} + + +/*------------------------------------------------- + astring_cmpc - compare a C string to an astring +-------------------------------------------------*/ + +int astring_cmpc(const astring *str1, const char *str2) +{ + const char *s1 = str1->text; + + /* loop while equal until we hit the end of strings */ + while (*s1 != 0 && *str2 != 0 && *s1 == *str2) + s1++, str2++; + return *s1 - *str2; +} + + +/*------------------------------------------------- + astring_cmpch - compare a character array to + an astring +-------------------------------------------------*/ + +int astring_cmpch(const astring *str1, const char *str2, int count) +{ + const char *s1 = str1->text; + int result; + + /* loop while equal until we hit the end of strings */ + while (count-- > 0 && *s1 != 0 && *str2 != 0 && *s1 == *str2) + s1++, str2++; + result = (count == -1) ? 0 : *s1 - *str2; + if (result == 0 && *s1 != 0) + result = 1; + return result; +} + + +/*------------------------------------------------- + astring_cmpsubstr - compare a substring to + an astring +-------------------------------------------------*/ + +int astring_cmpsubstr(const astring *str1, const astring *str2, int start, int count) +{ + normalize_substr(&start, &count, strlen(str2->text)); + return astring_cmpch(str1, str2->text + start, count); +} + + +/*------------------------------------------------- + astring_icmp - case-insenstive compare one + astring to another +-------------------------------------------------*/ + +int astring_icmp(const astring *str1, const astring *str2) +{ + return astring_icmpc(str1, str2->text); +} + + +/*------------------------------------------------- + astring_icmpc - case-insenstive compare a C + string to an astring +-------------------------------------------------*/ + +int astring_icmpc(const astring *str1, const char *str2) +{ + const char *s1 = str1->text; + + /* loop while equal until we hit the end of strings */ + while (*s1 != 0 && *str2 != 0 && tolower(*s1) == tolower(*str2)) + s1++, str2++; + return tolower(*s1) - tolower(*str2); +} + + +/*------------------------------------------------- + astring_icmpch - case-insenstive compare a + character array to an astring +-------------------------------------------------*/ + +int astring_icmpch(const astring *str1, const char *str2, int count) +{ + const char *s1 = str1->text; + int result; + + /* loop while equal until we hit the end of strings */ + while (count-- > 0 && *s1 != 0 && *str2 != 0 && tolower(*s1) == tolower(*str2)) + s1++, str2++; + result = (count == -1) ? 0 : tolower(*s1) - tolower(*str2); + if (result == 0 && *s1 != 0) + result = 1; + return result; +} + + +/*------------------------------------------------- + astring_icmpsubstr - case-insenstive compare a + substring to an astring +-------------------------------------------------*/ + +int astring_icmpsubstr(const astring *str1, const astring *str2, int start, int count) +{ + normalize_substr(&start, &count, strlen(str2->text)); + return astring_icmpch(str1, str2->text + start, count); +} + + +/*------------------------------------------------- + astring_chr - return the index of a character + in an astring +-------------------------------------------------*/ + +int astring_chr(const astring *str, int start, int ch) +{ + char *result = strchr(safe_string_base(str->text, start), ch); + return (result != NULL) ? (result - str->text) : -1; +} + + +/*------------------------------------------------- + astring_rchr - return the index of a character + in an astring, searching from the end +-------------------------------------------------*/ + +int astring_rchr(const astring *str, int start, int ch) +{ + char *result = strrchr(safe_string_base(str->text, start), ch); + return (result != NULL) ? (result - str->text) : -1; +} + + +/*------------------------------------------------- + astring_find - find one astring in another +-------------------------------------------------*/ + +int astring_find(const astring *str, int start, const astring *search) +{ + return astring_findc(str, start, search->text); +} + + +/*------------------------------------------------- + astring_findc - find a C string in an astring +-------------------------------------------------*/ + +int astring_findc(const astring *str, int start, const char *search) +{ + char *result = strstr(safe_string_base(str->text, start), search); + return (result != NULL) ? (result - str->text) : -1; +} + + + +/*************************************************************************** + ASTRING UTILITIES +***************************************************************************/ + +/*------------------------------------------------- + astring_delchr - delete all instances of + 'ch' +-------------------------------------------------*/ + +astring *astring_delchr(astring *str, int ch) +{ + char *src, *dst; + + /* simple deletion */ + for (src = dst = str->text; *src != 0; src++) + if (*src != ch) + *dst++ = *src; + *dst = 0; + + return str; +} + + +/*------------------------------------------------- + astring_replacechr - replace all instances of + 'ch' with 'newch' +-------------------------------------------------*/ + +astring *astring_replacechr(astring *str, int ch, int newch) +{ + char *text; + + /* simple replacement */ + for (text = str->text; *text != 0; text++) + if (*text == ch) + *text = newch; + + return str; +} + + +/*------------------------------------------------- + astring_toupper - convert string to all + upper-case +-------------------------------------------------*/ + +astring *astring_toupper(astring *str) +{ + char *text; + + /* just toupper() on all characters */ + for (text = str->text; *text != 0; text++) + *text = toupper(*text); + + return str; +} + + +/*------------------------------------------------- + astring_tolower - convert string to all + lower-case +-------------------------------------------------*/ + +astring *astring_tolower(astring *str) +{ + char *text; + + /* just toupper() on all characters */ + for (text = str->text; *text != 0; text++) + *text = tolower(*text); + + return str; +} + + +/*------------------------------------------------- + astring_trimspace - remove all space + characters from beginning/end +-------------------------------------------------*/ + +astring *astring_trimspace(astring *str) +{ + char *ptr; + + /* first remove stuff from the end */ + for (ptr = str->text + strlen(str->text) - 1; ptr >= str->text && isspace(*ptr); ptr--) + *ptr = 0; + + /* then count how much to remove from the beginning */ + for (ptr = str->text; *ptr != 0 && isspace(*ptr); ptr++) ; + if (ptr > str->text) + astring_substr(str, ptr - str->text, -1); + + return str; +} |