OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [java/] [lang/] [natString.cc] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
// natString.cc - Implementation of java.lang.String native methods.
2
 
3
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006  Free Software Foundation
4
 
5
   This file is part of libgcj.
6
 
7
This software is copyrighted work licensed under the terms of the
8
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9
details.  */
10
 
11
#include <config.h>
12
 
13
#include <string.h>
14
#include <stdlib.h>
15
 
16
#include <gcj/cni.h>
17
#include <java/lang/Character.h>
18
#include <java/lang/CharSequence.h>
19
#include <java/lang/String.h>
20
#include <java/lang/IndexOutOfBoundsException.h>
21
#include <java/lang/ArrayIndexOutOfBoundsException.h>
22
#include <java/lang/StringIndexOutOfBoundsException.h>
23
#include <java/lang/NullPointerException.h>
24
#include <java/lang/StringBuffer.h>
25
#include <java/io/ByteArrayOutputStream.h>
26
#include <java/io/OutputStreamWriter.h>
27
#include <java/io/ByteArrayInputStream.h>
28
#include <java/io/InputStreamReader.h>
29
#include <java/util/Locale.h>
30
#include <gnu/gcj/convert/UnicodeToBytes.h>
31
#include <gnu/gcj/convert/BytesToUnicode.h>
32
#include <gnu/gcj/runtime/StringBuffer.h>
33
#include <jvm.h>
34
 
35
static jstring* strhash = NULL;
36
static int strhash_count = 0;  /* Number of slots used in strhash. */
37
static int strhash_size = 0;  /* Number of slots available in strhash.
38
                               * Assumed be power of 2! */
39
 
40
// Some defines used by toUpperCase / toLowerCase.
41
#define ESSET     0x00df
42
#define CAPITAL_S 0x0053
43
#define SMALL_I   0x0069
44
#define CAPITAL_I_WITH_DOT 0x0130
45
#define SMALL_DOTLESS_I    0x0131
46
#define CAPITAL_I 0x0049
47
 
48
#define DELETED_STRING ((jstring)(~0))
49
#define SET_STRING_IS_INTERNED(STR) /* nothing */
50
 
51
#define UNMASK_PTR(Ptr) (((unsigned long) (Ptr)) & ~0x01)
52
#define MASK_PTR(Ptr) (((unsigned long) (Ptr)) | 0x01)
53
#define PTR_MASKED(Ptr) (((unsigned long) (Ptr)) & 0x01)
54
 
55
/* Find a slot where the string with elements DATA, length LEN,
56
   and hash HASH should go in the strhash table of interned strings. */
57
jstring*
58
_Jv_StringFindSlot (jchar* data, jint len, jint hash)
59
{
60
  JvSynchronize sync (&java::lang::String::class$);
61
 
62
  int start_index = hash & (strhash_size - 1);
63
  int deleted_index = -1;
64
 
65
  int index = start_index;
66
  /* step must be non-zero, and relatively prime with strhash_size. */
67
  jint step = (hash ^ (hash >> 16)) | 1;
68
  do
69
    {
70
      jstring* ptr = &strhash[index];
71
      jstring value = (jstring) UNMASK_PTR (*ptr);
72
      if (value == NULL)
73
        {
74
          if (deleted_index >= 0)
75
            return (&strhash[deleted_index]);
76
          else
77
            return ptr;
78
        }
79
      else if (*ptr == DELETED_STRING)
80
        deleted_index = index;
81
      else if (value->length() == len
82
               && memcmp(JvGetStringChars(value), data, 2*len) == 0)
83
        return (ptr);
84
      index = (index + step) & (strhash_size - 1);
85
    }
86
  while (index != start_index);
87
  // Note that we can have INDEX == START_INDEX if the table has no
88
  // NULL entries but does have DELETED_STRING entries.
89
  JvAssert (deleted_index >= 0);
90
  return &strhash[deleted_index];
91
}
92
 
93
/* Calculate a hash code for the string starting at PTR at given LENGTH.
94
   This uses the same formula as specified for java.lang.String.hash. */
95
 
96
static jint
97
hashChars (jchar* ptr, jint length)
98
{
99
  jchar* limit = ptr + length;
100
  jint hash = 0;
101
  // Updated specification from
102
  // http://www.javasoft.com/docs/books/jls/clarify.html.
103
  while (ptr < limit)
104
    hash = (31 * hash) + *ptr++;
105
  return hash;
106
}
107
 
108
jint
109
java::lang::String::hashCode()
110
{
111
  if (cachedHashCode == 0)
112
    cachedHashCode = hashChars(JvGetStringChars(this), length());
113
  return cachedHashCode;
114
}
115
 
116
jstring*
117
_Jv_StringGetSlot (jstring str)
118
{
119
  jchar* data = JvGetStringChars(str);
120
  int length = str->length();
121
  return _Jv_StringFindSlot(data, length, hashChars (data, length));
122
}
123
 
124
static void
125
rehash ()
126
{
127
  JvSynchronize sync (&java::lang::String::class$);
128
 
129
  if (strhash == NULL)
130
    {
131
      strhash_size = 1024;
132
      strhash = (jstring *) _Jv_AllocBytes (strhash_size * sizeof (jstring));
133
    }
134
  else
135
    {
136
      int i = strhash_size;
137
      jstring* ptr = strhash + i;
138
      int nsize = strhash_size * 2;
139
      jstring *next = (jstring *) _Jv_AllocBytes (nsize * sizeof (jstring));
140
 
141
      while (--i >= 0)
142
        {
143
          --ptr;
144
          if (*ptr == NULL || *ptr == DELETED_STRING)
145
            continue;
146
 
147
          /* This is faster equivalent of
148
           * *__JvGetInternSlot(*ptr) = *ptr; */
149
          jstring val = (jstring) UNMASK_PTR (*ptr);
150
          jint hash = val->hashCode();
151
          jint index = hash & (nsize - 1);
152
          jint step = (hash ^ (hash >> 16)) | 1;
153
          for (;;)
154
            {
155
              if (next[index] == NULL)
156
                {
157
                  next[index] = *ptr;
158
                  break;
159
                }
160
              index = (index + step) & (nsize - 1);
161
            }
162
        }
163
 
164
      strhash_size = nsize;
165
      strhash = next;
166
    }
167
}
168
 
169
jstring
170
java::lang::String::intern()
171
{
172
  JvSynchronize sync (&java::lang::String::class$);
173
  if (3 * strhash_count >= 2 * strhash_size)
174
    rehash();
175
  jstring* ptr = _Jv_StringGetSlot(this);
176
  if (*ptr != NULL && *ptr != DELETED_STRING)
177
    {
178
      // See description in _Jv_FinalizeString() to understand this.
179
      *ptr = (jstring) MASK_PTR (*ptr);
180
      return (jstring) UNMASK_PTR (*ptr);
181
    }
182
  jstring str = (this->data == this
183
                 ? this
184
                 : _Jv_NewString(JvGetStringChars(this), this->length()));
185
  SET_STRING_IS_INTERNED(str);
186
  strhash_count++;
187
  *ptr = str;
188
  // When string is GC'd, clear the slot in the hash table.
189
  _Jv_RegisterStringFinalizer (str);
190
  return str;
191
}
192
 
193
// The fake String finalizer.  This is only used when the String has
194
// been intern()d.  However, we must check this case, as it might be
195
// called by the Reference code for any String.
196
void
197
_Jv_FinalizeString (jobject obj)
198
{
199
  JvSynchronize sync (&java::lang::String::class$);
200
 
201
  // We might not actually have intern()d any strings at all, if
202
  // we're being called from Reference.
203
  if (! strhash)
204
    return;
205
 
206
  jstring str = reinterpret_cast<jstring> (obj);
207
  jstring *ptr = _Jv_StringGetSlot(str);
208
  if (*ptr == NULL || *ptr == DELETED_STRING
209
      || (jobject) UNMASK_PTR (*ptr) != obj)
210
    return;
211
 
212
  // We assume the lowest bit of the pointer is free for our nefarious
213
  // manipulations.  What we do is set it to `0' (implicitly) when
214
  // interning the String.  If we subsequently re-intern the same
215
  // String, then we set the bit.  When finalizing, if the bit is set
216
  // then we clear it and re-register the finalizer.  We know this is
217
  // a safe approach because both intern() and _Jv_FinalizeString()
218
  // acquire the class lock; this bit can't be manipulated when the
219
  // lock is not held.  So if we are finalizing and the bit is clear
220
  // then we know all references are gone and we can clear the entry
221
  // in the hash table.  The naive approach of simply clearing the
222
  // pointer here fails in the case where a request to intern a new
223
  // string with the same contents is made between the time the
224
  // intern()d string is found to be unreachable and when the
225
  // finalizer is actually run.  In this case we could clear a pointer
226
  // to a valid string, and future intern() calls for that particular
227
  // value would spuriously fail.
228
  if (PTR_MASKED (*ptr))
229
    {
230
      *ptr = (jstring) UNMASK_PTR (*ptr);
231
      _Jv_RegisterStringFinalizer (obj);
232
    }
233
  else
234
    {
235
      *ptr = DELETED_STRING;
236
      strhash_count--;
237
    }
238
}
239
 
240
jstring
241
_Jv_NewStringUTF (const char *bytes)
242
{
243
  int size = strlen (bytes);
244
  unsigned char *p = (unsigned char *) bytes;
245
 
246
  int length = _Jv_strLengthUtf8 ((char *) p, size);
247
  if (length < 0)
248
    return NULL;
249
 
250
  jstring jstr = JvAllocString (length);
251
  jchar *chrs = JvGetStringChars (jstr);
252
 
253
  p = (unsigned char *) bytes;
254
  unsigned char *limit = p + size;
255
  while (p < limit)
256
    *chrs++ = UTF8_GET (p, limit);
257
 
258
  return jstr;
259
}
260
 
261
jstring
262
_Jv_NewStringUtf8Const (Utf8Const* str)
263
{
264
  jchar *chrs;
265
  jchar buffer[100];
266
  jstring jstr;
267
  unsigned char* data = (unsigned char*) str->data;
268
  unsigned char* limit = data + str->length;
269
  int length = _Jv_strLengthUtf8(str->data, str->length);
270
 
271
  if (length <= (int) (sizeof(buffer) / sizeof(jchar)))
272
    {
273
      jstr = NULL;
274
      chrs = buffer;
275
    }
276
  else
277
    {
278
      jstr = JvAllocString(length);
279
      chrs = JvGetStringChars(jstr);
280
    }
281
 
282
  jint hash = 0;
283
  while (data < limit)
284
    {
285
      jchar ch = UTF8_GET(data, limit);
286
      hash = (31 * hash) + ch;
287
      *chrs++ = ch;
288
    }
289
  chrs -= length;
290
 
291
  JvSynchronize sync (&java::lang::String::class$);
292
  if (3 * strhash_count >= 2 * strhash_size)
293
    rehash();
294
  jstring* ptr = _Jv_StringFindSlot (chrs, length, hash);
295
  if (*ptr != NULL && *ptr != DELETED_STRING)
296
    return (jstring) UNMASK_PTR (*ptr);
297
  strhash_count++;
298
  if (jstr == NULL)
299
    {
300
      jstr = JvAllocString(length);
301
      chrs = JvGetStringChars(jstr);
302
      memcpy (chrs, buffer, sizeof(jchar)*length);
303
    }
304
  jstr->cachedHashCode = hash;
305
  *ptr = jstr;
306
  SET_STRING_IS_INTERNED(jstr);
307
  // When string is GC'd, clear the slot in the hash table.  Note that
308
  // we don't have to call _Jv_RegisterStringFinalizer here, as we
309
  // know the new object cannot be referred to by a Reference.
310
  _Jv_RegisterFinalizer ((void *) jstr, _Jv_FinalizeString);
311
  return jstr;
312
}
313
 
314
jsize
315
_Jv_GetStringUTFLength (jstring string)
316
{
317
  jsize len = 0;
318
  jchar *ptr = JvGetStringChars (string);
319
  jsize i = string->length();
320
  while (--i >= 0)
321
    {
322
      jchar ch = *ptr++;
323
      if (ch > 0 && ch <= 0x7F)
324
        len += 1;
325
      else if (ch <= 0x7FF)
326
        len += 2;
327
      else
328
        len += 3;
329
    }
330
  return len;
331
}
332
 
333
// Not sure this quite matches GetStringUTFRegion.
334
// null-termination of result?  len?  throw exception?
335
jsize
336
_Jv_GetStringUTFRegion (jstring str, jsize start, jsize len, char *buf)
337
{
338
  jchar *sptr = JvGetStringChars (str) + start;
339
  jsize i = len;
340
  char *dptr = buf;
341
  while (--i >= 0)
342
    {
343
      jchar ch = *sptr++;
344
      if (ch > 0 && ch <= 0x7F)
345
        *dptr++ = (char) ch;
346
      else if (ch <= 0x7FF)
347
        {
348
          *dptr++ = (char) (0xC0 + ((ch >> 6) & 0x1F));
349
          *dptr++ = (char) (0x80 + (ch & 0x3F));
350
        }
351
      else
352
        {
353
          *dptr++ = (char) (0xE0 + ((ch >> 12) & 0xF));
354
          *dptr++ = (char) (0x80 + ((ch >> 6) & 0x3F));
355
          *dptr++ = (char) (0x80 + (ch & 0x3F));
356
        }
357
    }
358
  return dptr - buf;
359
}
360
 
361
/* Put printed (decimal) representation of NUM in a buffer.
362
   BUFEND marks the end of the buffer, which must be at least 11 jchars long.
363
   Returns the COUNT of jchars written.  The result is in
364
   (BUFEND - COUNT) (inclusive) upto (BUFEND) (exclusive). */
365
 
366
jint
367
_Jv_FormatInt (jchar* bufend, jint num)
368
{
369
  register jchar* ptr = bufend;
370
  jboolean isNeg;
371
  if (num < 0)
372
    {
373
      isNeg = true;
374
      num = -(num);
375
      if (num < 0)
376
        {
377
          // Must be MIN_VALUE, so handle this special case.
378
          // FIXME use 'unsigned jint' for num.
379
          *--ptr = '8';
380
          num = 214748364;
381
        }
382
      }
383
    else
384
      isNeg = false;
385
 
386
    do
387
      {
388
        *--ptr = (jchar) ((int) '0' + (num % 10));
389
        num /= 10;
390
      }
391
    while (num > 0);
392
 
393
    if (isNeg)
394
      *--ptr = '-';
395
    return bufend - ptr;
396
}
397
 
398
jstring
399
java::lang::String::valueOf (jint num)
400
{
401
  // Use an array large enough for "-2147483648"; i.e. 11 chars.
402
  jchar buffer[11];
403
  int i = _Jv_FormatInt (buffer+11, num);
404
  return _Jv_NewString (buffer+11-i, i);
405
}
406
 
407
jstring
408
_Jv_NewString(const jchar *chars, jsize len)
409
{
410
  jstring str = _Jv_AllocString(len);
411
  jchar* data = JvGetStringChars (str);
412
  while (--len >= 0)
413
    *data++ = *chars++;
414
  return str;
415
}
416
 
417
jstring
418
_Jv_NewStringLatin1(const char *bytes, jsize len)
419
{
420
  jstring str = JvAllocString(len);
421
  jchar* data = JvGetStringChars (str);
422
  while (--len >= 0)
423
    *data++ = *(unsigned char*)bytes++;
424
  return str;
425
}
426
 
427
void
428
java::lang::String::init(jcharArray chars, jint offset, jint count,
429
                         jboolean dont_copy)
430
{
431
  if (! chars)
432
    throw new NullPointerException;
433
  jsize data_size = JvGetArrayLength (chars);
434
  if (offset < 0 || count < 0 || offset + count < 0
435
      || offset + count > data_size)
436
    throw new ArrayIndexOutOfBoundsException;
437
  jcharArray array;
438
  jchar *pdst;
439
  if (! dont_copy)
440
    {
441
      array = JvNewCharArray(count);
442
      pdst = elements (array);
443
      memcpy (pdst, elements (chars) + offset, count * sizeof (jchar));
444
    }
445
  else
446
    {
447
      array = chars;
448
      pdst = &(elements(array)[offset]);
449
    }
450
 
451
  data = array;
452
  boffset = (char *) pdst - (char *) array;
453
  this->count = count;
454
}
455
 
456
void
457
java::lang::String::init(jbyteArray ascii, jint hibyte, jint offset,
458
                         jint count)
459
{
460
  if (! ascii)
461
    throw new NullPointerException;
462
  jsize data_size = JvGetArrayLength (ascii);
463
  if (offset < 0 || count < 0 || offset + count < 0
464
      || offset + count > data_size)
465
    throw new ArrayIndexOutOfBoundsException;
466
  jcharArray array = JvNewCharArray(count);
467
  jbyte *psrc = elements (ascii) + offset;
468
  jchar *pdst = elements (array);
469
  data = array;
470
  boffset = (char *) pdst - (char *) array;
471
  this->count = count;
472
  hibyte = (hibyte & 0xff) << 8;
473
  while (-- count >= 0)
474
    {
475
      *pdst++ = hibyte | (*psrc++ & 0xff);
476
    }
477
}
478
 
479
void
480
java::lang::String::init (jbyteArray bytes, jint offset, jint count,
481
                          jstring encoding)
482
{
483
  if (! bytes)
484
    throw new NullPointerException;
485
  jsize data_size = JvGetArrayLength (bytes);
486
  if (offset < 0 || count < 0 || offset + count < 0
487
      || offset + count > data_size)
488
    throw new ArrayIndexOutOfBoundsException;
489
  jcharArray array = JvNewCharArray (count);
490
  gnu::gcj::convert::BytesToUnicode *converter
491
    = gnu::gcj::convert::BytesToUnicode::getDecoder(encoding);
492
  jint outpos = 0;
493
  int avail = count;
494
  converter->setInput(bytes, offset, offset+count);
495
  while (converter->inpos < converter->inlength)
496
    {
497
      int done = converter->read(array, outpos, avail);
498
      if (done == 0)
499
        {
500
          jint new_size = 2 * (outpos + avail);
501
          jcharArray new_array = JvNewCharArray (new_size);
502
          memcpy (elements (new_array), elements (array),
503
                  outpos * sizeof(jchar));
504
          array = new_array;
505
          avail = new_size - outpos;
506
        }
507
      else
508
        {
509
          outpos += done;
510
          avail -= done;
511
        }
512
    }
513
  converter->done ();
514
  this->data = array;
515
  this->boffset = (char *) elements (array) - (char *) array;
516
  this->count = outpos;
517
}
518
 
519
void
520
java::lang::String::init (gnu::gcj::runtime::StringBuffer *buffer)
521
{
522
  init (buffer->value, 0, buffer->count, true);
523
}
524
 
525
jboolean
526
java::lang::String::equals(jobject anObject)
527
{
528
  if (anObject == NULL)
529
    return false;
530
  if (anObject == this)
531
    return true;
532
  if (anObject->getClass() != &java::lang::String::class$)
533
    return false;
534
  jstring other = (jstring) anObject;
535
  if (count != other->count)
536
    return false;
537
  /* if both are interned, return false. */
538
  jint i = count;
539
  jchar *xptr = JvGetStringChars (this);
540
  jchar *yptr = JvGetStringChars (other);
541
  while (--i >= 0)
542
    {
543
      if (*xptr++ != *yptr++)
544
        return false;
545
    }
546
  return true;
547
}
548
 
549
jboolean
550
java::lang::String::contentEquals(java::lang::StringBuffer* buffer)
551
{
552
  if (buffer == NULL)
553
    throw new NullPointerException;
554
  JvSynchronize sync(buffer);
555
  if (count != buffer->count)
556
    return false;
557
  if (data == buffer->value)
558
    return true; // Possible if shared.
559
  jint i = count;
560
  jchar *xptr = JvGetStringChars(this);
561
  jchar *yptr = elements(buffer->value);
562
  while (--i >= 0)
563
    if (*xptr++ != *yptr++)
564
      return false;
565
  return true;
566
}
567
 
568
jboolean
569
java::lang::String::contentEquals(java::lang::CharSequence *seq)
570
{
571
  if (seq->length() != count)
572
    return false;
573
  jchar *value = JvGetStringChars(this);
574
  for (int i = 0; i < count; ++i)
575
    if (value[i] != seq->charAt(i))
576
      return false;
577
  return true;
578
}
579
 
580
jchar
581
java::lang::String::charAt(jint i)
582
{
583
  if (i < 0 || i >= count)
584
    throw new java::lang::StringIndexOutOfBoundsException(i);
585
  return JvGetStringChars(this)[i];
586
}
587
 
588
void
589
java::lang::String::getChars(jint srcBegin, jint srcEnd,
590
                             jcharArray dst, jint dstBegin)
591
{
592
  jint dst_length = JvGetArrayLength (dst);
593
  if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count)
594
    throw new java::lang::StringIndexOutOfBoundsException;
595
  // The 2nd part of the test below is equivalent to 
596
  // dstBegin + (srcEnd-srcBegin) > dst_length
597
  // except that it does not overflow.
598
  if (dstBegin < 0 || dstBegin > dst_length - (srcEnd-srcBegin))
599
    throw new ArrayIndexOutOfBoundsException;
600
  jchar *dPtr = elements (dst) + dstBegin;
601
  jchar *sPtr = JvGetStringChars (this) + srcBegin;
602
  jint i = srcEnd-srcBegin;
603
  while (--i >= 0)
604
    *dPtr++ = *sPtr++;
605
}
606
 
607
jbyteArray
608
java::lang::String::getBytes (jstring enc)
609
{
610
  jint todo = length();
611
  jint buflen = todo;
612
  jbyteArray buffer = JvNewByteArray(todo);
613
  jint bufpos = 0;
614
  jint offset = 0;
615
  gnu::gcj::convert::UnicodeToBytes *converter
616
    = gnu::gcj::convert::UnicodeToBytes::getEncoder(enc);
617
  while (todo > 0 || converter->havePendingBytes())
618
    {
619
      converter->setOutput(buffer, bufpos);
620
      int converted = converter->write(this, offset, todo, NULL);
621
      bufpos = converter->count;
622
      if (converted == 0 && bufpos == converter->count)
623
        {
624
          buflen *= 2;
625
          jbyteArray newbuffer = JvNewByteArray(buflen);
626
          memcpy (elements (newbuffer), elements (buffer), bufpos);
627
          buffer = newbuffer;
628
        }
629
      else
630
        bufpos = converter->count;
631
 
632
      offset += converted;
633
      todo -= converted;
634
    }
635
  converter->done ();
636
  if (bufpos == buflen)
637
    return buffer;
638
  jbyteArray result = JvNewByteArray(bufpos);
639
  memcpy (elements (result), elements (buffer), bufpos);
640
  return result;
641
}
642
 
643
void
644
java::lang::String::getBytes(jint srcBegin, jint srcEnd,
645
                             jbyteArray dst, jint dstBegin)
646
{
647
  jint dst_length = JvGetArrayLength (dst);
648
  if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count)
649
    throw new java::lang::StringIndexOutOfBoundsException;
650
  // The 2nd part of the test below is equivalent to 
651
  // dstBegin + (srcEnd-srcBegin) > dst_length
652
  // except that it does not overflow.
653
  if (dstBegin < 0 || dstBegin > dst_length - (srcEnd-srcBegin))
654
    throw new ArrayIndexOutOfBoundsException;
655
  jbyte *dPtr = elements (dst) + dstBegin;
656
  jchar *sPtr = JvGetStringChars (this) + srcBegin;
657
  jint i = srcEnd-srcBegin;
658
  while (--i >= 0)
659
    *dPtr++ = (jbyte) *sPtr++;
660
}
661
 
662
jcharArray
663
java::lang::String::toCharArray()
664
{
665
  jcharArray array = JvNewCharArray(count);
666
  jchar *dPtr = elements (array);
667
  jchar *sPtr = JvGetStringChars (this);
668
  jint i = count;
669
  while (--i >= 0)
670
    *dPtr++ = *sPtr++;
671
  return array;
672
}
673
 
674
jboolean
675
java::lang::String::equalsIgnoreCase (jstring anotherString)
676
{
677
  if (anotherString == NULL || count != anotherString->count)
678
    return false;
679
  jchar *tptr = JvGetStringChars (this);
680
  jchar *optr = JvGetStringChars (anotherString);
681
  jint i = count;
682
  while (--i >= 0)
683
    {
684
      jchar tch = *tptr++;
685
      jchar och = *optr++;
686
      if (tch != och
687
          && (java::lang::Character::toLowerCase (tch)
688
              != java::lang::Character::toLowerCase (och))
689
          && (java::lang::Character::toUpperCase (tch)
690
              != java::lang::Character::toUpperCase (och)))
691
        return false;
692
    }
693
  return true;
694
}
695
 
696
jboolean
697
java::lang::String::regionMatches (jint toffset,
698
                                   jstring other, jint ooffset, jint len)
699
{
700
  if (toffset < 0 || ooffset < 0 || len < 0
701
      || toffset > count - len
702
      || ooffset > other->count - len)
703
    return false;
704
  jchar *tptr = JvGetStringChars (this) + toffset;
705
  jchar *optr = JvGetStringChars (other) + ooffset;
706
  jint i = len;
707
  while (--i >= 0)
708
    {
709
      if (*tptr++ != *optr++)
710
        return false;
711
    }
712
  return true;
713
}
714
 
715
jint
716
java::lang::String::compareTo (jstring anotherString)
717
{
718
  jchar *tptr = JvGetStringChars (this);
719
  jchar *optr = JvGetStringChars (anotherString);
720
  jint tlen = this->count;
721
  jint olen = anotherString->count;
722
  jint i = tlen > olen ? olen : tlen;
723
  while (--i >= 0)
724
    {
725
      jchar tch = *tptr++;
726
      jchar och = *optr++;
727
      if (tch != och)
728
        return (jint) tch - (jint) och;
729
    }
730
  return tlen - olen;
731
}
732
 
733
jboolean
734
java::lang::String::regionMatches (jboolean ignoreCase, jint toffset,
735
                                   jstring other, jint ooffset, jint len)
736
{
737
  if (toffset < 0 || ooffset < 0 || len < 0
738
      || toffset > count - len
739
      || ooffset > other->count - len)
740
    return false;
741
  jchar *tptr = JvGetStringChars (this) + toffset;
742
  jchar *optr = JvGetStringChars (other) + ooffset;
743
  jint i = len;
744
  if (ignoreCase)
745
    while (--i >= 0)
746
      {
747
        jchar tch = *tptr++;
748
        jchar och = *optr++;
749
        if ((java::lang::Character::toLowerCase (tch)
750
             != java::lang::Character::toLowerCase (och))
751
            && (java::lang::Character::toUpperCase (tch)
752
                != java::lang::Character::toUpperCase (och)))
753
          return false;
754
      }
755
  else
756
    while (--i >= 0)
757
      {
758
        jchar tch = *tptr++;
759
        jchar och = *optr++;
760
        if (tch != och)
761
          return false;
762
      }
763
  return true;
764
}
765
 
766
jboolean
767
java::lang::String::startsWith (jstring prefix, jint toffset)
768
{
769
  jint i = prefix->count;
770
  if (toffset < 0 || toffset > count - i)
771
    return false;
772
  jchar *xptr = JvGetStringChars (this) + toffset;
773
  jchar *yptr = JvGetStringChars (prefix);
774
  while (--i >= 0)
775
    {
776
      if (*xptr++ != *yptr++)
777
        return false;
778
    }
779
  return true;
780
}
781
 
782
jint
783
java::lang::String::indexOf (jint ch, jint fromIndex)
784
{
785
  if (fromIndex < 0)
786
    fromIndex = 0;
787
  jchar *ptr = JvGetStringChars(this);
788
  for (;; ++fromIndex)
789
    {
790
      if (fromIndex >= count)
791
        return -1;
792
      if (ptr[fromIndex] == ch)
793
        return fromIndex;
794
    }
795
}
796
 
797
jint
798
java::lang::String::indexOf (jstring s, jint fromIndex)
799
{
800
  const jchar *const xchars = JvGetStringChars(s);
801
  const jchar *const ychars = JvGetStringChars(this) + fromIndex;
802
 
803
  const int xlength = s->length ();
804
  const int ylength = length () - fromIndex;
805
 
806
  int i = 0;
807
  int j = 0;
808
 
809
  while (i < ylength && j < xlength)
810
    {
811
      if (xchars[j] != ychars[i])
812
        {
813
          i = i - j + 1;
814
          j = 0;
815
        }
816
      else
817
        i++, j++;
818
    }
819
 
820
  if (j >= xlength)
821
    return fromIndex + i - xlength;
822
  else
823
    return -1;
824
}
825
 
826
jint
827
java::lang::String::lastIndexOf (jint ch, jint fromIndex)
828
{
829
  if (fromIndex >= count)
830
    fromIndex = count - 1;
831
  jchar *ptr = JvGetStringChars(this);
832
  for (;; --fromIndex)
833
    {
834
      if (fromIndex < 0)
835
        return -1;
836
      if (ptr[fromIndex] == ch)
837
        return fromIndex;
838
    }
839
}
840
 
841
jstring
842
java::lang::String::substring (jint beginIndex, jint endIndex)
843
{
844
  if (beginIndex < 0 || endIndex > count || beginIndex > endIndex)
845
    throw new StringIndexOutOfBoundsException;
846
  if (beginIndex == 0 && endIndex == count)
847
    return this;
848
  jint newCount = endIndex - beginIndex;
849
  // For very small strings, just allocate a new one.  For other
850
  // substrings, allocate a new one unless the substring is over half
851
  // of the original string.
852
  if (newCount <= 8 || newCount < (count >> 1))
853
    return JvNewString(JvGetStringChars(this) + beginIndex, newCount);
854
  jstring s = new String();
855
  s->data = data;
856
  s->count = newCount;
857
  s->boffset = boffset + sizeof(jchar) * beginIndex;
858
  return s;
859
}
860
 
861
jstring
862
java::lang::String::concat(jstring str)
863
{
864
  jint str_count = str->count;
865
  if (str_count == 0)
866
    return this;
867
  jstring result = JvAllocString(count + str_count);
868
  jchar *dstPtr = JvGetStringChars(result);
869
  jchar *srcPtr = JvGetStringChars(this);
870
  jint i = count;
871
  while (--i >= 0)
872
    *dstPtr++ = *srcPtr++;
873
  srcPtr = JvGetStringChars(str);
874
  i = str->count;
875
  while (--i >= 0)
876
    *dstPtr++ = *srcPtr++;
877
  return result;
878
}
879
 
880
jstring
881
java::lang::String::replace (jchar oldChar, jchar newChar)
882
{
883
  jint i;
884
  jchar* chrs = JvGetStringChars (this);
885
  for (i = 0;  ;  i++)
886
    {
887
      if (i == count)
888
        return this;
889
      if (chrs[i] == oldChar)
890
        break;
891
    }
892
  jstring result = JvAllocString (count);
893
  jchar *dPtr = JvGetStringChars (result);
894
  for (int j = 0;  j < i;  j++)
895
    *dPtr++ = chrs[j];
896
  for (; i < count;  i++)
897
    {
898
      jchar ch = chrs[i];
899
      if (ch == oldChar)
900
        ch = newChar;
901
      *dPtr++ = ch;
902
    }
903
  return result;
904
}
905
 
906
jstring
907
java::lang::String::toLowerCase (java::util::Locale *locale)
908
{
909
  jint i;
910
  jchar* chrs = JvGetStringChars(this);
911
  jchar ch = 0;
912
 
913
  bool handle_tr = false;
914
  if (locale != NULL)
915
    {
916
      String *lang = locale->getLanguage ();
917
      if (lang->length () == 2
918
          && lang->charAt (0) == 't'
919
          && lang->charAt (1) == 'r')
920
        handle_tr = true;
921
    }
922
 
923
  for (i = 0;  ;  i++)
924
    {
925
      if (i == count)
926
        return this;
927
      jchar origChar = chrs[i];
928
 
929
      if (handle_tr && (origChar == CAPITAL_I
930
                        || origChar == CAPITAL_I_WITH_DOT))
931
        break;
932
 
933
      ch = java::lang::Character::toLowerCase(origChar);
934
      if (ch != origChar)
935
        break;
936
    }
937
  jstring result = JvAllocString(count);
938
  jchar *dPtr = JvGetStringChars (result);
939
  for (int j = 0;  j < i;  j++)
940
    *dPtr++ = chrs[j];
941
  *dPtr++ = ch;  i++;
942
  for (; i < count;  i++)
943
    {
944
      if (handle_tr && chrs[i] == CAPITAL_I)
945
        *dPtr++ = SMALL_DOTLESS_I;
946
      else if (handle_tr && chrs[i] == CAPITAL_I_WITH_DOT)
947
        *dPtr++ = SMALL_I;
948
      else
949
        *dPtr++ = java::lang::Character::toLowerCase(chrs[i]);
950
    }
951
  return result;
952
}
953
 
954
jstring
955
java::lang::String::toUpperCase (java::util::Locale *locale)
956
{
957
  jint i;
958
  jchar* chrs = JvGetStringChars(this);
959
  jchar ch;
960
 
961
  // When handling a specific locale there might be special rules.
962
  // Currently all existing rules are simply handled inline, as there
963
  // are only two and they are documented in the online 1.2 docs.
964
  bool handle_esset = locale != NULL;
965
  bool handle_tr = false;
966
  if (locale != NULL)
967
    {
968
      String *lang = locale->getLanguage ();
969
      if (lang->length () == 2
970
          && lang->charAt (0) == 't'
971
          && lang->charAt (1) == 'r')
972
        handle_tr = true;
973
    }
974
 
975
  int new_count = count;
976
  bool new_string = false;
977
  for (i = 0;  ;  i++)
978
    {
979
      if (i == count)
980
        break;
981
      jchar origChar = chrs[i];
982
 
983
      if (handle_esset && origChar == ESSET)
984
        {
985
          ++new_count;
986
          new_string = true;
987
        }
988
      else if (handle_tr && (origChar == SMALL_I
989
                             || origChar == SMALL_DOTLESS_I))
990
        new_string = true;
991
      else
992
        {
993
          ch = java::lang::Character::toUpperCase(origChar);
994
          if (ch != origChar)
995
            new_string = true;
996
        }
997
 
998
      if (new_string && ! handle_esset)
999
        break;
1000
    }
1001
  if (! new_string)
1002
    return this;
1003
  jstring result = JvAllocString(new_count);
1004
  jchar *dPtr = JvGetStringChars (result);
1005
  for (i = 0; i < count;  i++)
1006
    {
1007
      if (handle_esset && chrs[i] == ESSET)
1008
        {
1009
          *dPtr++ = CAPITAL_S;
1010
          *dPtr++ = CAPITAL_S;
1011
        }
1012
      else if (handle_tr && chrs[i] == SMALL_I)
1013
        *dPtr++ = CAPITAL_I_WITH_DOT;
1014
      else if (handle_tr && chrs[i] == SMALL_DOTLESS_I)
1015
        *dPtr++ = CAPITAL_I;
1016
      else
1017
        *dPtr++ = java::lang::Character::toUpperCase(chrs[i]);
1018
    }
1019
  return result;
1020
}
1021
 
1022
jstring
1023
java::lang::String::trim ()
1024
{
1025
  jchar* chrs = JvGetStringChars(this);
1026
  if (count == 0 || (chrs[0] > ' ' && chrs[count-1] > ' '))
1027
    return this;
1028
  jint preTrim = 0;
1029
  for (;; preTrim++)
1030
    {
1031
      if (preTrim == count)
1032
        return new String();
1033
      if (chrs[preTrim] > ' ')
1034
        break;
1035
    }
1036
  jint endTrim = count;
1037
  while (chrs[endTrim-1] <= ' ')
1038
    endTrim--;
1039
  return substring(preTrim, endTrim);
1040
}
1041
 
1042
jstring
1043
java::lang::String::valueOf(jcharArray data, jint offset, jint count)
1044
{
1045
  jint data_length = JvGetArrayLength (data);
1046
  if (offset < 0 || count < 0 || offset > data_length - count)
1047
    throw new ArrayIndexOutOfBoundsException;
1048
  jstring result = JvAllocString(count);
1049
  jchar *sPtr = elements (data) + offset;
1050
  jchar *dPtr = JvGetStringChars(result);
1051
  while (--count >= 0)
1052
    *dPtr++ = *sPtr++;
1053
  return result;
1054
}
1055
 
1056
jstring
1057
java::lang::String::valueOf(jchar c)
1058
{
1059
  jstring result = JvAllocString(1);
1060
  JvGetStringChars (result)[0] = c;
1061
  return result;
1062
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.