diff options
Diffstat (limited to 'libjava/java/lang/natString.cc')
-rw-r--r-- | libjava/java/lang/natString.cc | 1068 |
1 files changed, 0 insertions, 1068 deletions
diff --git a/libjava/java/lang/natString.cc b/libjava/java/lang/natString.cc deleted file mode 100644 index 75006a7..0000000 --- a/libjava/java/lang/natString.cc +++ /dev/null @@ -1,1068 +0,0 @@ -// natString.cc - Implementation of java.lang.String native methods. - -/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, - 2007, 2008 Free Software Foundation - - This file is part of libgcj. - -This software is copyrighted work licensed under the terms of the -Libgcj License. Please consult the file "LIBGCJ_LICENSE" for -details. */ - -#include <config.h> - -#include <string.h> -#include <stdlib.h> - -#include <gcj/cni.h> -#include <java/lang/Character.h> -#include <java/lang/CharSequence.h> -#include <java/lang/String.h> -#include <java/lang/IndexOutOfBoundsException.h> -#include <java/lang/ArrayIndexOutOfBoundsException.h> -#include <java/lang/StringIndexOutOfBoundsException.h> -#include <java/lang/NullPointerException.h> -#include <java/lang/StringBuffer.h> -#include <java/io/ByteArrayOutputStream.h> -#include <java/io/CharConversionException.h> -#include <java/io/OutputStreamWriter.h> -#include <java/io/ByteArrayInputStream.h> -#include <java/io/InputStreamReader.h> -#include <java/util/Locale.h> -#include <gnu/gcj/convert/UnicodeToBytes.h> -#include <gnu/gcj/convert/BytesToUnicode.h> -#include <gnu/gcj/runtime/StringBuffer.h> -#include <jvm.h> - -static jstring* strhash = NULL; -static int strhash_count = 0; /* Number of slots used in strhash. */ -static int strhash_size = 0; /* Number of slots available in strhash. - * Assumed be power of 2! */ - -// Some defines used by toUpperCase / toLowerCase. -#define ESSET 0x00df -#define CAPITAL_S 0x0053 -#define SMALL_I 0x0069 -#define CAPITAL_I_WITH_DOT 0x0130 -#define SMALL_DOTLESS_I 0x0131 -#define CAPITAL_I 0x0049 - -#define DELETED_STRING ((jstring)(~0)) -#define SET_STRING_IS_INTERNED(STR) /* nothing */ - -#define UNMASK_PTR(Ptr) (((unsigned long) (Ptr)) & ~0x01) -#define MASK_PTR(Ptr) (((unsigned long) (Ptr)) | 0x01) -#define PTR_MASKED(Ptr) (((unsigned long) (Ptr)) & 0x01) - -/* Find a slot where the string with elements DATA, length LEN, - and hash HASH should go in the strhash table of interned strings. */ -jstring* -_Jv_StringFindSlot (jchar* data, jint len, jint hash) -{ - JvSynchronize sync (&java::lang::String::class$); - - int start_index = hash & (strhash_size - 1); - int deleted_index = -1; - - int index = start_index; - /* step must be non-zero, and relatively prime with strhash_size. */ - jint step = (hash ^ (hash >> 16)) | 1; - do - { - jstring* ptr = &strhash[index]; - jstring value = (jstring) UNMASK_PTR (*ptr); - if (value == NULL) - { - if (deleted_index >= 0) - return (&strhash[deleted_index]); - else - return ptr; - } - else if (*ptr == DELETED_STRING) - deleted_index = index; - else if (value->length() == len - && memcmp(JvGetStringChars(value), data, 2*len) == 0) - return (ptr); - index = (index + step) & (strhash_size - 1); - } - while (index != start_index); - // Note that we can have INDEX == START_INDEX if the table has no - // NULL entries but does have DELETED_STRING entries. - JvAssert (deleted_index >= 0); - return &strhash[deleted_index]; -} - -/* Calculate a hash code for the string starting at PTR at given LENGTH. - This uses the same formula as specified for java.lang.String.hash. */ - -static jint -hashChars (jchar* ptr, jint length) -{ - jchar* limit = ptr + length; - jint hash = 0; - // Updated specification from - // http://www.javasoft.com/docs/books/jls/clarify.html. - while (ptr < limit) - hash = (31 * hash) + *ptr++; - return hash; -} - -jint -java::lang::String::hashCode() -{ - if (cachedHashCode == 0) - cachedHashCode = hashChars(JvGetStringChars(this), length()); - return cachedHashCode; -} - -jstring* -_Jv_StringGetSlot (jstring str) -{ - jchar* data = JvGetStringChars(str); - int length = str->length(); - return _Jv_StringFindSlot(data, length, hashChars (data, length)); -} - -static void -rehash () -{ - JvSynchronize sync (&java::lang::String::class$); - - if (strhash == NULL) - { - strhash_size = 1024; - strhash = (jstring *) _Jv_AllocBytes (strhash_size * sizeof (jstring)); - } - else - { - int i = strhash_size; - jstring* ptr = strhash + i; - int nsize = strhash_size * 2; - jstring *next = (jstring *) _Jv_AllocBytes (nsize * sizeof (jstring)); - - while (--i >= 0) - { - --ptr; - if (*ptr == NULL || *ptr == DELETED_STRING) - continue; - - /* This is faster equivalent of - * *__JvGetInternSlot(*ptr) = *ptr; */ - jstring val = (jstring) UNMASK_PTR (*ptr); - jint hash = val->hashCode(); - jint index = hash & (nsize - 1); - jint step = (hash ^ (hash >> 16)) | 1; - for (;;) - { - if (next[index] == NULL) - { - next[index] = *ptr; - break; - } - index = (index + step) & (nsize - 1); - } - } - - strhash_size = nsize; - strhash = next; - } -} - -jstring -java::lang::String::intern() -{ - JvSynchronize sync (&java::lang::String::class$); - if (3 * strhash_count >= 2 * strhash_size) - rehash(); - jstring* ptr = _Jv_StringGetSlot(this); - if (*ptr != NULL && *ptr != DELETED_STRING) - { - // See description in _Jv_FinalizeString() to understand this. - *ptr = (jstring) MASK_PTR (*ptr); - return (jstring) UNMASK_PTR (*ptr); - } - jstring str = (this->data == this - ? this - : _Jv_NewString(JvGetStringChars(this), this->length())); - SET_STRING_IS_INTERNED(str); - strhash_count++; - *ptr = str; - // When string is GC'd, clear the slot in the hash table. - _Jv_RegisterStringFinalizer (str); - return str; -} - -// The fake String finalizer. This is only used when the String has -// been intern()d. However, we must check this case, as it might be -// called by the Reference code for any String. -void -_Jv_FinalizeString (jobject obj) -{ - JvSynchronize sync (&java::lang::String::class$); - - // We might not actually have intern()d any strings at all, if - // we're being called from Reference. - if (! strhash) - return; - - jstring str = reinterpret_cast<jstring> (obj); - jstring *ptr = _Jv_StringGetSlot(str); - if (*ptr == NULL || *ptr == DELETED_STRING - || (jobject) UNMASK_PTR (*ptr) != obj) - return; - - // We assume the lowest bit of the pointer is free for our nefarious - // manipulations. What we do is set it to `0' (implicitly) when - // interning the String. If we subsequently re-intern the same - // String, then we set the bit. When finalizing, if the bit is set - // then we clear it and re-register the finalizer. We know this is - // a safe approach because both intern() and _Jv_FinalizeString() - // acquire the class lock; this bit can't be manipulated when the - // lock is not held. So if we are finalizing and the bit is clear - // then we know all references are gone and we can clear the entry - // in the hash table. The naive approach of simply clearing the - // pointer here fails in the case where a request to intern a new - // string with the same contents is made between the time the - // intern()d string is found to be unreachable and when the - // finalizer is actually run. In this case we could clear a pointer - // to a valid string, and future intern() calls for that particular - // value would spuriously fail. - if (PTR_MASKED (*ptr)) - { - *ptr = (jstring) UNMASK_PTR (*ptr); - _Jv_RegisterStringFinalizer (obj); - } - else - { - *ptr = DELETED_STRING; - strhash_count--; - } -} - -jstring -_Jv_NewStringUTF (const char *bytes) -{ - int size = strlen (bytes); - unsigned char *p = (unsigned char *) bytes; - - int length = _Jv_strLengthUtf8 ((char *) p, size); - if (length < 0) - return NULL; - - jstring jstr = JvAllocString (length); - jchar *chrs = JvGetStringChars (jstr); - - p = (unsigned char *) bytes; - unsigned char *limit = p + size; - while (p < limit) - *chrs++ = UTF8_GET (p, limit); - - return jstr; -} - -jstring -_Jv_NewStringUtf8Const (Utf8Const* str) -{ - jchar *chrs; - jchar buffer[100]; - jstring jstr; - unsigned char* data = (unsigned char*) str->data; - unsigned char* limit = data + str->length; - int length = _Jv_strLengthUtf8(str->data, str->length); - - if (length <= (int) (sizeof(buffer) / sizeof(jchar))) - { - jstr = NULL; - chrs = buffer; - } - else - { - jstr = JvAllocString(length); - chrs = JvGetStringChars(jstr); - } - - jint hash = 0; - while (data < limit) - { - jchar ch = UTF8_GET(data, limit); - hash = (31 * hash) + ch; - *chrs++ = ch; - } - chrs -= length; - - JvSynchronize sync (&java::lang::String::class$); - if (3 * strhash_count >= 2 * strhash_size) - rehash(); - jstring* ptr = _Jv_StringFindSlot (chrs, length, hash); - if (*ptr != NULL && *ptr != DELETED_STRING) - return (jstring) UNMASK_PTR (*ptr); - strhash_count++; - if (jstr == NULL) - { - jstr = JvAllocString(length); - chrs = JvGetStringChars(jstr); - memcpy (chrs, buffer, sizeof(jchar)*length); - } - jstr->cachedHashCode = hash; - *ptr = jstr; - SET_STRING_IS_INTERNED(jstr); - // When string is GC'd, clear the slot in the hash table. Note that - // we don't have to call _Jv_RegisterStringFinalizer here, as we - // know the new object cannot be referred to by a Reference. - _Jv_RegisterFinalizer ((void *) jstr, _Jv_FinalizeString); - return jstr; -} - -jsize -_Jv_GetStringUTFLength (jstring string) -{ - jsize len = 0; - jchar *ptr = JvGetStringChars (string); - jsize i = string->length(); - while (--i >= 0) - { - jchar ch = *ptr++; - if (ch > 0 && ch <= 0x7F) - len += 1; - else if (ch <= 0x7FF) - len += 2; - else - len += 3; - } - return len; -} - -// Not sure this quite matches GetStringUTFRegion. -// null-termination of result? len? throw exception? -jsize -_Jv_GetStringUTFRegion (jstring str, jsize start, jsize len, char *buf) -{ - jchar *sptr = JvGetStringChars (str) + start; - jsize i = len; - char *dptr = buf; - while (--i >= 0) - { - jchar ch = *sptr++; - if (ch > 0 && ch <= 0x7F) - *dptr++ = (char) ch; - else if (ch <= 0x7FF) - { - *dptr++ = (char) (0xC0 + ((ch >> 6) & 0x1F)); - *dptr++ = (char) (0x80 + (ch & 0x3F)); - } - else - { - *dptr++ = (char) (0xE0 + ((ch >> 12) & 0xF)); - *dptr++ = (char) (0x80 + ((ch >> 6) & 0x3F)); - *dptr++ = (char) (0x80 + (ch & 0x3F)); - } - } - return dptr - buf; -} - -/* Put printed (decimal) representation of NUM in a buffer. - BUFEND marks the end of the buffer, which must be at least 11 jchars long. - Returns the COUNT of jchars written. The result is in - (BUFEND - COUNT) (inclusive) upto (BUFEND) (exclusive). */ - -jint -_Jv_FormatInt (jchar* bufend, jint num) -{ - register jchar* ptr = bufend; - jboolean isNeg; - if (num < 0) - { - isNeg = true; - if (num != (jint) -2147483648U) - num = -(num); - else - { - // Handle special case of MIN_VALUE. - *--ptr = '8'; - num = 214748364; - } - } - else - isNeg = false; - - do - { - *--ptr = (jchar) ((int) '0' + (num % 10)); - num /= 10; - } - while (num > 0); - - if (isNeg) - *--ptr = '-'; - return bufend - ptr; -} - -jstring -java::lang::String::valueOf (jint num) -{ - // Use an array large enough for "-2147483648"; i.e. 11 chars. - jchar buffer[11]; - int i = _Jv_FormatInt (buffer+11, num); - return _Jv_NewString (buffer+11-i, i); -} - -jstring -_Jv_NewString(const jchar *chars, jsize len) -{ - jstring str = _Jv_AllocString(len); - jchar* data = JvGetStringChars (str); - memcpy (data, chars, len * sizeof (jchar)); - return str; -} - -jstring -_Jv_NewStringLatin1(const char *bytes, jsize len) -{ - jstring str = JvAllocString(len); - jchar* data = JvGetStringChars (str); - while (--len >= 0) - *data++ = *(unsigned char*)bytes++; - return str; -} - -void -java::lang::String::init(jcharArray chars, jint offset, jint count, - jboolean dont_copy) -{ - if (! chars) - throw new NullPointerException; - jsize data_size = JvGetArrayLength (chars); - if (offset < 0 || count < 0 || offset + count < 0 - || offset + count > data_size) - throw new ArrayIndexOutOfBoundsException; - jcharArray array; - jchar *pdst; - if (! dont_copy) - { - array = JvNewCharArray(count); - pdst = elements (array); - memcpy (pdst, elements (chars) + offset, count * sizeof (jchar)); - } - else - { - array = chars; - pdst = &(elements(array)[offset]); - } - - data = array; - boffset = (char *) pdst - (char *) array; - this->count = count; -} - -void -java::lang::String::init(jbyteArray ascii, jint hibyte, jint offset, - jint count) -{ - if (! ascii) - throw new NullPointerException; - jsize data_size = JvGetArrayLength (ascii); - if (offset < 0 || count < 0 || offset + count < 0 - || offset + count > data_size) - throw new ArrayIndexOutOfBoundsException; - jcharArray array = JvNewCharArray(count); - jbyte *psrc = elements (ascii) + offset; - jchar *pdst = elements (array); - data = array; - boffset = (char *) pdst - (char *) array; - this->count = count; - hibyte = (hibyte & 0xff) << 8; - while (-- count >= 0) - { - *pdst++ = hibyte | (*psrc++ & 0xff); - } -} - -void -java::lang::String::init (jbyteArray bytes, jint offset, jint count, - jstring encoding) -{ - if (! bytes) - throw new NullPointerException; - jsize data_size = JvGetArrayLength (bytes); - if (offset < 0 || count < 0 || offset + count < 0 - || offset + count > data_size) - throw new ArrayIndexOutOfBoundsException; - jcharArray array = JvNewCharArray (count); - gnu::gcj::convert::BytesToUnicode *converter - = gnu::gcj::convert::BytesToUnicode::getDecoder(encoding); - jint outpos = 0; - int avail = count; - converter->setInput(bytes, offset, offset+count); - while (converter->inpos < converter->inlength) - { - int done; - try - { - done = converter->read(array, outpos, avail); - } - catch (::java::io::CharConversionException *e) - { - // Ignore it and silently throw away the offending data. - break; - } - if (done == 0) - { - // done is zero if either there is no space available in the - // output *or* the input is incomplete. We assume that if - // there are 20 characters available in the output, the - // input must be incomplete and there is no more work to do. - // This means we may skip several bytes of input, but that - // is OK as the behavior is explicitly unspecified in this - // case. - if (avail - outpos > 20) - break; - - jint new_size = 2 * (outpos + avail); - jcharArray new_array = JvNewCharArray (new_size); - memcpy (elements (new_array), elements (array), - outpos * sizeof(jchar)); - array = new_array; - avail = new_size - outpos; - } - else - { - outpos += done; - avail -= done; - } - } - converter->done (); - this->data = array; - this->boffset = (char *) elements (array) - (char *) array; - this->count = outpos; -} - -void -java::lang::String::init (gnu::gcj::runtime::StringBuffer *buffer) -{ - init (buffer->value, 0, buffer->count, true); -} - -jboolean -java::lang::String::equals(jobject anObject) -{ - if (anObject == NULL) - return false; - if (anObject == this) - return true; - if (anObject->getClass() != &java::lang::String::class$) - return false; - jstring other = (jstring) anObject; - if (count != other->count) - return false; - - // If both have cached hash codes, check that. If the cached hash - // codes are zero, don't bother trying to compute them. - int myHash = cachedHashCode; - int otherHash = other->cachedHashCode; - if (myHash && otherHash && myHash != otherHash) - return false; - - // We could see if both are interned, and return false. But that - // seems too expensive. - - jchar *xptr = JvGetStringChars (this); - jchar *yptr = JvGetStringChars (other); - return ! memcmp (xptr, yptr, count * sizeof (jchar)); -} - -jboolean -java::lang::String::contentEquals(java::lang::StringBuffer* buffer) -{ - if (buffer == NULL) - throw new NullPointerException; - JvSynchronize sync(buffer); - if (count != buffer->count) - return false; - if (data == buffer->value) - return true; // Possible if shared. - jchar *xptr = JvGetStringChars(this); - jchar *yptr = elements(buffer->value); - return ! memcmp (xptr, yptr, count * sizeof (jchar)); -} - -jboolean -java::lang::String::contentEquals(java::lang::CharSequence *seq) -{ - if (seq->length() != count) - return false; - jchar *value = JvGetStringChars(this); - for (int i = 0; i < count; ++i) - if (value[i] != seq->charAt(i)) - return false; - return true; -} - -jchar -java::lang::String::charAt(jint i) -{ - if (i < 0 || i >= count) - throw new java::lang::StringIndexOutOfBoundsException(i); - return JvGetStringChars(this)[i]; -} - -void -java::lang::String::getChars(jint srcBegin, jint srcEnd, - jcharArray dst, jint dstBegin) -{ - jint dst_length = JvGetArrayLength (dst); - if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count) - throw new java::lang::StringIndexOutOfBoundsException; - // The 2nd part of the test below is equivalent to - // dstBegin + (srcEnd-srcBegin) > dst_length - // except that it does not overflow. - if (dstBegin < 0 || dstBegin > dst_length - (srcEnd-srcBegin)) - throw new ArrayIndexOutOfBoundsException; - jchar *dPtr = elements (dst) + dstBegin; - jchar *sPtr = JvGetStringChars (this) + srcBegin; - jint i = srcEnd - srcBegin; - memcpy (dPtr, sPtr, i * sizeof (jchar)); -} - -jbyteArray -java::lang::String::getBytes (jstring enc) -{ - jint todo = length(); - jint buflen = todo; - jbyteArray buffer = JvNewByteArray(todo); - jint bufpos = 0; - jint offset = 0; - gnu::gcj::convert::UnicodeToBytes *converter - = gnu::gcj::convert::UnicodeToBytes::getEncoder(enc); - while (todo > 0 || converter->havePendingBytes()) - { - converter->setOutput(buffer, bufpos); - int converted = converter->write(this, offset, todo, NULL); - bufpos = converter->count; - if (converted == 0) - { - buflen *= 2; - jbyteArray newbuffer = JvNewByteArray(buflen); - memcpy (elements (newbuffer), elements (buffer), bufpos); - buffer = newbuffer; - } - else - { - offset += converted; - todo -= converted; - } - } - if (length() > 0) - { - converter->setFinished(); - converter->write(this, 0, 0, NULL); - } - converter->done (); - if (bufpos == buflen) - return buffer; - jbyteArray result = JvNewByteArray(bufpos); - memcpy (elements (result), elements (buffer), bufpos); - return result; -} - -void -java::lang::String::getBytes(jint srcBegin, jint srcEnd, - jbyteArray dst, jint dstBegin) -{ - jint dst_length = JvGetArrayLength (dst); - if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count) - throw new java::lang::StringIndexOutOfBoundsException; - // The 2nd part of the test below is equivalent to - // dstBegin + (srcEnd-srcBegin) > dst_length - // except that it does not overflow. - if (dstBegin < 0 || dstBegin > dst_length - (srcEnd-srcBegin)) - throw new ArrayIndexOutOfBoundsException; - jbyte *dPtr = elements (dst) + dstBegin; - jchar *sPtr = JvGetStringChars (this) + srcBegin; - jint i = srcEnd-srcBegin; - while (--i >= 0) - *dPtr++ = (jbyte) *sPtr++; -} - -jcharArray -java::lang::String::toCharArray() -{ - jcharArray array = JvNewCharArray(count); - jchar *dPtr = elements (array); - jchar *sPtr = JvGetStringChars (this); - jint i = count; - memcpy (dPtr, sPtr, i * sizeof (jchar)); - return array; -} - -jboolean -java::lang::String::equalsIgnoreCase (jstring anotherString) -{ - if (anotherString == NULL || count != anotherString->count) - return false; - jchar *tptr = JvGetStringChars (this); - jchar *optr = JvGetStringChars (anotherString); - jint i = count; - while (--i >= 0) - { - jchar tch = *tptr++; - jchar och = *optr++; - if (tch != och - && (java::lang::Character::toLowerCase (tch) - != java::lang::Character::toLowerCase (och)) - && (java::lang::Character::toUpperCase (tch) - != java::lang::Character::toUpperCase (och))) - return false; - } - return true; -} - -jboolean -java::lang::String::regionMatches (jint toffset, - jstring other, jint ooffset, jint len) -{ - if (toffset < 0 || ooffset < 0 || len < 0 - || toffset > count - len - || ooffset > other->count - len) - return false; - jchar *tptr = JvGetStringChars (this) + toffset; - jchar *optr = JvGetStringChars (other) + ooffset; - jint i = len; - return ! memcmp (tptr, optr, i * sizeof (jchar)); -} - -jint -java::lang::String::nativeCompareTo (jstring anotherString) -{ - jchar *tptr = JvGetStringChars (this); - jchar *optr = JvGetStringChars (anotherString); - jint tlen = this->count; - jint olen = anotherString->count; - jint i = tlen > olen ? olen : tlen; - while (--i >= 0) - { - jchar tch = *tptr++; - jchar och = *optr++; - if (tch != och) - return (jint) tch - (jint) och; - } - return tlen - olen; -} - -jboolean -java::lang::String::regionMatches (jboolean ignoreCase, jint toffset, - jstring other, jint ooffset, jint len) -{ - if (toffset < 0 || ooffset < 0 || len < 0 - || toffset > count - len - || ooffset > other->count - len) - return false; - jchar *tptr = JvGetStringChars (this) + toffset; - jchar *optr = JvGetStringChars (other) + ooffset; - jint i = len; - if (ignoreCase) - { - while (--i >= 0) - { - jchar tch = *tptr++; - jchar och = *optr++; - if ((java::lang::Character::toLowerCase (tch) - != java::lang::Character::toLowerCase (och)) - && (java::lang::Character::toUpperCase (tch) - != java::lang::Character::toUpperCase (och))) - return false; - } - return true; - } - return ! memcmp (tptr, optr, i * sizeof (jchar)); -} - -jboolean -java::lang::String::startsWith (jstring prefix, jint toffset) -{ - jint i = prefix->count; - if (toffset < 0 || toffset > count - i) - return false; - jchar *xptr = JvGetStringChars (this) + toffset; - jchar *yptr = JvGetStringChars (prefix); - return ! memcmp (xptr, yptr, i * sizeof (jchar)); -} - -jint -java::lang::String::indexOf (jint ch, jint fromIndex) -{ - if (fromIndex < 0) - fromIndex = 0; - jchar *ptr = JvGetStringChars(this); - for (;; ++fromIndex) - { - if (fromIndex >= count) - return -1; - if (ptr[fromIndex] == ch) - return fromIndex; - } -} - -jint -java::lang::String::indexOf (jstring s, jint fromIndex) -{ - const jchar *const xchars = JvGetStringChars(s); - const jchar *const ychars = JvGetStringChars(this) + fromIndex; - - const int xlength = s->length (); - const int ylength = length () - fromIndex; - - int i = 0; - int j = 0; - - while (i < ylength && j < xlength) - { - if (xchars[j] != ychars[i]) - { - i = i - j + 1; - j = 0; - } - else - i++, j++; - } - - if (j >= xlength) - return fromIndex + i - xlength; - else - return -1; -} - -jint -java::lang::String::lastIndexOf (jint ch, jint fromIndex) -{ - if (fromIndex >= count) - fromIndex = count - 1; - jchar *ptr = JvGetStringChars(this); - for (;; --fromIndex) - { - if (fromIndex < 0) - return -1; - if (ptr[fromIndex] == ch) - return fromIndex; - } -} - -jstring -java::lang::String::substring (jint beginIndex, jint endIndex) -{ - if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) - throw new StringIndexOutOfBoundsException; - if (beginIndex == 0 && endIndex == count) - return this; - jint newCount = endIndex - beginIndex; - // For very small strings, just allocate a new one. For other - // substrings, allocate a new one unless the substring is over half - // of the original string. - if (newCount <= 8 || newCount < (count >> 1)) - return JvNewString(JvGetStringChars(this) + beginIndex, newCount); - jstring s = new String(); - s->data = data; - s->count = newCount; - s->boffset = boffset + sizeof(jchar) * beginIndex; - return s; -} - -jstring -java::lang::String::concat(jstring str) -{ - jint str_count = str->count; - if (str_count == 0) - return this; - jstring result = JvAllocString(count + str_count); - jchar *dstPtr = JvGetStringChars(result); - jchar *srcPtr = JvGetStringChars(this); - jint i = count; - memcpy (dstPtr, srcPtr, i * sizeof (jchar)); - dstPtr += i; - srcPtr = JvGetStringChars(str); - i = str->count; - memcpy (dstPtr, srcPtr, i * sizeof (jchar)); - return result; -} - -jstring -java::lang::String::replace (jchar oldChar, jchar newChar) -{ - jint i; - jchar* chrs = JvGetStringChars (this); - for (i = 0; ; i++) - { - if (i == count) - return this; - if (chrs[i] == oldChar) - break; - } - jstring result = JvAllocString (count); - jchar *dPtr = JvGetStringChars (result); - for (int j = 0; j < i; j++) - *dPtr++ = chrs[j]; - for (; i < count; i++) - { - jchar ch = chrs[i]; - if (ch == oldChar) - ch = newChar; - *dPtr++ = ch; - } - return result; -} - -jstring -java::lang::String::toLowerCase (java::util::Locale *locale) -{ - jint i; - jchar* chrs = JvGetStringChars(this); - jchar ch = 0; - - bool handle_tr = false; - if (locale != NULL) - { - String *lang = locale->getLanguage (); - if (lang->length () == 2 - && lang->charAt (0) == 't' - && lang->charAt (1) == 'r') - handle_tr = true; - } - - for (i = 0; ; i++) - { - if (i == count) - return this; - jchar origChar = chrs[i]; - - if (handle_tr && (origChar == CAPITAL_I - || origChar == CAPITAL_I_WITH_DOT)) - break; - - ch = java::lang::Character::toLowerCase(origChar); - if (ch != origChar) - break; - } - jstring result = JvAllocString(count); - jchar *dPtr = JvGetStringChars (result); - for (int j = 0; j < i; j++) - *dPtr++ = chrs[j]; - *dPtr++ = ch; i++; - for (; i < count; i++) - { - if (handle_tr && chrs[i] == CAPITAL_I) - *dPtr++ = SMALL_DOTLESS_I; - else if (handle_tr && chrs[i] == CAPITAL_I_WITH_DOT) - *dPtr++ = SMALL_I; - else - *dPtr++ = java::lang::Character::toLowerCase(chrs[i]); - } - return result; -} - -jstring -java::lang::String::toUpperCase (java::util::Locale *locale) -{ - jint i; - jchar* chrs = JvGetStringChars(this); - jchar ch; - - // When handling a specific locale there might be special rules. - // Currently all existing rules are simply handled inline, as there - // are only two and they are documented in the online 1.2 docs. - bool handle_esset = locale != NULL; - bool handle_tr = false; - if (locale != NULL) - { - String *lang = locale->getLanguage (); - if (lang->length () == 2 - && lang->charAt (0) == 't' - && lang->charAt (1) == 'r') - handle_tr = true; - } - - int new_count = count; - bool new_string = false; - for (i = 0; ; i++) - { - if (i == count) - break; - jchar origChar = chrs[i]; - - if (handle_esset && origChar == ESSET) - { - ++new_count; - new_string = true; - } - else if (handle_tr && (origChar == SMALL_I - || origChar == SMALL_DOTLESS_I)) - new_string = true; - else - { - ch = java::lang::Character::toUpperCase(origChar); - if (ch != origChar) - new_string = true; - } - - if (new_string && ! handle_esset) - break; - } - if (! new_string) - return this; - jstring result = JvAllocString(new_count); - jchar *dPtr = JvGetStringChars (result); - for (i = 0; i < count; i++) - { - if (handle_esset && chrs[i] == ESSET) - { - *dPtr++ = CAPITAL_S; - *dPtr++ = CAPITAL_S; - } - else if (handle_tr && chrs[i] == SMALL_I) - *dPtr++ = CAPITAL_I_WITH_DOT; - else if (handle_tr && chrs[i] == SMALL_DOTLESS_I) - *dPtr++ = CAPITAL_I; - else - *dPtr++ = java::lang::Character::toUpperCase(chrs[i]); - } - return result; -} - -jstring -java::lang::String::trim () -{ - jchar* chrs = JvGetStringChars(this); - if (count == 0 || (chrs[0] > ' ' && chrs[count-1] > ' ')) - return this; - jint preTrim = 0; - for (;; preTrim++) - { - if (preTrim == count) - return new String(); - if (chrs[preTrim] > ' ') - break; - } - jint endTrim = count; - while (chrs[endTrim-1] <= ' ') - endTrim--; - return substring(preTrim, endTrim); -} - -jstring -java::lang::String::valueOf(jcharArray data, jint offset, jint count) -{ - jint data_length = JvGetArrayLength (data); - if (offset < 0 || count < 0 || offset > data_length - count) - throw new ArrayIndexOutOfBoundsException; - jstring result = JvAllocString(count); - jchar *sPtr = elements (data) + offset; - jchar *dPtr = JvGetStringChars(result); - memcpy (dPtr, sPtr, count * sizeof (jchar)); - return result; -} - -jstring -java::lang::String::valueOf(jchar c) -{ - jstring result = JvAllocString(1); - JvGetStringChars (result)[0] = c; - return result; -} |