/**************************************************************************** * apps/interpreters/bas/bas_str.c * Dynamic strings. * * Copyright (c) 1999-2014 Michael Haardt * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include #include #include "bas_str.h" /**************************************************************************** * Public Functions ****************************************************************************/ int cistrcmp(const char *s, const char *r) { assert(s != (char *)0); assert(r != (char *)0); while (*s && tolower(*s) == tolower(*r)) { ++s; ++r; } return ((tolower(*s) - tolower(*r))); } struct String *String_new(struct String *self) { assert(self != (struct String *)0); self->length = 0; self->character = (char *)0; self->field = (struct StringField *)0; return self; } void String_destroy(struct String *self) { assert(self != (struct String *)0); if (self->field) { String_leaveField(self); } if (self->length) { free(self->character); } } int String_joinField(struct String *self, struct StringField *field, char *character, size_t length) { struct String **n; assert(self != (struct String *)0); if (self->field) { String_leaveField(self); } self->field = field; if ((n = (struct String **)realloc(field->refStrings, sizeof(struct String *) * (field->refCount + 1))) == (struct String **)0) { return -1; } field->refStrings = n; field->refStrings[field->refCount] = self; ++field->refCount; if (self->length) { free(self->character); } self->character = character; self->length = length; return 0; } void String_leaveField(struct String *self) { struct StringField *field; int i; struct String **ref; assert(self != (struct String *)0); field = self->field; assert(field != (struct StringField *)0); for (i = 0, ref = field->refStrings; i < field->refCount; ++i, ++ref) { if (*ref == self) { int further = --field->refCount - i; if (further) { memmove(ref, ref + 1, further * sizeof(struct String **)); } self->character = (char *)0; self->length = 0; self->field = (struct StringField *)0; return; } } assert(0); } struct String *String_clone(struct String *self, const struct String *original) { assert(self != (struct String *)0); String_new(self); String_appendString(self, original); return self; } int String_size(struct String *self, size_t length) { char *n; assert(self != (struct String *)0); if (self->field) { String_leaveField(self); } if (length) { if (length > self->length) { if ((n = realloc(self->character, length + 1)) == (char *)0) { return -1; } self->character = n; } self->character[length] = '\0'; } else { if (self->length) { free(self->character); } self->character = (char *)0; } self->length = length; return 0; } int String_appendString(struct String *self, const struct String *app) { size_t oldlength = self->length; if (self->field) { String_leaveField(self); } if (app->length == 0) { return 0; } if (String_size(self, self->length + app->length) == -1) { return -1; } memcpy(self->character + oldlength, app->character, app->length); return 0; } int String_appendChar(struct String *self, char ch) { size_t oldlength = self->length; if (self->field) { String_leaveField(self); } if (String_size(self, self->length + 1) == -1) { return -1; } self->character[oldlength] = ch; return 0; } int String_appendChars(struct String *self, const char *ch) { size_t oldlength = self->length; size_t chlen = strlen(ch); if (self->field) { String_leaveField(self); } if (String_size(self, self->length + chlen) == -1) { return -1; } memcpy(self->character + oldlength, ch, chlen); return 0; } int String_appendPrintf(struct String *self, const char *fmt, ...) { char buf[1024]; size_t l, j; va_list ap; if (self->field) { String_leaveField(self); } va_start(ap, fmt); l = vsprintf(buf, fmt, ap); va_end(ap); j = self->length; if (String_size(self, j + l) == -1) { return -1; } memcpy(self->character + j, buf, l); return 0; } int String_insertChar(struct String *self, size_t where, char ch) { size_t oldlength = self->length; if (self->field) { String_leaveField(self); } assert(where < oldlength); if (String_size(self, self->length + 1) == -1) { return -1; } memmove(self->character + where + 1, self->character + where, oldlength - where); self->character[where] = ch; return 0; } int String_delete(struct String *self, size_t where, size_t len) { size_t oldlength = self->length; if (self->field) { String_leaveField(self); } assert(where < oldlength); assert(len > 0); if ((where + len) < oldlength) { memmove(self->character + where, self->character + where + len, oldlength - where - len); } self->character[self->length -= len] = '\0'; return 0; } void String_ucase(struct String *self) { size_t i; for (i = 0; i < self->length; ++i) { self->character[i] = toupper(self->character[i]); } } void String_lcase(struct String *self) { size_t i; for (i = 0; i < self->length; ++i) { self->character[i] = tolower(self->character[i]); } } int String_cmp(const struct String *self, const struct String *s) { size_t pos; int res; const char *thisch, *sch; for (pos = 0, thisch = self->character, sch = s->character; pos < self->length && pos < s->length; ++pos, ++thisch, ++sch) { if ((res = (*thisch - *sch))) { return res; } } return (self->length - s->length); } void String_lset(struct String *self, const struct String *s) { size_t copy; copy = (self->length < s->length ? self->length : s->length); if (copy) { memcpy(self->character, s->character, copy); } if (copy < self->length) { memset(self->character + copy, ' ', self->length - copy); } } void String_rset(struct String *self, const struct String *s) { size_t copy; copy = (self->length < s->length ? self->length : s->length); if (copy) { memcpy(self->character + self->length - copy, s->character, copy); } if (copy < self->length) { memset(self->character, ' ', self->length - copy); } } void String_set(struct String *self, size_t pos, const struct String *s, size_t length) { if (self->length >= pos) { if (self->length < (pos + length)) { length = self->length - pos; } if (length) { memcpy(self->character + pos, s->character, length); } } } struct StringField *StringField_new(struct StringField *self) { self->refStrings = (struct String **)0; self->refCount = 0; return self; } void StringField_destroy(struct StringField *self) { int i; for (i = self->refCount; i > 0;) { String_leaveField(self->refStrings[--i]); } self->refCount = -1; free(self->refStrings); }