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 2458 2005-05-12 23:02:07Z twisti $
42 #include "vm/global.h"
44 #include "mm/memory.h"
45 #include "native/include/java_lang_String.h"
46 #include "vm/exceptions.h"
47 #include "vm/loader.h"
48 #include "vm/options.h"
49 #include "vm/stringlocal.h"
53 /* global string definitions **************************************************/
55 /* exception/error super class */
57 const char *string_java_lang_Throwable =
58 "java/lang/Throwable";
60 const char *string_java_lang_VMThrowable =
61 "java/lang/VMThrowable";
64 /* specify some exception strings for code generation */
66 const char *string_java_lang_ArithmeticException =
67 "java/lang/ArithmeticException";
69 const char *string_java_lang_ArithmeticException_message =
72 const char *string_java_lang_ArrayIndexOutOfBoundsException =
73 "java/lang/ArrayIndexOutOfBoundsException";
75 const char *string_java_lang_ArrayStoreException =
76 "java/lang/ArrayStoreException";
78 const char *string_java_lang_ClassCastException =
79 "java/lang/ClassCastException";
81 const char *string_java_lang_ClassNotFoundException =
82 "java/lang/ClassNotFoundException";
84 const char *string_java_lang_CloneNotSupportedException =
85 "java/lang/CloneNotSupportedException";
87 const char *string_java_lang_Exception =
88 "java/lang/Exception";
90 const char *string_java_lang_IllegalAccessException =
91 "java/lang/IllegalAccessException";
93 const char *string_java_lang_IllegalArgumentException =
94 "java/lang/IllegalArgumentException";
96 const char *string_java_lang_IllegalMonitorStateException =
97 "java/lang/IllegalMonitorStateException";
99 const char *string_java_lang_IndexOutOfBoundsException =
100 "java/lang/IndexOutOfBoundsException";
102 const char *string_java_lang_InstantiationException =
103 "java/lang/InstantiationException";
105 const char *string_java_lang_InterruptedException =
106 "java/lang/InterruptedException";
108 const char *string_java_lang_NegativeArraySizeException =
109 "java/lang/NegativeArraySizeException";
111 const char *string_java_lang_NoSuchFieldException =
112 "java/lang/NoSuchFieldException";
114 const char *string_java_lang_NoSuchMethodException =
115 "java/lang/NoSuchMethodException";
117 const char *string_java_lang_NullPointerException =
118 "java/lang/NullPointerException";
121 /* specify some error strings for code generation */
123 const char *string_java_lang_AbstractMethodError =
124 "java/lang/AbstractMethodError";
126 const char *string_java_lang_ClassCircularityError =
127 "java/lang/ClassCircularityError";
129 const char *string_java_lang_ClassFormatError =
130 "java/lang/ClassFormatError";
132 const char *string_java_lang_Error =
135 const char *string_java_lang_ExceptionInInitializerError =
136 "java/lang/ExceptionInInitializerError";
138 const char *string_java_lang_IncompatibleClassChangeError =
139 "java/lang/IncompatibleClassChangeError";
141 const char *string_java_lang_InternalError =
142 "java/lang/InternalError";
144 const char *string_java_lang_LinkageError =
145 "java/lang/LinkageError";
147 const char *string_java_lang_NoClassDefFoundError =
148 "java/lang/NoClassDefFoundError";
150 const char *string_java_lang_NoSuchFieldError =
151 "java/lang/NoSuchFieldError";
153 const char *string_java_lang_NoSuchMethodError =
154 "java/lang/NoSuchMethodError";
156 const char *string_java_lang_OutOfMemoryError =
157 "java/lang/OutOfMemoryError";
159 const char *string_java_lang_UnsupportedClassVersionError =
160 "java/lang/UnsupportedClassVersionError";
162 const char *string_java_lang_VerifyError =
163 "java/lang/VerifyError";
165 const char *string_java_lang_VirtualMachineError =
166 "java/lang/VirtualMachineError";
169 /* stringtable_update **********************************************************
171 Traverses the javastring hashtable and sets the vftbl-entries of
172 javastrings which were temporarily set to NULL, because
173 java.lang.Object was not yet loaded.
175 *******************************************************************************/
177 void stringtable_update(void)
179 java_lang_String *js;
181 literalstring *s; /* hashtable entry */
184 for (i = 0; i < string_hash.size; i++) {
185 s = string_hash.ptr[i];
189 js = (java_lang_String *) s->string;
191 if (!js || !js->value)
192 /* error in hashtable found */
193 panic("invalid literalstring in hashtable");
197 if (!js->header.vftbl)
198 /* vftbl of javastring is NULL */
199 js->header.vftbl = class_java_lang_String->vftbl;
201 if (!a->header.objheader.vftbl)
202 /* vftbl of character-array is NULL */
203 a->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
205 /* follow link in external hash chain */
213 /* javastring_new **************************************************************
215 creates a new object of type java/lang/String with the text of
216 the specified utf8-string
218 return: pointer to the string or NULL if memory is exhausted.
220 *******************************************************************************/
222 java_lang_String *javastring_new(utf *u)
224 char *utf_ptr; /* current utf character in utf string */
225 u4 utflength; /* length of utf-string if uncompressed */
226 java_lang_String *s; /* result-string */
231 *exceptionptr = new_nullpointerexception();
236 utflength = utf_strlen(u);
238 s = (java_lang_String *) builtin_new(class_java_lang_String);
239 a = builtin_newarray_char(utflength);
241 /* javastring or character-array could not be created */
245 /* decompress utf-string */
246 for (i = 0; i < utflength; i++)
247 a->data[i] = utf_nextu2(&utf_ptr);
249 /* set fields of the javastring-object */
252 s->count = utflength;
257 /* javastring_new_slash_to_dot *************************************************
259 creates a new object of type java/lang/String with the text of
260 the specified utf8-string with slashes changed to dots
262 return: pointer to the string or NULL if memory is exhausted.
264 *******************************************************************************/
266 java_lang_String *javastring_new_slash_to_dot(utf *u)
268 char *utf_ptr; /* current utf character in utf string */
269 u4 utflength; /* length of utf-string if uncompressed */
270 java_lang_String *s; /* result-string */
276 *exceptionptr = new_nullpointerexception();
281 utflength = utf_strlen(u);
283 s = (java_lang_String *) builtin_new(class_java_lang_String);
284 a = builtin_newarray_char(utflength);
286 /* javastring or character-array could not be created */
290 /* decompress utf-string */
291 for (i = 0; i < utflength; i++) {
292 ch = utf_nextu2(&utf_ptr);
298 /* set fields of the javastring-object */
301 s->count = utflength;
307 /* javastring_new_char *********************************************************
309 creates a new java/lang/String object which contains the convertet
310 C-string passed via text.
312 return: the object pointer or NULL if memory is exhausted.
314 *******************************************************************************/
316 java_lang_String *javastring_new_char(const char *text)
319 s4 len; /* length of the string */
320 java_lang_String *s; /* result-string */
324 *exceptionptr = new_nullpointerexception();
330 s = (java_lang_String *) builtin_new(class_java_lang_String);
331 a = builtin_newarray_char(len);
333 /* javastring or character-array could not be created */
338 for (i = 0; i < len; i++)
339 a->data[i] = text[i];
341 /* set fields of the javastring-object */
350 /* javastring_tochar ***********************************************************
352 converts a Java string into a C string.
354 return: pointer to C string
356 Caution: calling method MUST release the allocated memory!
358 *******************************************************************************/
360 char *javastring_tochar(java_objectheader *so)
362 java_lang_String *s = (java_lang_String *) so;
375 buf = MNEW(char, s->count + 1);
377 for (i = 0; i < s->count; i++)
378 buf[i] = a->data[s->offset + i];
386 /* javastring_toutf ************************************************************
388 Make utf symbol from javastring.
390 *******************************************************************************/
392 utf *javastring_toutf(java_lang_String *string, bool isclassname)
394 java_lang_String *str = (java_lang_String *) string;
396 return utf_new_u2(str->value->data + str->offset, str->count, isclassname);
400 /* literalstring_u2 ************************************************************
402 Searches for the javastring with the specified u2-array in the
403 string hashtable, if there is no such string a new one is created.
405 If copymode is true a copy of the u2-array is made.
407 *******************************************************************************/
409 java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
412 literalstring *s; /* hashtable element */
413 java_lang_String *js; /* u2-array wrapped in javastring */
414 java_chararray *stringdata; /* copy of u2-array */
419 /* find location in hashtable */
420 key = unicode_hashkey(a->data + offset, length);
421 slot = key & (string_hash.size - 1);
422 s = string_hash.ptr[slot];
425 js = (java_lang_String *) s->string;
427 if (length == js->count) {
429 for (i = 0; i < length; i++) {
430 if (a->data[offset + i] != js->value->data[i])
434 /* string already in hashtable, free memory */
436 mem_free(a, sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10);
438 return (java_objectheader *) js;
442 /* follow link in external hash chain */
447 /* create copy of u2-array for new javastring */
448 u4 arraysize = sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10;
449 stringdata = mem_alloc(arraysize);
450 /* memcpy(stringdata, a, arraysize); */
451 memcpy(&(stringdata->header), &(a->header), sizeof(java_arrayheader));
452 memcpy(&(stringdata->data), &(a->data) + offset, sizeof(u2) * (length - 1) + 10);
458 /* location in hashtable found, complete arrayheader */
459 stringdata->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
460 stringdata->header.size = length;
462 if (!class_java_lang_String)
463 load_class_bootstrap(utf_java_lang_String,&class_java_lang_String);
464 assert(class_java_lang_String);
465 assert(class_java_lang_String->loaded);
467 /* if we use eager loading, we have to check loaded String class */
469 list_addfirst(&unlinkedclasses, class_java_lang_String);
472 /* create new javastring */
473 js = NEW(java_lang_String);
474 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
475 initObjectLock(&js->header);
477 js->header.vftbl = class_java_lang_String->vftbl;
478 js->value = stringdata;
482 /* create new literalstring */
483 s = NEW(literalstring);
484 s->hashlink = string_hash.ptr[slot];
485 s->string = (java_objectheader *) js;
486 string_hash.ptr[slot] = s;
488 /* update number of hashtable entries */
489 string_hash.entries++;
491 /* reorganization of hashtable */
492 if (string_hash.entries > (string_hash.size * 2)) {
493 /* reorganization of hashtable, average length of
494 the external chains is approx. 2 */
498 hashtable newhash; /* the new hashtable */
500 /* create new hashtable, double the size */
501 init_hashtable(&newhash, string_hash.size * 2);
502 newhash.entries = string_hash.entries;
504 /* transfer elements to new hashtable */
505 for (i = 0; i < string_hash.size; i++) {
506 s = string_hash.ptr[i];
508 literalstring *nexts = s->hashlink;
509 js = (java_lang_String *) s->string;
510 slot = unicode_hashkey(js->value->data, js->count) & (newhash.size - 1);
512 s->hashlink = newhash.ptr[slot];
513 newhash.ptr[slot] = s;
515 /* follow link in external hash chain */
520 /* dispose old table */
521 MFREE(string_hash.ptr, void*, string_hash.size);
522 string_hash = newhash;
525 return (java_objectheader *) js;
529 /* literalstring_new ***********************************************************
531 Creates a new javastring with the text of the utf-symbol and inserts it into
532 the string hashtable.
534 *******************************************************************************/
536 java_objectheader *literalstring_new(utf *u)
538 char *utf_ptr; /* pointer to current unicode character */
540 u4 utflength; /* length of utf-string if uncompressed */
541 java_chararray *a; /* u2-array constructed from utf string */
545 utflength = utf_strlen(u);
547 /* allocate memory */
548 a = mem_alloc(sizeof(java_chararray) + sizeof(u2) * (utflength - 1) + 10);
550 /* convert utf-string to u2-array */
551 for (i = 0; i < utflength; i++)
552 a->data[i] = utf_nextu2(&utf_ptr);
554 return literalstring_u2(a, utflength, 0, false);
558 /* literalstring_free **********************************************************
560 Removes a javastring from memory.
562 *******************************************************************************/
564 void literalstring_free(java_objectheader* sobj)
569 s = (java_lang_String *) sobj;
572 /* dispose memory of java.lang.String object */
573 FREE(s, java_lang_String);
575 /* dispose memory of java-characterarray */
576 FREE(a, sizeof(java_chararray) + sizeof(u2) * (a->header.size - 1)); /* +10 ?? */
581 * These are local overrides for various environment variables in Emacs.
582 * Please do not remove this and leave it at the end of the file, where
583 * Emacs will automagically detect them.
584 * ---------------------------------------------------------------------
587 * indent-tabs-mode: t