/* Generated automatically by jlpp - do not edit. */ #include static jakelib::lang::String* jakelib2_strings[] = {null, null, null, null, null, null, null, null, null, null, null, null, null, null}; // "Allocating " static jchar chars_jakelib2_str_0[] = {65,108,108,111,99,97,116,105,110,103,32}; // " bytes of memory." static jchar chars_jakelib2_str_1[] = {32,98,121,116,101,115,32,111,102,32,109,101,109,111,114,121,46}; // "string null pointer" static jchar chars_jakelib2_str_2[] = {115,116,114,105,110,103,32,110,117,108,108,32,112,111,105,110,116,101,114}; // "" static jchar chars_jakelib2_str_3[] = {0}; // ", " static jchar chars_jakelib2_str_4[] = {44,32}; // "): endIndex < 0" static jchar chars_jakelib2_str_5[] = {41,58,32,101,110,100,73,110,100,101,120,32,60,32,48}; // "" static jchar chars_jakelib2_str_6[] = {0}; // ", " static jchar chars_jakelib2_str_7[] = {44,32}; // "): beginIndex < 0" static jchar chars_jakelib2_str_8[] = {41,58,32,98,101,103,105,110,73,110,100,101,120,32,60,32,48}; // "" static jchar chars_jakelib2_str_9[] = {0}; // " < 0" static jchar chars_jakelib2_str_10[] = {32,60,32,48}; // "" static jchar chars_jakelib2_str_11[] = {0}; // " < 0" static jchar chars_jakelib2_str_12[] = {32,60,32,48}; // "idx = " static jchar chars_jakelib2_str_13[] = {105,100,120,32,61,32}; #line 1 "lang/String.jlc" // -*- c++ -*- /* * 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: String.jlc,v 1.24 2006-02-18 16:12:16 florian Exp $ */ #include "jakelib2.h" #include "jakelib2/lang/System.h" #include "jakelib2/lang/Integer.h" #include "jakelib2/lang/Long.h" #include "jakelib2/lang/Byte.h" #include "jakelib2/lang/Double.h" #include "jakelib2/lang/Float.h" #include "jakelib2/lang/Short.h" #include "jakelib2/lang/Character.h" #include "jakelib2/util/ByteArray.h" #include "jakelib2/io/ByteArrayInputStream.h" #include "jakelib2/util/StringComparator.h" #include "jakelib2/text/enc/CharToByteConverter.h" #include "jakelib2/text/enc/ByteToCharConverter.h" #include using namespace jakelib::lang; using namespace jakelib::util; using namespace jakelib::io; using namespace jakelib::text::enc; JAKELIB_IMPLEMENT_CLASS_1("jakelib.lang.String", String, Object, Comparable); JAKELIB_IMPLEMENT_ARRAY(String); #ifndef BORLAND # include # include #endif int String::initialCapacity = 64; int String::increment = 64; String* String::emptyString = null; String* String::nullString = null; /*****************************************************************************\ * String | *****************************************************************************/ String::String(String* str) { init(str->len); this->len = str->len; memcpy(buffer, str->buffer, len * sizeof(jchar)); } String::String() { init(initialCapacity); } String::String(const jbyte* str) { init(strlen(str)); this->len = strlen(str); for (int x = 0; x < len; x++) { buffer[x] = ((jchar) str[x]) & 0xff; } } String::String(jbyte* str, char* enc) { String encStr(enc); ByteToCharConverter* conv = ByteToCharConverter::getConverter(&encStr); int maxLen = strlen(str); init(maxLen); ByteArrayInputStream byteStream(str, maxLen); len = conv->convert(&byteStream, buffer, maxLen); } String::String(jbyte* str, String* enc) { ByteToCharConverter* conv = ByteToCharConverter::getConverter(enc); int maxLen = strlen(str); init(maxLen); ByteArrayInputStream byteStream(str, maxLen); len = conv->convert(&byteStream, buffer, maxLen); } String::String(jbyte* str, jint offset, jint len) { init(len); this->len = len; for (int x = 0; x < len; x++) buffer[x] = (jchar) str[offset + x]; } String::String(jchar* str, jint offset, jint len) { init(len); this->len = len; memcpy(buffer, &str[offset], sizeof(jchar) * len); } /*****************************************************************************\ * init | *****************************************************************************/ void String::init(int initialCapacity) { capacity = 0; len = 0; buffer = null; latin1Buffer = null; utf8Buffer = null; cachedHashCode = 0; if (initialCapacity >= String::initialCapacity) ensureCapacity(initialCapacity); else ensureCapacity(String::initialCapacity); } /*****************************************************************************\ * ensureCapacity | *****************************************************************************/ void String::ensureCapacity(int minimumCapacity) { if (capacity >= minimumCapacity +1) { return; } else { int newCapacity = capacity + increment; if (minimumCapacity +1 > newCapacity) newCapacity = minimumCapacity +1; jchar* newText = (jchar*) realloc(buffer, sizeof(jchar) * newCapacity); if (newText == null) throw new MemoryException(JAKELIB_ONDEMAND(jakelib2_strings[0], new jakelib::lang::String(chars_jakelib2_str_0, 0, 11)) ->plus( (jlong) (sizeof(jchar) * newCapacity) )->plus( JAKELIB_ONDEMAND(jakelib2_strings[1], new jakelib::lang::String(chars_jakelib2_str_1, 0, 17)) )->plus( JAKELIB_AT2("jakelib.lang.String.ensureCapacity"))); else { capacity = newCapacity; buffer = newText; } } } /*****************************************************************************\ * ~String | *****************************************************************************/ String::~String() { free(buffer); GC_FREE(latin1Buffer); GC_FREE(utf8Buffer); } /*****************************************************************************\ * hashCode | *****************************************************************************/ int String::hashCode() { if (cachedHashCode == 0) { int h = 0; int off = 0; for (int i = 0; i < len; i++) { h = 31*h + buffer[off++]; } cachedHashCode = h; } return cachedHashCode; } /*****************************************************************************\ * equals | *****************************************************************************/ jboolean String::equals(Object* obj) { if (obj == null || !obj->getClass()->isInstance(this)) return false; String* other = (String*) obj; if (this->len != other->len) { return false; } else { for (int x = 0; x < len; x++) if (this->buffer[x] != other->buffer[x]) return false; return true; } } jboolean String::equals(jbyte* str) { if (str == null) return false; String s(str); return equals(&s); } /*****************************************************************************\ * equalsIgnoreCase | *****************************************************************************/ jboolean String::equalsIgnoreCase(jbyte* str) { if (str == null) return false; String s(str); return equalsIgnoreCase(&s); } jboolean String::equalsIgnoreCase(String* str) { if (str == null) return false; if (len != str->len) { return false; } else { for (int x = 0; x < len; x++) if (! (buffer[x] == str->buffer[x] || Character::toLowerCase(buffer[x]) == Character::toLowerCase(str->buffer[x]) || Character::toUpperCase(buffer[x]) == Character::toUpperCase(str->buffer[x]))) return false; } return true; } /*****************************************************************************\ * trim | *****************************************************************************/ String* String::trim() { int from; int to; for (from = 0; from < len && (buffer[from] == ' ' || buffer[from] == '\t'); from++); for (to = len -1; to >= from && (buffer[to] == ' ' || buffer[to] == '\t'); to--); if (to < from) return emptyString; else if (from > 0 || to < len -1) return substring(from, to + 1); else return this; } /*****************************************************************************\ * toInt | *****************************************************************************/ jint String::toInt() { return Integer::parseInt(this); } /*****************************************************************************\ * toLong | *****************************************************************************/ jlong String::toLong() { return Long::parseLong(this); } /*****************************************************************************\ * toByte | *****************************************************************************/ jbyte String::toByte() { return Byte::parseByte(this); } /*****************************************************************************\ * toShort | *****************************************************************************/ jshort String::toShort() { return Short::parseShort(this); } /*****************************************************************************\ * indexOf | *****************************************************************************/ int String::indexOf(String* str, int fromIndex) { if (fromIndex < 0) fromIndex = 0; for (int x = fromIndex; x <= len - str->len; x++) { if (regionMatches(x, str, 0, str->len)) return x; } return -1; } int String::indexOf(jbyte* str, int fromIndex) { String s(str); return indexOf(&s, fromIndex); } int String::indexOf(jchar c, int fromIndex) { if (fromIndex < 0) fromIndex = 0; for (int x = fromIndex; x < len; x++) { if (buffer[x] == c) return x; } return -1; } /*****************************************************************************\ * lastIndexOf | *****************************************************************************/ int String::lastIndexOf(String* str, int fromIndex) { if (fromIndex > len) fromIndex = len; for (int x = fromIndex; x >= 0; x--) { if (regionMatches(x, str, 0, str->len)) return x; } return -1; } int String::lastIndexOf(jbyte* str, int fromIndex) { String s(str); return lastIndexOf(&s); } int String::lastIndexOf(String* str) { return lastIndexOf(str, len -1); } int String::lastIndexOf(jbyte* str) { return lastIndexOf(str, len -1); } /*****************************************************************************\ * startsWith | *****************************************************************************/ jboolean String::startsWith(String* str) { if (len < str->len) return false; for (int x = 0; x < str->len; x++) { if (str->buffer[x] != buffer[x]) return false; } return true; } jboolean String::startsWith(jbyte* str) { String s(str); return startsWith(&s); } jboolean String::startsWith(String* prefix, jint toffset) { if (prefix == null) throw new NullPointerException(JAKELIB_ONDEMAND(jakelib2_strings[2], new jakelib::lang::String(chars_jakelib2_str_2, 0, 19)) ->plus( JAKELIB_AT2("jakelib.lang.String.startsWith"))); return regionMatches(false, toffset, prefix, 0, prefix->length()); } /*****************************************************************************\ * endsWith | *****************************************************************************/ jboolean String::endsWith(String* str) { if (len < str->len) return false; for (int x = 0; x < str->len; x++) { if (str->buffer[x] != buffer[x + len - str->len]) return false; } return true; } jboolean String::endsWith(jbyte* str) { String s(str); return endsWith(&s); } /*****************************************************************************\ * latin1 | *****************************************************************************/ char* String::latin1() { if (latin1Buffer == null) { char* b = (char*) GC_MALLOC_ATOMIC(len +1); jchar c; for (int x = 0; x < len; x++) { c = buffer[x]; if (c <= 0x00ff) { b[x] = (jbyte) c; } else { b[x] = '?'; } } b[len] = 0; latin1Buffer = b; } return latin1Buffer; } /*****************************************************************************\ * utf16 | *****************************************************************************/ jchar* String::utf16() { buffer[len] = 0; return buffer; } /*****************************************************************************\ * utf8 | *****************************************************************************/ char* String::utf8() { if (utf8Buffer == null) { char* b; CharToByteConverter* conv = CharToByteConverter::getConverter("UTF-8"); // FIXME: Reuse ByteArray! ByteArray bytes; conv->convert(buffer, 0, len, &bytes); b = (char*) GC_MALLOC_ATOMIC(bytes.size() +1); bytes.copyTo(b); b[len] = '\0'; utf8Buffer = b; } return utf8Buffer; } /*****************************************************************************\ * substring | *****************************************************************************/ String* String::substring(int beginIndex, int endIndex) { if (endIndex < 0) { throw new IllegalArgumentException(JAKELIB_ONDEMAND(jakelib2_strings[3], new jakelib::lang::String(chars_jakelib2_str_3, 0, 0)) ->plus( beginIndex )->plus( JAKELIB_ONDEMAND(jakelib2_strings[4], new jakelib::lang::String(chars_jakelib2_str_4, 0, 2)) )->plus( endIndex )->plus( JAKELIB_ONDEMAND(jakelib2_strings[5], new jakelib::lang::String(chars_jakelib2_str_5, 0, 15)) )->plus( JAKELIB_AT2("jakelib.lang.String.substring"))); } if (beginIndex < 0) { throw new IllegalArgumentException(JAKELIB_ONDEMAND(jakelib2_strings[6], new jakelib::lang::String(chars_jakelib2_str_6, 0, 0)) ->plus( beginIndex )->plus( JAKELIB_ONDEMAND(jakelib2_strings[7], new jakelib::lang::String(chars_jakelib2_str_7, 0, 2)) )->plus( endIndex )->plus( JAKELIB_ONDEMAND(jakelib2_strings[8], new jakelib::lang::String(chars_jakelib2_str_8, 0, 17)) )->plus( JAKELIB_AT2("jakelib.lang.String.substring"))); } if (endIndex < beginIndex) { return emptyString; } if (beginIndex >= len) { return emptyString; } else if (beginIndex == 0 && endIndex >= len) { return this; } else { return new String(buffer, beginIndex, endIndex - beginIndex); } } String* String::substring(int beginIndex) { if (beginIndex < 0) { throw new IllegalArgumentException(JAKELIB_ONDEMAND(jakelib2_strings[9], new jakelib::lang::String(chars_jakelib2_str_9, 0, 0)) ->plus( beginIndex )->plus( JAKELIB_ONDEMAND(jakelib2_strings[10], new jakelib::lang::String(chars_jakelib2_str_10, 0, 4)) )->plus( JAKELIB_AT2("jakelib.lang.String.substring"))); } if (beginIndex >= len) { return emptyString; } else { return new String(buffer, beginIndex, len - beginIndex); } } /*****************************************************************************\ * replace | *****************************************************************************/ String* String::replace(jchar oldChar, jchar newChar) { if (oldChar != newChar && indexOf(oldChar) != -1 && len > 0) { String* newStr = new String(this); for (int i = 0; i < len; i++) { if (newStr->buffer[i] == oldChar) { newStr->buffer[i] = newChar; } } return newStr; } else { return this; } } /*****************************************************************************\ * getChars | *****************************************************************************/ jchar* String::protectedGetChars() { return buffer; } // jchars* String::getChars(jint srcBegin, jint srcEnd, jchars* dst, jint dstBegin) // { // if(srcBegin < 0) // throw new StringIndexOutOfBoundsException(`"Specified beginning value negative: "` .. // srcBegin .. `" < 0"` .. // JAKELIB_AT2("jakelib.lang.String.getChars")); // else if (srcBegin > srcEnd) // throw new StringIndexOutOfBoundsException(`"Beginning value larger than end: "` .. // srcBegin .. `" > "` .. srcEnd .. // JAKELIB_AT2("jakelib.lang.String.getChars")); // else if (srcEnd > len) // throw new StringIndexOutOfBoundsException(`"End value larger than length: "` .. // srcEnd .. `" > "` .. len .. // JAKELIB_AT2("jakelib.lang.String.getChars")); // jchars* tmpdst = dst; // if (tmpdst == null) { // tmpdst = new jchars(srcEnd - srcBegin); // dstBegin = 0; // } // memcpy(tmpdst->getArray()+dstBegin, &buffer[srcBegin], sizeof(jchar) * (srcEnd - srcBegin)); // return(tmpdst); // } /*****************************************************************************\ * regionMatches | *****************************************************************************/ jboolean String::regionMatches(int toffset, String* other, int ooffset, int len) { return regionMatches(false, toffset, other, ooffset, len); } jboolean String::regionMatches(jboolean ignoreCase, int toffset, String* other, int ooffset, int len) { if (toffset < 0 || ooffset < 0 || toffset+len > this->len || ooffset+len > other->len) return false; if (ignoreCase) { for (int x = 0; x < len; x++) { if (buffer[toffset+x] == other->buffer[ooffset+x] || Character::toLowerCase(buffer[toffset+x]) == Character::toLowerCase(other->buffer[ooffset+x]) || Character::toUpperCase(buffer[toffset+x]) == Character::toUpperCase(other->buffer[ooffset+x])) continue; else return false; } } else { for (int x = 0; x < len; x++) { if (buffer[toffset+x] != other->buffer[ooffset+x]) return false; } } return true; } /*****************************************************************************\ * compareTo | *****************************************************************************/ int String::compareTo(String* other) { // FIXME: Do Unicode compare! return strcmp(latin1(), other->latin1()); } int String::compareTo(Object* obj) { // FIXME: Check for object class! return compareTo((String*) obj); } /*****************************************************************************\ * plus | *****************************************************************************/ String* String::plus(Object* obj) { if (obj != null) { String* str = obj->toString(); String* newStr = new String(this); newStr->ensureCapacity(len + str->len); memcpy(&newStr->buffer[len], str->buffer, str->len * sizeof(jchar)); newStr->len += str->len; return newStr; } else { return plus("null"); } } String* String::plus(const jbyte* str) { if (str != null) { String* newStr = new String(this); int l = strlen(str); newStr->ensureCapacity(len + l); for (int x = 0; x < l; x++) newStr->buffer[len + x] = (jchar) str[x]; newStr->len += strlen(str); return newStr; } else return plus("null"); } String* String::plus(jbyte c) { String* newStr = new String(this); newStr->ensureCapacity(len + 1); newStr->buffer[len] = c; newStr->len++; return newStr; } String* String::plus(jchar c) { String* newStr = new String(this); newStr->ensureCapacity(len + 1); newStr->buffer[len] = c; newStr->len++; return newStr; } String* String::plus(jdouble d) { return plus(Double::toString(d)); } String* String::plus(jlong l) { return plus(Long::toString(l)); } String* String::plus(jint i) { return plus(Integer::toString(i)); } /*****************************************************************************\ * charAt | *****************************************************************************/ jchar String::charAt(int index) { if (index < 0) throw new IndexOutOfBoundsException(JAKELIB_ONDEMAND(jakelib2_strings[11], new jakelib::lang::String(chars_jakelib2_str_11, 0, 0)) ->plus( index )->plus( index )->plus( JAKELIB_ONDEMAND(jakelib2_strings[12], new jakelib::lang::String(chars_jakelib2_str_12, 0, 4)) )->plus( JAKELIB_AT2("jakelib.lang.String.charAt"))); if (index >= len) return 0; return buffer[index]; } /*****************************************************************************\ * toUpperCase | *****************************************************************************/ String* String::toUpperCase() { if (len > 0) { String* newStr = new String(this); for (int x = 0; x < len; x++) { newStr->buffer[x] = Character::toUpperCase(buffer[x]); } return newStr; } else { return this; } } /*****************************************************************************\ * toLowerCase | *****************************************************************************/ String* String::toLowerCase() { if (len > 0) { String* newStr = new String(this); for (int x = 0; x < len; x++) { newStr->buffer[x] = Character::toLowerCase(buffer[x]); } return newStr; } else { return this; } } /*****************************************************************************\ * intern | *****************************************************************************/ /*String* String::intern(String* str) { String* i = (String*) internPool->get(str); if (i == null) { internPool->put(str, str); i = str; } return i; } String* String::intern(char* str) { return intern(new String(str)); }*/ /*****************************************************************************\ * | * Some EXTRAS... | * | *****************************************************************************/ /*****************************************************************************\ * printf | *****************************************************************************/ #include "../io/printf-macro.inc" String* String::printf(String* fstring, ...) { JAKELIB_PRINTF(fstring, buf); return buf.toString(); } /*****************************************************************************\ * append | *****************************************************************************/ void String::append(String* str) { //::printf("String::append(String*)\n"); if (str != null) { ensureCapacity(len + str->len); memcpy(&buffer[len], str->buffer, str->len + 1); len += str->len; } } void String::append(const jbyte* str) { //::printf("String::append(jbyte*)\n"); if (str != null) { int l = strlen(str); ensureCapacity(len + l); for (int x = 0; x < l; x++) { buffer[len++] = str[x]; } } } void String::append(jbyte c) { //::printf("String::append(jbyte)\n"); ensureCapacity(len +1); buffer[len++] = (jchar) c; } void String::append(jchar c) { ensureCapacity(len +1); buffer[len++] = c; } /*****************************************************************************\ * toCppString | *****************************************************************************/ String* String::toCppString() { String* str = new String(); for (int x = 0; x < len; x++) { switch(buffer[x]) { 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(buffer[x]); break; } } return str; } /*****************************************************************************\ * parseCppString | *****************************************************************************/ String* String::parseCppString() { String* str = new String(); jchar c; for (int x = 0; x < len; x++) { c = buffer[x]; if (c == '\\') { if (x +1 < len) switch(buffer[x +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; } x ++; } else { str->append(c); } } return str; } /*****************************************************************************\ * arg | *****************************************************************************/ String* String::arg(int idx, String* subst) { if (idx < 0 || idx > 9) throw new IllegalArgumentException(JAKELIB_ONDEMAND(jakelib2_strings[13], new jakelib::lang::String(chars_jakelib2_str_13, 0, 6)) ->plus( idx )->plus( JAKELIB_AT2("jakelib.lang.String.arg"))); idx += '0'; jchar c; for (int x = 0; x < len; x ++) { c = charAt(x); if (c == '%' && x < len -1) { c = charAt(++x); if (c == idx) { return substring(0, x -1) ->plus( subst )->plus( substring(x +1)); } } } return this; } String* String::arg(int idx, jlong l) { return arg(idx, valueOf(l)); } String* String::arg(int idx, jint i) { return arg(idx, valueOf(i)); } String* String::arg(int idx, jdouble d) { return arg(idx, valueOf(d)); } String* String::arg(int idx, const jbyte *str) { return arg(idx, new String(str)); } String* String::arg(int idx, jbyte c) { return arg(idx, new String(&c, 0, 1)); } String* String::arg(int idx, jchar c) { return arg(idx, new String(&c, 0, 1)); } /*****************************************************************************\ * valueOf | *****************************************************************************/ String* String::valueOf(jint i) { return Integer::toString(i); } String* String::valueOf(jlong l) { return Long::toString(l); } String* String::valueOf(jchar c) { return new String(&c, 0, 1); } String* String::valueOf(jfloat f) { return Float::toString(f); } String* String::valueOf(jdouble d) { return Double::toString(d); } /*****************************************************************************\ * initStringClass | *****************************************************************************/ void String::initStringClass() { emptyString = new String(); nullString = new String("null"); }