/* * Jakelib2 - General purpose C++ library * Copyright (C) 2001 Florian Wolff (florian@donuz.de) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id: ZString.cpp,v 1.6 2003/07/03 17:55:16 florian Exp $ */ #include "../include/jlpplib.h" #include #ifndef BORLAND #include #include #endif int ZString::initialCapacity = 64; int ZString::increment = 64; /*****************************************************************************\ | ZString | \*****************************************************************************/ ZString::ZString(const ZString& str) { init(str.len); memcpy(buffer, str.buffer, str.len + 1); len = str.len; } ZString::ZString(ZString* str) { init(str->len); memcpy(buffer, str->getChars(), str->len + 1); len = str->len; } ZString::ZString() { init(initialCapacity); } ZString::ZString(boolean isNullString) { init(1); this->isNullString = isNullString; } ZString::ZString(const char* str) { init((int) strlen(str)); len = (int) strlen(str); memcpy(buffer, str, len + 1); } ZString::ZString(int, const char* fstring, ...) { init((int) strlen(fstring)); va_list pz; va_start(pz, fstring); while (*fstring) { if (*fstring != '%') { append(*fstring); fstring ++; } else { fstring ++; switch(*fstring) { case '%': append(fstring[0]); break; case 's': { char* s = va_arg(pz, char*); append(s); } break; case 'S': { ZString *s = va_arg(pz, ZString*); append(s); } break; case 'c': { int ch = va_arg(pz, int); append((char) ch); } break; case 'u': { char s[20]; int i = va_arg(pz, int); sprintf(s, "%u", i); append(s); } break; case 'i': case 'd': { char s[20]; int i = va_arg(pz, int); sprintf(s, "%i", i); append(s); } break; } if (*fstring != '\0') fstring ++; } } } /*****************************************************************************\ | init | \*****************************************************************************/ void ZString::init(int initialCapacity) { classname = "ZString"; isNullString = FALSE; capacity = 0; len = 0; buffer = NULL; if (initialCapacity >= ZString::initialCapacity) ensureCapacity(initialCapacity); else ensureCapacity(ZString::initialCapacity); buffer[0] = '\0'; } /*****************************************************************************\ | ensureCapacity | \*****************************************************************************/ void ZString::ensureCapacity(int minimumCapacity) { if (capacity >= minimumCapacity) { return; } else { int newCapacity = capacity + increment; if (minimumCapacity > newCapacity) newCapacity = minimumCapacity; char* newText = (char*) realloc(buffer, sizeof(char) * (newCapacity +1)); if (newText == NULL) throw ZMemoryException(ZString(0, "Allocating %u bytes of memory.", sizeof(char) * newCapacity).getChars()); else { capacity = newCapacity; buffer = newText; } } } /*****************************************************************************\ | ~ZString | \*****************************************************************************/ ZString::~ZString() { free(buffer); } /*****************************************************************************\ | hashCode | \*****************************************************************************/ int ZString::hashCode() { int h = 0; int off = 0; int len = length(); for (int i = 0; i < len; i++) { h = 31*h + charAt(off++); } return h; } /*****************************************************************************\ | equals | \*****************************************************************************/ boolean ZString::equals(ZObject* obj) { if (obj == NULL) return FALSE; if (strcmp(getClassname(), obj->getClassname())) return FALSE; ZString* object = (ZString*) obj; return ( strcmp(getChars(), object->getChars()) == 0 ); } boolean ZString::equals(const char* str) { if (str == NULL) return FALSE; else return (strcmp(getChars(), str) == 0); } /*****************************************************************************\ | equalsIgnoreCase | \*****************************************************************************/ boolean ZString::equalsIgnoreCase(const char* str) { #ifdef WIN32 if (str == NULL) return FALSE; else return (stricmp(getChars(), str) == 0); #else throw ZUnsupportedOperationException("ZString.equalsIgnoreCase"); #endif } /*****************************************************************************\ | toCppString | \*****************************************************************************/ ZString ZString::toCppString() { ZString str; for (int idx = 0; idx < length(); idx++) { switch(charAt(idx)) { case '\n': str.append("\\n"); break; case '\\': str.append("\\\\"); break; case '\r': str.append("\\r"); break; case '\t': str.append("\\t"); break; case '\"': str.append("\\\""); break; default: str.append(charAt(idx)); break; } } return ZString(str); } /*****************************************************************************\ | parseCppString | \*****************************************************************************/ ZString ZString::parseCppString() { ZString str; char c; for (int idx = 0; idx < length(); idx++) { c = charAt(idx); if (c == '\\') { if (idx +1 < length()) switch(charAt(idx +1)) { case 'n': str.append('\n'); break; case 'r': str.append('\r'); break; case '\\': str.append('\\'); break; case 'b': str.append('\b'); break; case 't': str.append('\t'); break; case '\"': str.append('\"'); break; case ' ': str.append(' '); break; } idx ++; } else { str.append(c); } } return ZString(str); } /*****************************************************************************\ | length | \*****************************************************************************/ int ZString::length() { return len; } /*****************************************************************************\ | toString | \*****************************************************************************/ ZString ZString::toString() { return ZString(*this); } /*****************************************************************************\ | trim | \*****************************************************************************/ ZString& ZString::trim() { ltrim(); rtrim(); return *this; } /*****************************************************************************\ | ltrim | \*****************************************************************************/ ZString& ZString::ltrim() { while (length() && (charAt(0) == ' ')) { remove(0, 1); } return *this; } /*****************************************************************************\ | rtrim | \*****************************************************************************/ ZString& ZString::rtrim() { while (length() && (charAt(length() -1) == ' ')) { remove(length() -1); } return *this; } /*****************************************************************************\ | toUpperCase | \*****************************************************************************/ ZString& ZString::toUpperCase() { unsigned char c, n; for (int i = 0; i < length(); i++) { c = charAt(i); switch (c) { case 'ä': n = (unsigned char) 'Ä'; break; case 'ö': n = (unsigned char) 'Ö'; break; case 'ü': n = (unsigned char) 'Ü'; break; default: n = (unsigned char) toupper(c); break; } setChar(i, n); } return *this; } /*****************************************************************************\ | toLowerCase | \*****************************************************************************/ ZString& ZString::toLowerCase() { unsigned char c, n; for (int i = 0; i < length(); i++) { c = charAt(i); switch (c) { case 'Ä': n = (unsigned char) 'ä'; break; case 'Ö': n = (unsigned char) 'ö'; break; case 'Ü': n = (unsigned char) 'ü'; break; default: n = (unsigned char) tolower(c); break; } setChar(i, n); } return *this; } /*****************************************************************************\ | getUpperCase | \*****************************************************************************/ ZString ZString::getUpperCase() { unsigned char c, n; ZString newStr(this); for (int i = 0; i < length(); i++) { c = charAt(i); switch (c) { case 'ä': n = (unsigned char) 'Ä'; break; case 'ö': n = (unsigned char) 'Ö'; break; case 'ü': n = (unsigned char) 'Ü'; break; default: n = (unsigned char) toupper(c); break; } newStr.setChar(i, n); } return newStr; } /*****************************************************************************\ | getLowerCase | \*****************************************************************************/ ZString ZString::getLowerCase() { unsigned char c, n; ZString newStr(this); for (int i = 0; i < length(); i++) { c = charAt(i); switch (c) { case 'Ä': n = (unsigned char) 'ä'; break; case 'Ö': n = (unsigned char) 'ö'; break; case 'Ü': n = (unsigned char) 'ü'; break; default: n = (unsigned char) tolower(c); break; } newStr.setChar(i, n); } return newStr; } /*****************************************************************************\ | toInt | \*****************************************************************************/ int ZString::toInt() { return atoi(buffer); } /*****************************************************************************\ | toLong | \*****************************************************************************/ long ZString::toLong() { return atol(buffer); } /*****************************************************************************\ | indexOf | \*****************************************************************************/ int ZString::indexOf(ZString* str) { return indexOf(str->getChars()); } int ZString::indexOf(const char* str) { const char* ptr = strstr(getChars(), str); if (ptr == NULL) return -1; else return (int)(ptr - getChars()); } int ZString::indexOf(char c) { char str[2]; str[0] = c; str[1] = '\0'; const char* ptr = strstr(getChars(), str); if (ptr == NULL) return -1; else return (int)(ptr - getChars()); } int ZString::indexOf(ZString* str, int fromIndex) { return indexOf(str->getChars(), fromIndex); } int ZString::indexOf(const char* str, int fromIndex) { if (fromIndex >= len) return -1; if (fromIndex < 0) fromIndex = 0; const char* ptr = strstr(getChars(fromIndex), str); if (ptr == NULL) return -1; else return (int)(ptr - getChars()); } /*****************************************************************************\ | lastIndexOf | \*****************************************************************************/ int ZString::lastIndexOf(ZString* str) { return lastIndexOf(str->getChars()); } int ZString::lastIndexOf(const char* str) { int len = (int)strlen(str); if (length() < len) return -1; int to = length() - (int)strlen(str); for (int idx = to; idx >= 0; idx--) if (strncmp(getChars(idx), str, len) == 0) return idx; return -1; } /*****************************************************************************\ | startsWith | \*****************************************************************************/ boolean ZString::startsWith(ZString* str) { return startsWith(str->getChars()); } boolean ZString::startsWith(const char* str) { if (len < (int) strlen(str)) return FALSE; if (strncmp(getChars(), str, strlen(str)) == 0) return TRUE; else return FALSE; } /*****************************************************************************\ | startsWithIgnoreCase | \*****************************************************************************/ boolean ZString::startsWithIgnoreCase(const char* str) { #ifdef WIN32 if (len < (int) strlen(str)) return FALSE; if (strnicmp(getChars(), str, strlen(str)) == 0) return TRUE; else return FALSE; #else throw ZUnsupportedOperationException("ZString.equalsIgnoreCase"); #endif } /*****************************************************************************\ | endsWith | \*****************************************************************************/ boolean ZString::endsWith(ZString* str) { return endsWith(str->getChars()); } boolean ZString::endsWith(const char* str) { if (len < (int) strlen(str)) return FALSE; const char* ptr = getChars(); if (strcmp(&ptr[length() - strlen(str)], str) == 0) return TRUE; else return FALSE; } /*****************************************************************************\ | endsWithIgnoreCase | \*****************************************************************************/ boolean ZString::endsWithIgnoreCase(const char* str) { #ifdef WIN32 if (len < (int) strlen(str)) return FALSE; const char* ptr = getChars(); if (stricmp(&ptr[length() - strlen(str)], str) == 0) return TRUE; else return FALSE; #else throw ZUnsupportedOperationException("ZString.equalsIgnoreCase"); #endif } /*****************************************************************************\ | getChars | \*****************************************************************************/ const char* ZString::getChars() { return buffer; } const char* ZString::getChars(int index) { if (index < 0) throw ZIllegalArgumentException(ZString(0, "ZString.getChars(%i): %i < 0", index, index).getChars()); if (index > len) throw ZIllegalArgumentException(ZString(0, "ZString.getChars(%i): %i > %i", index, index, len).getChars()); const char* chars = buffer; return &chars[index]; } /*****************************************************************************\ | substring | \*****************************************************************************/ ZString ZString::substring(int beginIndex, int endIndex) { if (endIndex < 0) { ZString err = ZString(0, "ZString.substring(%i, %i): endIndex < 0", beginIndex, endIndex); throw ZIllegalArgumentException(err); } if (beginIndex < 0) { ZString err = ZString(0, "ZString.substring(%i, %i): beginIndex < 0", beginIndex, endIndex); throw ZIllegalArgumentException(err); } if (endIndex < beginIndex) { ZString err = ZString(0, "ZString.substring(%i, %i): endIndex < beginIndex", beginIndex, endIndex); throw ZIllegalArgumentException(err.getChars()); } if (beginIndex >= length()) { return ZString(); } ZString substr = ZString(getChars(beginIndex)); substr.remove(endIndex - beginIndex); return substr; } /*****************************************************************************\ | substring | \*****************************************************************************/ ZString ZString::substring(int beginIndex) { if (beginIndex < 0) { ZString err = ZString(0, "ZString.substring(%i): beginIndex < 0", beginIndex); throw ZIllegalArgumentException(err); } if (beginIndex >= length()) { return ZString(); } return ZString(getChars(beginIndex)); } /*****************************************************************************\ | charAt | \*****************************************************************************/ char ZString::charAt(int index) { if (index < 0) throw ZIndexOutOfBoundsException(ZString(0, "ZString.charAt(%i): %i < 0", index, index).getChars()); if (index >= len) return 0; return buffer[index]; } /*****************************************************************************\ | setChar | \*****************************************************************************/ ZString& ZString::setChar(int index, char c) { if (index < 0) throw ZIndexOutOfBoundsException(ZString(0, "ZString.setChar(%i, '%c'): %i < 0", index, c, index).getChars()); if (index > len) throw ZIndexOutOfBoundsException(ZString(0, "ZString.setChar(%i, '%c'): %i > %i", index, c, index, len).getChars()); if (index == len) { append(c); } else { buffer[index] = c; } return *this; } /*****************************************************************************\ | replace | \*****************************************************************************/ ZString& ZString::replace(char oldChar, char newChar) { for (int i = 0; i < len; i++) { if (charAt(i) == oldChar) { setChar(i, newChar); } } return *this; } /*****************************************************************************\ | remove | \*****************************************************************************/ ZString& ZString::remove(int beginIndex, int endIndex) { if (beginIndex < 0) throw ZIndexOutOfBoundsException(ZString(0, "ZString.remove(%i, %i): %i < 0", beginIndex, endIndex, beginIndex).getChars()); if (beginIndex > endIndex) throw ZIndexOutOfBoundsException(ZString(0, "ZString.remove(%i, %i): %i > %i", beginIndex, endIndex, beginIndex, endIndex).getChars()); if (beginIndex >= len) { return *this; } else { if (endIndex >= len) { buffer[beginIndex] = '\0'; } else { memmove(&buffer[beginIndex], &buffer[endIndex], len - endIndex +1); } len = (int)strlen(buffer); } return *this; } ZString& ZString::remove(int beginIndex) { if (beginIndex < len) remove(beginIndex, len); return *this; } /*****************************************************************************\ | append | \*****************************************************************************/ ZString& ZString::append(const ZString* str) { if (str != NULL) { ensureCapacity(len + str->len); memcpy(&buffer[len], str->buffer, str->len + 1); len += str->len; } return *this; } ZString& ZString::append(const char* str) { if (str != NULL) { ensureCapacity(len + (int)strlen(str)); strcpy(&buffer[len], str); len += (int)strlen(str); } return *this; } ZString& ZString::append(char c) { ensureCapacity(len +1); buffer[len] = c; len ++; buffer[len] = '\0'; return *this; } /*****************************************************************************\ | isNull | \*****************************************************************************/ boolean ZString::isNull() { return isNullString; } /*****************************************************************************\ | insert | \*****************************************************************************/ ZString& ZString::insert(int index, char c) { if (index < 0) throw ZIndexOutOfBoundsException(ZString(0, "ZString.insert(%i, '%c'): %i < 0", index, c, index).getChars()); if (index > len) throw ZIndexOutOfBoundsException(ZString(0, "ZString.insert(%i, '%c'): %i > %i", index, c, index, len).getChars()); ZString tmp = substring(index); remove(index); append(c); append(&tmp); return *this; } ZString& ZString::insert(int index, const char* str) { if (index < 0) throw ZIndexOutOfBoundsException(ZString(0, "ZString.insert(%i, \"%s\"): %i < 0", index, str, index).getChars()); if (index > len) throw ZIndexOutOfBoundsException(ZString(0, "ZString.insert(%i, \"%s\"): %i > %i", index, str, index, len).getChars()); ZString tmp = substring(index); remove(index); append(str); append(&tmp); return *this; } /*****************************************************************************\ | clear | \*****************************************************************************/ ZString& ZString::clear() { if (len > 0) { len = 0; buffer[0] = '\0'; } return *this; } /*****************************************************************************\ | operator = | \*****************************************************************************/ ZString& ZString::operator = (const ZString& str) { clear(); append(&str); isNullString = str.isNullString; return *this; } ZString& ZString::operator = (const char* str) { clear(); append(str); return *this; } /*****************************************************************************\ | operator += | \*****************************************************************************/ ZString& ZString::operator += (const char* str) { append(str); return *this; } ZString& ZString::operator += (const ZString& str) { append(&str); return *this; } ZString& ZString::printf(const char* fstring, ...) { clear(); va_list pz; va_start(pz, fstring); while (*fstring) { if (*fstring != '%') { append(*fstring); fstring ++; } else { fstring ++; switch(*fstring) { case '%': append(fstring[0]); break; case 's': { char* s = va_arg(pz, char*); append(s); } break; case 'S': { ZString *s = va_arg(pz, ZString*); append(s); } break; case 'c': { int ch = va_arg(pz, int); append((char) ch); } break; case 'u': { char s[20]; int i = va_arg(pz, int); sprintf(s, "%u", i); append(s); } break; case 'i': case 'd': { char s[20]; int i = va_arg(pz, int); sprintf(s, "%i", i); append(s); } break; } if (*fstring != '\0') fstring ++; } } return *this; } #ifndef HAVE_ITOA char itoa_chars[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n'}; char *itoa (int value, char *string, int radix) { int pos = 12; boolean negative = FALSE; string[--pos] = '\0'; if (value < 0) { value *= -1; negative = TRUE; } while (value > 0) { string[--pos] = itoa_chars[value % radix]; value /= radix; } if (negative) string[--pos] = '-'; return &string[pos]; } #endif