1 /* src/vm/string.c - java.lang.String related functions
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
31 Changes: Christian Thalinger
33 $Id: string.c 3581 2005-11-05 19:44:38Z twisti $
43 #include "vm/global.h"
45 #include "mm/memory.h"
46 #include "native/include/java_lang_String.h"
47 #include "vm/exceptions.h"
48 #include "vm/loader.h"
49 #include "vm/options.h"
50 #include "vm/stringlocal.h"
54 /* global string definitions **************************************************/
56 /* exception/error super class */
58 const char *string_java_lang_Throwable =
59 "java/lang/Throwable";
61 const char *string_java_lang_VMThrowable =
62 "java/lang/VMThrowable";
65 /* specify some exception strings for code generation */
67 const char *string_java_lang_ArithmeticException =
68 "java/lang/ArithmeticException";
70 const char *string_java_lang_ArithmeticException_message =
73 const char *string_java_lang_ArrayIndexOutOfBoundsException =
74 "java/lang/ArrayIndexOutOfBoundsException";
76 const char *string_java_lang_ArrayStoreException =
77 "java/lang/ArrayStoreException";
79 const char *string_java_lang_ClassCastException =
80 "java/lang/ClassCastException";
82 const char *string_java_lang_ClassNotFoundException =
83 "java/lang/ClassNotFoundException";
85 const char *string_java_lang_CloneNotSupportedException =
86 "java/lang/CloneNotSupportedException";
88 const char *string_java_lang_Exception =
89 "java/lang/Exception";
91 const char *string_java_lang_IllegalAccessException =
92 "java/lang/IllegalAccessException";
94 const char *string_java_lang_IllegalArgumentException =
95 "java/lang/IllegalArgumentException";
97 const char *string_java_lang_IllegalMonitorStateException =
98 "java/lang/IllegalMonitorStateException";
100 const char *string_java_lang_IndexOutOfBoundsException =
101 "java/lang/IndexOutOfBoundsException";
103 const char *string_java_lang_InstantiationException =
104 "java/lang/InstantiationException";
106 const char *string_java_lang_InterruptedException =
107 "java/lang/InterruptedException";
109 const char *string_java_lang_NegativeArraySizeException =
110 "java/lang/NegativeArraySizeException";
112 const char *string_java_lang_NoSuchFieldException =
113 "java/lang/NoSuchFieldException";
115 const char *string_java_lang_NoSuchMethodException =
116 "java/lang/NoSuchMethodException";
118 const char *string_java_lang_NullPointerException =
119 "java/lang/NullPointerException";
121 const char *string_java_lang_reflect_InvocationTargetException =
122 "java/lang/reflect/InvocationTargetException";
125 /* specify some error strings for code generation */
127 const char *string_java_lang_AbstractMethodError =
128 "java/lang/AbstractMethodError";
130 const char *string_java_lang_ClassCircularityError =
131 "java/lang/ClassCircularityError";
133 const char *string_java_lang_ClassFormatError =
134 "java/lang/ClassFormatError";
136 const char *string_java_lang_Error =
139 const char *string_java_lang_ExceptionInInitializerError =
140 "java/lang/ExceptionInInitializerError";
142 const char *string_java_lang_IncompatibleClassChangeError =
143 "java/lang/IncompatibleClassChangeError";
145 const char *string_java_lang_InstantiationError =
146 "java/lang/InstantiationError";
148 const char *string_java_lang_InternalError =
149 "java/lang/InternalError";
151 const char *string_java_lang_LinkageError =
152 "java/lang/LinkageError";
154 const char *string_java_lang_NoClassDefFoundError =
155 "java/lang/NoClassDefFoundError";
157 const char *string_java_lang_NoSuchFieldError =
158 "java/lang/NoSuchFieldError";
160 const char *string_java_lang_NoSuchMethodError =
161 "java/lang/NoSuchMethodError";
163 const char *string_java_lang_OutOfMemoryError =
164 "java/lang/OutOfMemoryError";
166 const char *string_java_lang_UnsatisfiedLinkError =
167 "java/lang/UnsatisfiedLinkError";
169 const char *string_java_lang_UnsupportedClassVersionError =
170 "java/lang/UnsupportedClassVersionError";
172 const char *string_java_lang_VerifyError =
173 "java/lang/VerifyError";
175 const char *string_java_lang_VirtualMachineError =
176 "java/lang/VirtualMachineError";
179 /* stringtable_update **********************************************************
181 Traverses the javastring hashtable and sets the vftbl-entries of
182 javastrings which were temporarily set to NULL, because
183 java.lang.Object was not yet loaded.
185 *******************************************************************************/
187 void stringtable_update(void)
189 java_lang_String *js;
191 literalstring *s; /* hashtable entry */
194 for (i = 0; i < string_hash.size; i++) {
195 s = string_hash.ptr[i];
199 js = (java_lang_String *) s->string;
201 if (!js || !js->value) {
202 /* error in hashtable found */
203 log_text("invalid literalstring in hashtable");
209 if (!js->header.vftbl)
210 /* vftbl of javastring is NULL */
211 js->header.vftbl = class_java_lang_String->vftbl;
213 if (!a->header.objheader.vftbl)
214 /* vftbl of character-array is NULL */
215 a->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
217 /* follow link in external hash chain */
225 /* javastring_new **************************************************************
227 creates a new object of type java/lang/String with the text of
228 the specified utf8-string
230 return: pointer to the string or NULL if memory is exhausted.
232 *******************************************************************************/
234 java_lang_String *javastring_new(utf *u)
236 char *utf_ptr; /* current utf character in utf string */
237 u4 utflength; /* length of utf-string if uncompressed */
238 java_lang_String *s; /* result-string */
243 *exceptionptr = new_nullpointerexception();
248 utflength = utf_strlen(u);
250 s = (java_lang_String *) builtin_new(class_java_lang_String);
251 a = builtin_newarray_char(utflength);
253 /* javastring or character-array could not be created */
257 /* decompress utf-string */
258 for (i = 0; i < utflength; i++)
259 a->data[i] = utf_nextu2(&utf_ptr);
261 /* set fields of the javastring-object */
264 s->count = utflength;
269 /* javastring_new_slash_to_dot *************************************************
271 creates a new object of type java/lang/String with the text of
272 the specified utf8-string with slashes changed to dots
274 return: pointer to the string or NULL if memory is exhausted.
276 *******************************************************************************/
278 java_lang_String *javastring_new_slash_to_dot(utf *u)
280 char *utf_ptr; /* current utf character in utf string */
281 u4 utflength; /* length of utf-string if uncompressed */
282 java_lang_String *s; /* result-string */
288 *exceptionptr = new_nullpointerexception();
293 utflength = utf_strlen(u);
295 s = (java_lang_String *) builtin_new(class_java_lang_String);
296 a = builtin_newarray_char(utflength);
298 /* javastring or character-array could not be created */
302 /* decompress utf-string */
303 for (i = 0; i < utflength; i++) {
304 ch = utf_nextu2(&utf_ptr);
310 /* set fields of the javastring-object */
313 s->count = utflength;
319 /* javastring_new_char *********************************************************
321 creates a new java/lang/String object which contains the convertet
322 C-string passed via text.
324 return: the object pointer or NULL if memory is exhausted.
326 *******************************************************************************/
328 java_lang_String *javastring_new_char(const char *text)
331 s4 len; /* length of the string */
332 java_lang_String *s; /* result-string */
336 *exceptionptr = new_nullpointerexception();
342 s = (java_lang_String *) builtin_new(class_java_lang_String);
343 a = builtin_newarray_char(len);
345 /* javastring or character-array could not be created */
350 for (i = 0; i < len; i++)
351 a->data[i] = text[i];
353 /* set fields of the javastring-object */
362 /* javastring_tochar ***********************************************************
364 converts a Java string into a C string.
366 return: pointer to C string
368 Caution: calling method MUST release the allocated memory!
370 *******************************************************************************/
372 char *javastring_tochar(java_objectheader *so)
374 java_lang_String *s = (java_lang_String *) so;
387 buf = MNEW(char, s->count + 1);
389 for (i = 0; i < s->count; i++)
390 buf[i] = a->data[s->offset + i];
398 /* javastring_toutf ************************************************************
400 Make utf symbol from javastring.
402 *******************************************************************************/
404 utf *javastring_toutf(java_lang_String *string, bool isclassname)
406 java_lang_String *str = (java_lang_String *) string;
408 return utf_new_u2(str->value->data + str->offset, str->count, isclassname);
412 /* javastring_strlen ***********************************************************
414 Returns the length of the Java string.
416 *******************************************************************************/
418 s4 javastring_strlen(java_objectheader *so)
420 java_lang_String *s = (java_lang_String *) so;
429 /* literalstring_u2 ************************************************************
431 Searches for the javastring with the specified u2-array in the
432 string hashtable, if there is no such string a new one is created.
434 If copymode is true a copy of the u2-array is made.
436 *******************************************************************************/
438 java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
441 literalstring *s; /* hashtable element */
442 java_lang_String *js; /* u2-array wrapped in javastring */
443 java_chararray *stringdata; /* copy of u2-array */
448 /* find location in hashtable */
449 key = unicode_hashkey(a->data + offset, length);
450 slot = key & (string_hash.size - 1);
451 s = string_hash.ptr[slot];
454 js = (java_lang_String *) s->string;
456 if (length == js->count) {
458 for (i = 0; i < length; i++) {
459 if (a->data[offset + i] != js->value->data[i])
463 /* string already in hashtable, free memory */
465 mem_free(a, sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10);
467 return (java_objectheader *) js;
471 /* follow link in external hash chain */
476 /* create copy of u2-array for new javastring */
477 u4 arraysize = sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10;
478 stringdata = mem_alloc(arraysize);
479 /* memcpy(stringdata, a, arraysize); */
480 memcpy(&(stringdata->header), &(a->header), sizeof(java_arrayheader));
481 memcpy(&(stringdata->data), &(a->data) + offset, sizeof(u2) * (length - 1) + 10);
487 /* location in hashtable found, complete arrayheader */
489 stringdata->header.objheader.vftbl =
490 primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
491 stringdata->header.size = length;
493 /* XXX TWISTI: is this necessary? */
494 if (!class_java_lang_String)
495 class_java_lang_String = load_class_bootstrap(utf_java_lang_String);
497 assert(class_java_lang_String);
498 assert(class_java_lang_String->loaded);
500 /* if we use eager loading, we have to check loaded String class */
503 list_addfirst(&unlinkedclasses, class_java_lang_String);
505 /* create new javastring */
507 js = NEW(java_lang_String);
509 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
510 initObjectLock(&js->header);
513 js->header.vftbl = class_java_lang_String->vftbl;
514 js->value = stringdata;
518 /* create new literalstring */
520 s = NEW(literalstring);
521 s->hashlink = string_hash.ptr[slot];
522 s->string = (java_objectheader *) js;
523 string_hash.ptr[slot] = s;
525 /* update number of hashtable entries */
527 string_hash.entries++;
529 /* reorganization of hashtable */
531 if (string_hash.entries > (string_hash.size * 2)) {
532 /* reorganization of hashtable, average length of the external
533 chains is approx. 2 */
537 literalstring *nexts;
538 java_lang_String *tmpjs;
539 hashtable newhash; /* the new hashtable */
541 /* create new hashtable, double the size */
543 init_hashtable(&newhash, string_hash.size * 2);
544 newhash.entries = string_hash.entries;
546 /* transfer elements to new hashtable */
548 for (i = 0; i < string_hash.size; i++) {
549 s = string_hash.ptr[i];
553 tmpjs = (java_lang_String *) s->string;
554 slot = unicode_hashkey(tmpjs->value->data, tmpjs->count) & (newhash.size - 1);
556 s->hashlink = newhash.ptr[slot];
557 newhash.ptr[slot] = s;
559 /* follow link in external hash chain */
564 /* dispose old table */
566 MFREE(string_hash.ptr, void*, string_hash.size);
567 string_hash = newhash;
570 return (java_objectheader *) js;
574 /* literalstring_new ***********************************************************
576 Creates a new javastring with the text of the utf-symbol and inserts it into
577 the string hashtable.
579 *******************************************************************************/
581 java_objectheader *literalstring_new(utf *u)
583 char *utf_ptr; /* pointer to current unicode character */
585 u4 utflength; /* length of utf-string if uncompressed */
586 java_chararray *a; /* u2-array constructed from utf string */
590 utflength = utf_strlen(u);
592 /* allocate memory */
593 a = mem_alloc(sizeof(java_chararray) + sizeof(u2) * (utflength - 1) + 10);
595 /* convert utf-string to u2-array */
596 for (i = 0; i < utflength; i++)
597 a->data[i] = utf_nextu2(&utf_ptr);
599 return literalstring_u2(a, utflength, 0, false);
603 /* literalstring_free **********************************************************
605 Removes a javastring from memory.
607 *******************************************************************************/
609 void literalstring_free(java_objectheader* sobj)
614 s = (java_lang_String *) sobj;
617 /* dispose memory of java.lang.String object */
618 FREE(s, java_lang_String);
620 /* dispose memory of java-characterarray */
621 FREE(a, sizeof(java_chararray) + sizeof(u2) * (a->header.size - 1)); /* +10 ?? */
626 * These are local overrides for various environment variables in Emacs.
627 * Please do not remove this and leave it at the end of the file, where
628 * Emacs will automagically detect them.
629 * ---------------------------------------------------------------------
632 * indent-tabs-mode: t