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 2148 2005-03-30 16:49:40Z twisti $
41 #include "vm/global.h"
43 #include "mm/memory.h"
44 #include "native/include/java_lang_String.h"
45 #include "vm/exceptions.h"
46 #include "vm/loader.h"
47 #include "vm/options.h"
48 #include "vm/stringlocal.h"
52 /* stringtable_update **********************************************************
54 Traverses the javastring hashtable and sets the vftbl-entries of
55 javastrings which were temporarily set to NULL, because
56 java.lang.Object was not yet loaded.
58 *******************************************************************************/
60 void stringtable_update(void)
64 literalstring *s; /* hashtable entry */
67 for (i = 0; i < string_hash.size; i++) {
68 s = string_hash.ptr[i];
72 js = (java_lang_String *) s->string;
74 if (!js || !js->value)
75 /* error in hashtable found */
76 panic("invalid literalstring in hashtable");
80 if (!js->header.vftbl)
81 /* vftbl of javastring is NULL */
82 js->header.vftbl = class_java_lang_String->vftbl;
84 if (!a->header.objheader.vftbl)
85 /* vftbl of character-array is NULL */
86 a->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
88 /* follow link in external hash chain */
96 /* javastring_new **************************************************************
98 creates a new object of type java/lang/String with the text of
99 the specified utf8-string
101 return: pointer to the string or NULL if memory is exhausted.
103 *******************************************************************************/
105 java_lang_String *javastring_new(utf *u)
107 char *utf_ptr; /* current utf character in utf string */
108 u4 utflength; /* length of utf-string if uncompressed */
109 java_lang_String *s; /* result-string */
114 *exceptionptr = new_nullpointerexception();
119 utflength = utf_strlen(u);
121 s = (java_lang_String *) builtin_new(class_java_lang_String);
122 a = builtin_newarray_char(utflength);
124 /* javastring or character-array could not be created */
128 /* decompress utf-string */
129 for (i = 0; i < utflength; i++)
130 a->data[i] = utf_nextu2(&utf_ptr);
132 /* set fields of the javastring-object */
135 s->count = utflength;
141 /* javastring_new_char *********************************************************
143 creates a new java/lang/String object which contains the convertet
144 C-string passed via text.
146 return: the object pointer or NULL if memory is exhausted.
148 *******************************************************************************/
150 java_lang_String *javastring_new_char(const char *text)
153 s4 len; /* length of the string */
154 java_lang_String *s; /* result-string */
158 *exceptionptr = new_nullpointerexception();
164 s = (java_lang_String *) builtin_new(class_java_lang_String);
165 a = builtin_newarray_char(len);
167 /* javastring or character-array could not be created */
172 for (i = 0; i < len; i++)
173 a->data[i] = text[i];
175 /* set fields of the javastring-object */
184 /* javastring_tochar ***********************************************************
186 converts a Java string into a C string.
188 return: pointer to C string
190 Caution: calling method MUST release the allocated memory!
192 *******************************************************************************/
194 char *javastring_tochar(java_objectheader *so)
196 java_lang_String *s = (java_lang_String *) so;
209 buf = MNEW(char, s->count + 1);
211 for (i = 0; i < s->count; i++)
212 buf[i] = a->data[s->offset + i];
220 /* javastring_toutf ************************************************************
222 Make utf symbol from javastring.
224 *******************************************************************************/
226 utf *javastring_toutf(java_lang_String *string, bool isclassname)
228 java_lang_String *str = (java_lang_String *) string;
230 return utf_new_u2(str->value->data + str->offset, str->count, isclassname);
234 /* literalstring_u2 ************************************************************
236 Searches for the javastring with the specified u2-array in the
237 string hashtable, if there is no such string a new one is created.
239 If copymode is true a copy of the u2-array is made.
241 *******************************************************************************/
243 java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
246 literalstring *s; /* hashtable element */
247 java_lang_String *js; /* u2-array wrapped in javastring */
248 java_chararray *stringdata; /* copy of u2-array */
253 /* find location in hashtable */
254 key = unicode_hashkey(a->data + offset, length);
255 slot = key & (string_hash.size - 1);
256 s = string_hash.ptr[slot];
259 js = (java_lang_String *) s->string;
261 if (length == js->count) {
263 for (i = 0; i < length; i++) {
264 if (a->data[offset + i] != js->value->data[i])
268 /* string already in hashtable, free memory */
270 mem_free(a, sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10);
272 return (java_objectheader *) js;
276 /* follow link in external hash chain */
281 /* create copy of u2-array for new javastring */
282 u4 arraysize = sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10;
283 stringdata = mem_alloc(arraysize);
284 /* memcpy(stringdata, a, arraysize); */
285 memcpy(&(stringdata->header), &(a->header), sizeof(java_arrayheader));
286 memcpy(&(stringdata->data), &(a->data) + offset, sizeof(u2) * (length - 1) + 10);
292 /* location in hashtable found, complete arrayheader */
293 stringdata->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
294 stringdata->header.size = length;
296 /* if we use eager loading, we have to check loaded String class */
298 if (!load_class_bootstrap(class_java_lang_String))
301 list_addfirst(&unlinkedclasses, class_java_lang_String);
304 /* create new javastring */
305 js = NEW(java_lang_String);
306 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
307 initObjectLock(&js->header);
309 js->header.vftbl = class_java_lang_String->vftbl;
310 js->value = stringdata;
314 /* create new literalstring */
315 s = NEW(literalstring);
316 s->hashlink = string_hash.ptr[slot];
317 s->string = (java_objectheader *) js;
318 string_hash.ptr[slot] = s;
320 /* update number of hashtable entries */
321 string_hash.entries++;
323 /* reorganization of hashtable */
324 if (string_hash.entries > (string_hash.size * 2)) {
325 /* reorganization of hashtable, average length of
326 the external chains is approx. 2 */
330 hashtable newhash; /* the new hashtable */
332 /* create new hashtable, double the size */
333 init_hashtable(&newhash, string_hash.size * 2);
334 newhash.entries = string_hash.entries;
336 /* transfer elements to new hashtable */
337 for (i = 0; i < string_hash.size; i++) {
338 s = string_hash.ptr[i];
340 literalstring *nexts = s->hashlink;
341 js = (java_lang_String *) s->string;
342 slot = unicode_hashkey(js->value->data, js->count) & (newhash.size - 1);
344 s->hashlink = newhash.ptr[slot];
345 newhash.ptr[slot] = s;
347 /* follow link in external hash chain */
352 /* dispose old table */
353 MFREE(string_hash.ptr, void*, string_hash.size);
354 string_hash = newhash;
357 return (java_objectheader *) js;
361 /* literalstring_new ***********************************************************
363 Creates a new javastring with the text of the utf-symbol and inserts it into
364 the string hashtable.
366 *******************************************************************************/
368 java_objectheader *literalstring_new(utf *u)
370 char *utf_ptr; /* pointer to current unicode character */
372 u4 utflength; /* length of utf-string if uncompressed */
373 java_chararray *a; /* u2-array constructed from utf string */
377 utflength = utf_strlen(u);
379 /* allocate memory */
380 a = mem_alloc(sizeof(java_chararray) + sizeof(u2) * (utflength - 1) + 10);
382 /* convert utf-string to u2-array */
383 for (i = 0; i < utflength; i++)
384 a->data[i] = utf_nextu2(&utf_ptr);
386 return literalstring_u2(a, utflength, 0, false);
390 /* literalstring_free **********************************************************
392 Removes a javastring from memory.
394 *******************************************************************************/
396 void literalstring_free(java_objectheader* sobj)
401 s = (java_lang_String *) sobj;
404 /* dispose memory of java.lang.String object */
405 FREE(s, java_lang_String);
407 /* dispose memory of java-characterarray */
408 FREE(a, sizeof(java_chararray) + sizeof(u2) * (a->header.size - 1)); /* +10 ?? */
413 * These are local overrides for various environment variables in Emacs.
414 * Please do not remove this and leave it at the end of the file, where
415 * Emacs will automagically detect them.
416 * ---------------------------------------------------------------------
419 * indent-tabs-mode: t