2 * string-icalls.c: String internal calls for the corlib
5 * Patrik Torstensson (patrik.torstensson@labs2.com)
7 * (C) 2001 Ximian, Inc.
14 #include <mono/metadata/string-icalls.h>
15 #include <mono/metadata/appdomain.h>
16 #include <mono/metadata/tabledefs.h>
17 #include <mono/metadata/loader.h>
18 #include <mono/metadata/object.h>
19 #include <mono/metadata/unicode.h>
22 mono_string_InternalJoin (MonoString *separator, MonoArray * value, gint32 sindex, gint32 count)
34 insert = mono_string_chars(separator);
35 insertlen = mono_string_length(separator);
38 for (pos = sindex; pos != sindex + count; pos++) {
39 length += mono_string_length(mono_array_get(value, MonoString *, pos));
40 if (pos < sindex + count - 1)
44 ret = mono_string_InternalAllocateStr(length);
45 dest = mono_string_chars(ret);
48 for (pos = sindex; pos != sindex + count; pos++) {
49 src = mono_string_chars(mono_array_get(value, MonoString *, pos));
50 srclen = mono_string_length(mono_array_get(value, MonoString *, pos));
52 memcpy(dest + destpos, src, srclen * sizeof(gunichar2));
55 if (pos < sindex + count - 1) {
56 memcpy(dest + destpos, insert, insertlen * sizeof(gunichar2));
65 mono_string_InternalInsert (MonoString *me, gint32 sindex, MonoString *value)
73 src = mono_string_chars(me);
74 srclen = mono_string_length(value);
76 ret = mono_string_InternalAllocateStr(mono_string_length(me) + srclen - sindex);
77 dest = mono_string_chars(ret);
79 memcpy(dest, src, sindex * sizeof(gunichar2));
80 memcpy(dest + sindex, insertsrc, srclen * sizeof(gunichar2));
86 mono_string_InternalReplaceChar (MonoString *me, gunichar2 oldChar, gunichar2 newChar)
88 g_warning("mono_string_InternalReplaceChar not impl");
89 return mono_string_new_utf16(mono_domain_get(), mono_string_chars(me), mono_string_length(me));
93 mono_string_InternalReplaceStr (MonoString *me, MonoString *oldValue, MonoString *newValue)
95 g_warning("mono_string_InternalReplaceStr not impl");
96 return mono_string_new_utf16(mono_domain_get(), mono_string_chars(me), mono_string_length(me));
100 mono_string_InternalRemove (MonoString *me, gint32 sindex, gint32 count)
108 ret = mono_string_InternalAllocateStr(mono_string_length(me) - count);
109 index_bytes = sindex * sizeof(gunichar2);
110 count_bytes = count * sizeof(gunichar2);
112 src = mono_string_chars(me);
113 dest = mono_string_chars(ret);
115 memcpy(dest, src, index_bytes);
116 memcpy(dest + sindex, src + sindex + count, index_bytes - count_bytes);
122 mono_string_InternalCopyTo (MonoString *me, gint32 sindex, MonoArray *dest, gint32 dindex, gint32 count)
124 gunichar2 *destptr = (gunichar2 *) mono_array_addr(dest, gunichar2, dindex);
125 gunichar2 *src = mono_string_chars(me);
127 memcpy(destptr, src + sindex, sizeof(gunichar2) * count);
131 mono_string_InternalSplit (MonoString *me, MonoArray *separator, gint32 count)
136 gint32 arrsize, srcsize, splitsize;
137 gint32 i, lastpos, arrpos;
139 gunichar2 *tmpstrptr;
141 src = mono_string_chars(me);
142 srcsize = mono_string_length(me);
143 arrsize = mono_array_length(separator);
146 for (i = 0; i != srcsize && splitsize < count; i++) {
147 if (mono_string_isinarray(separator, arrsize, src[i]))
154 // if no split chars found return the string
155 if (splitsize == 0) {
156 retarr = mono_array_new(mono_domain_get(), mono_defaults.string_class, 1);
157 tmpstr = mono_string_InternalAllocateStr(srcsize);
158 tmpstrptr = mono_string_chars(tmpstr);
160 memcpy(tmpstrptr, src, srcsize * sizeof(gunichar2));
161 mono_array_set(retarr, MonoString *, 0, tmpstr);
166 retarr = mono_array_new(mono_domain_get(), mono_defaults.string_class, splitsize);
167 for (i = 0; i != srcsize && arrpos != count; i++) {
168 if (mono_string_isinarray(separator, arrsize, src[i])) {
169 if (arrpos == count - 1)
170 tmpstrsize = srcsize - lastpos;
172 tmpstrsize = i - lastpos;
174 tmpstr = mono_string_InternalAllocateStr(tmpstrsize);
175 tmpstrptr = mono_string_chars(tmpstr);
177 memcpy(tmpstrptr, src + lastpos, tmpstrsize * sizeof(gunichar2));
178 mono_array_set(retarr, MonoString *, arrpos, tmpstr);
188 mono_string_isinarray (MonoArray *chars, gint32 arraylength, gunichar2 chr)
193 for (arrpos = 0; arrpos != arraylength; arrpos++) {
194 cmpchar = mono_array_get(chars, gunichar2, arrpos);
195 if (mono_string_cmp_char(cmpchar, chr, 1) == 0)
203 mono_string_InternalTrim (MonoString *me, MonoArray *chars, gint32 typ)
206 gunichar2 *src, *dest;
207 gint32 srclen, newlen, arrlen;
208 gint32 i, lenfirst, lenlast;
210 srclen = mono_string_length(me);
211 src = mono_string_chars(me);
212 arrlen = mono_array_length(chars);
217 if (0 == typ || 1 == typ) {
218 for (i = 0; i != srclen; i++) {
219 if (mono_string_isinarray(chars, arrlen, src[i]))
226 if (0 == typ || 2 == typ) {
227 for (i = srclen - lenfirst; i != 0; i--) {
228 if (mono_string_isinarray(chars, arrlen, src[i]))
235 newlen = srclen - lenfirst - lenlast;
237 ret = mono_string_InternalAllocateStr(newlen);
238 dest = mono_string_chars(ret);
240 memcpy(dest, src + lenfirst, newlen *sizeof(gunichar2));
246 mono_string_InternalIndexOfChar (MonoString *me, gunichar2 value, gint32 sindex, gint32 count)
251 src = mono_string_chars(me);
252 for (pos = sindex; pos != count + sindex; pos++) {
253 if (mono_string_cmp_char(src[pos], value ,1) == 0)
261 mono_string_InternalIndexOfStr (MonoString *me, MonoString *value, gint32 sindex, gint32 count)
268 lencmpstr = mono_string_length(value);
270 src = mono_string_chars(me);
271 cmpstr = mono_string_chars(value);
273 for (pos = sindex; pos != count + sindex; pos++) {
274 if (0 == mono_string_InternalCompareStrN(me, pos, value, 0, lencmpstr, 0)) {
283 mono_string_InternalIndexOfAny (MonoString *me, MonoArray *arr, gint32 sindex, gint32 count)
289 arraysize = mono_array_length(arr);
290 src = mono_string_chars(me);
292 for (pos = sindex; pos != count + sindex; pos++) {
293 if (mono_string_isinarray(arr, arraysize, src[pos]))
301 mono_string_InternalLastIndexOfChar (MonoString *me, gunichar2 value, gint32 sindex, gint32 count)
306 src = mono_string_chars(me);
307 for (pos = sindex; pos > sindex - count; pos--) {
308 if (mono_string_cmp_char(src[pos], value ,1) == 0)
316 mono_string_InternalLastIndexOfStr (MonoString *me, MonoString *value, gint32 sindex, gint32 count)
323 lencmpstr = mono_string_length(value);
325 src = mono_string_chars(me);
326 cmpstr = mono_string_chars(value);
328 for (pos = sindex; pos > sindex - count; pos -= lencmpstr) {
329 if (0 == mono_string_InternalCompareStrN(me, pos, value, 0, lencmpstr, 0)) {
338 mono_string_InternalLastIndexOfAny (MonoString *me, MonoArray *anyOf, gint32 sindex, gint32 count)
344 arraysize = mono_array_length(anyOf);
345 src = mono_string_chars(me);
347 for (pos = sindex; pos > sindex - count; pos--) {
348 if (mono_string_isinarray(anyOf, arraysize, src[pos]))
356 mono_string_InternalPad (MonoString *me, gint32 width, gint16 chr, MonoBoolean right)
365 srclen = mono_string_length(me);
366 src = mono_string_chars(me);
368 ret = mono_string_InternalAllocateStr(width);
369 dest = mono_string_chars(ret);
370 fillcount = width - srclen;
373 memcpy(dest, src, srclen * sizeof(gunichar2));
374 for (i = srclen; i != width; i++)
381 for (i = 0; i != fillcount; i++)
384 memcpy(dest + fillcount, src, srclen * sizeof(gunichar2));
390 mono_string_InternalToLower (MonoString *me)
397 ret = mono_string_new_size(mono_domain_get (), mono_string_length(me));
399 src = mono_string_chars (me);
400 dest = mono_string_chars (ret);
402 for (i = 0; i < mono_string_length (me); ++i)
403 dest[i] = g_unichar_tolower(src[i]);
409 mono_string_InternalToUpper (MonoString *me)
416 ret = mono_string_new_size(mono_domain_get (), mono_string_length(me));
418 src = mono_string_chars (me);
419 dest = mono_string_chars (ret);
421 for (i = 0; i < mono_string_length (me); ++i)
422 dest[i] = g_unichar_toupper(src[i]);
428 mono_string_InternalAllocateStr(gint32 length)
430 return mono_string_new_size(mono_domain_get (), length);
434 mono_string_InternalStrcpyStr (MonoString *dest, gint32 destPos, MonoString *src)
439 srcptr = mono_string_chars(src);
440 destptr = mono_string_chars(dest);
442 memcpy(destptr + destPos, srcptr, mono_string_length(src) * sizeof(gunichar2));
446 mono_string_InternalStrcpyStrN (MonoString *dest, gint32 destPos, MonoString *src, gint32 startPos, gint32 count)
451 srcptr = mono_string_chars(src);
452 destptr = mono_string_chars(dest);
453 memcpy(destptr + destPos, srcptr + startPos, count * sizeof(gunichar2));
457 mono_string_InternalIntern (MonoString *str)
459 return mono_string_intern(str);
463 mono_string_InternalIsInterned (MonoString *str)
465 return mono_string_is_interned(str);
469 mono_string_InternalCompareStrN (MonoString *s1, gint32 i1, MonoString *s2, gint32 i2, gint32 length, MonoBoolean inCase)
471 // c translation of C# code.. :)
486 lenstr1 = mono_string_length(s1);
487 lenstr2 = mono_string_length(s2);
489 str1 = mono_string_chars(s1);
490 str2 = mono_string_chars(s2);
494 for (pos = 0; pos != length; pos++) {
495 if (i1 + pos >= lenstr1 || i2 + pos >= lenstr2)
498 if (0 != mono_string_cmp_char(str1[i1 + pos], str2[i2 + pos], mode))
502 // the lesser wins, so if we have looped until length we just need to check the last char
504 return mono_string_cmp_char(str1[i1 + pos - 1], str2[i2 + pos - 1], mode);
507 // Test if one the strings has been compared to the end
508 if (i1 + pos >= lenstr1) {
509 if (i2 + pos >= lenstr2)
513 } else if (i2 + pos >= lenstr2)
516 // if not, check our last char only.. (can this happen?)
517 return mono_string_cmp_char(str1[i1 + pos], str2[i2 + pos], mode);
521 mono_string_GetHashCode (MonoString *me)
524 gunichar2 *data = mono_string_chars (me);
526 for (i = 0; i < mono_string_length (me); ++i)
527 h = (h << 5) - h + data [i];
533 mono_string_get_Chars (MonoString *me, gint32 idx)
535 return mono_string_chars(me)[idx];
538 /* @mode : 0 = StringCompareModeDirect
539 1 = StringCompareModeCaseInsensitive
540 2 = StringCompareModeOrdinal
543 mono_string_cmp_char (gunichar2 c1, gunichar2 c2, gint16 mode)
549 // TODO: compare with culture info
550 if (g_unichar_isupper(c1) && g_unichar_islower(c2))
553 if (g_unichar_islower(c1) && g_unichar_isupper(c2))
556 result = (gint32) c1 - c2;
559 result = (gint32) g_unichar_tolower(c1) - g_unichar_tolower(c2);
561 // fix: compare ordinal
563 result = (gint32) g_unichar_tolower(c1) - g_unichar_tolower(c2);