1 /* string.c++ -- written by Alexis WILKE for Made to Order Software Corp. (c) 2005-2009 */
2 
3 /*
4 
5 Copyright (c) 2005-2009 Made to Order Software Corp.
6 
7 Permission is hereby granted, free of charge, to any
8 person obtaining a copy of this software and
9 associated documentation files (the "Software"), to
10 deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify,
12 merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom
14 the Software is furnished to do so, subject to the
15 following conditions:
16 
17 The above copyright notice and this permission notice
18 shall be included in all copies or substantial
19 portions of the Software.
20 
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
22 ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
23 LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
24 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
25 EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28 ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 SOFTWARE.
31 
32 */
33 
34 #include	"compiler.h"
35 
36 
37 namespace sswf
38 {
39 namespace as
40 {
41 
42 
43 
44 
String(void)45 String::String(void)
46 {
47 	f_len = 0;
48 	f_max = 0;
49 	f_str = 0;
50 }
String(const String & string)51 String::String(const String& string)
52 {
53 	f_len = 0;
54 	f_max = 0;
55 	f_str = 0;
56 	Set(string.f_str, string.f_len);
57 }
String(const char * str)58 String::String(const char *str)
59 {
60 	f_len = 0;
61 	f_max = 0;
62 	f_str = 0;
63 	operator += (str);
64 }
~String()65 String::~String()
66 {
67 	delete [] f_str;
68 }
69 
operator =(const String & string)70 String& String::operator = (const String& string)
71 {
72 	Set(string.f_str, string.f_len);
73 	return *this;
74 }
75 
76 // Assume ISO-8859-1 as input
operator =(const char * str)77 String& String::operator = (const char *str)
78 {
79 	Empty();
80 	return operator += (str);
81 }
82 
operator ==(const String & string) const83 bool String::operator == (const String& string) const
84 {
85 	if(f_len != string.f_len) {
86 		return false;
87 	}
88 
89 	return memcmp(f_str, string.f_str, sizeof(long) * f_len) == 0;
90 }
91 
operator !=(const String & string) const92 bool String::operator != (const String& string) const
93 {
94 	return !operator == (string);
95 }
96 
operator ==(const char * str) const97 bool String::operator == (const char *str) const
98 {
99 	long	idx = 0;
100 
101 	while(*str != '\0' && idx < f_len) {
102 		if(*str != f_str[idx]) {
103 			return false;
104 		}
105 		str++;
106 		idx++;
107 	}
108 
109 	return *str == '\0' && idx == f_len;
110 }
111 
operator !=(const char * str) const112 bool String::operator != (const char *str) const
113 {
114 	return !operator == (str);
115 }
116 
Compare(const String & string) const117 int String::Compare(const String& string) const
118 {
119 	long idx = 0;
120 	long max = f_len < string.f_len ? f_len : string.f_len;
121 	while(idx < max) {
122 		long r = f_str[idx] - string.f_str[idx];
123 		if(r != 0) {
124 			return r < 0 ? -1 : 1;
125 		}
126 		idx++;
127 	}
128 	if(max == f_len) {
129 		return max == string.f_len ? 0 : -1;
130 	}
131 	return 1;
132 }
133 
Compare(const char * string) const134 int String::Compare(const char *string) const
135 {
136 	if(string == 0) {
137 		if(f_len == 0) {
138 			return 0;
139 		}
140 		return 1;
141 	}
142 	long idx = 0;
143 	long len = strlen(string);
144 	long max = f_len < len ? f_len : len;
145 	while(idx < max) {
146 		long r = f_str[idx] - ((const unsigned char *) string)[idx];
147 		if(r != 0) {
148 			return r < 0 ? -1 : 1;
149 		}
150 		idx++;
151 	}
152 	if(max == f_len) {
153 		return max == len ? 0 : -1;
154 	}
155 	return 1;
156 }
157 
IsEmpty(void) const158 bool String::IsEmpty(void) const
159 {
160 	return f_len == 0;
161 }
Empty(void)162 void String::Empty(void)
163 {
164 	f_len = 0;
165 }
166 
GetLength(void) const167 long String::GetLength(void) const
168 {
169 	return f_len;
170 }
Get(void) const171 const long *String::Get(void) const
172 {
173 	return f_str;
174 }
Set(const long * str,long size)175 void String::Set(const long *str, long size)
176 {
177 	if(size > 0 && size < f_max) {
178 		f_len = size;
179 		memcpy(f_str, str, f_len * sizeof(long));
180 	}
181 	else {
182 		delete [] f_str;
183 		if(size <= 0) {
184 			f_len = 0;
185 			f_max = 0;
186 			f_str = 0;
187 		}
188 		else {
189 			f_len = size;
190 			f_max = (size + 255) & -256;
191 			f_str = new long[f_max];
192 			memcpy(f_str, str, f_len * sizeof(long));
193 		}
194 	}
195 }
196 
AppendChar(long c)197 void String::AppendChar(long c)
198 {
199 	if(f_len >= f_max) {
200 		f_max += 256;
201 		long *s = new long[f_max];
202 		memcpy(s, f_str, f_len * sizeof(long));
203 		delete [] f_str;
204 		f_str = s;
205 	}
206 
207 	f_str[f_len] = c;
208 	++f_len;
209 }
210 
AppendStr(const long * str,long len)211 String& String::AppendStr(const long *str, long len)
212 {
213 	if(len == 0) {
214 		return *this;
215 	}
216 
217 	if(f_len + len > f_max) {
218 		f_max = (f_len + len + 255) & -256;
219 		long *s = new long[f_max];
220 		memcpy(s, f_str, f_len * sizeof(long));
221 		memcpy(s + f_len, str, len * sizeof(long));
222 		delete [] f_str;
223 		f_str = s;
224 	}
225 	else {
226 		memcpy(f_str + f_len, str, len * sizeof(long));
227 	}
228 	f_len += len;
229 
230 	return *this;
231 }
232 
operator +=(const String & string)233 String& String::operator += (const String& string)
234 {
235 	if(string.f_len == 0) {
236 		return *this;
237 	}
238 
239 	if(f_len + string.f_len > f_max) {
240 		f_max = (f_len + string.f_len + 255) & -256;
241 		long *s = new long[f_max];
242 		if(f_len > 0) {
243 			memcpy(s, f_str, f_len * sizeof(long));
244 		}
245 		memcpy(s + f_len, string.f_str, string.f_len * sizeof(long));
246 		delete [] f_str;
247 		f_str = s;
248 	}
249 	else {
250 		memcpy(f_str + f_len, string.f_str, string.f_len * sizeof(long));
251 	}
252 	f_len += string.f_len;
253 
254 	return *this;
255 }
256 
257 // Assume ISO-8859-1 as input
operator +=(const char * str)258 String& String::operator += (const char *str)
259 {
260 	if(str == 0) {
261 		return *this;
262 	}
263 	long l = strlen(str);
264 	if(l == 0) {
265 		return *this;
266 	}
267 
268 	long idx;
269 	if(f_len + l > f_max) {
270 		f_max = (f_len + l + 255) & -256;
271 		long *s = new long[f_max];
272 		if(f_len > 0) {
273 			memcpy(s, f_str, f_len * sizeof(long));
274 		}
275 		for(idx = 0; idx < l; ++idx) {
276 			s[f_len + idx] = str[idx];
277 		}
278 		delete [] f_str;
279 		f_str = s;
280 	}
281 	else {
282 		for(idx = 0; idx < l; ++idx) {
283 			f_str[f_len + idx] = str[idx];
284 		}
285 	}
286 	f_len += l;
287 
288 	return *this;
289 }
290 
291 
292 
293 
GetUTF8Length(void) const294 int String::GetUTF8Length(void) const
295 {
296 	size_t		r, l, wc_len;
297 	long		*wc, c;
298 
299 	// make sure we always have a null at the end...
300 	r = 0;
301 
302 	wc_len = f_len;
303 	wc = f_str;
304 	while(wc_len > 0) {
305 		/* get one wide character */
306 		c = *wc++;
307 		wc_len--;
308 		/* encode in temp buffer */
309 		if(c < 0x80) {
310 			/* this will also encode '\0'... */
311 			l = 1;
312 		}
313 		else if(c < 0x800) {
314 			l = 2;
315 		}
316 		else if(c < 0x10000) {
317 			l = 3;
318 		}
319 		else if(c < 0x200000) {
320 			l = 4;
321 		}
322 		else if(c < 0x4000000) {
323 			l = 5;
324 		}
325 		else if(c > 0) {
326 			l = 6;
327 		}
328 		else {
329 			/* an invalid wide character (negative!) */
330 			return -1;
331 		}
332 		r += l;
333 	}
334 
335 	return r;
336 }
337 
ToUTF8(char * mb,size_t & mb_len) const338 int String::ToUTF8(char *mb, size_t& mb_len) const
339 {
340 	char		buf[6];
341 	size_t		l, wc_len;
342 	long		*wc, c;
343 
344 	// make sure we always have a null at the end...
345 	mb_len--;
346 	mb[mb_len] = '\0';
347 
348 	wc_len = f_len;
349 	wc = f_str;
350 	while(wc_len > 0) {
351 		/* get one wide character */
352 		c = *wc++;
353 		wc_len--;
354 		/* encode in temp buffer */
355 		if(c < 0x80) {
356 			/* this will also encode '\0'... */
357 			buf[0] = (char) c;
358 			l = 1;
359 		}
360 		else if(c < 0x800) {
361 			buf[0] = (c >> 6) | 0xC0;
362 			buf[1] = (c & 0x3F) | 0x80;
363 			l = 2;
364 		}
365 		else if(c < 0x10000) {
366 			buf[0] = (c >> 12) | 0xE0;
367 			buf[1] = ((c >> 6) & 0x3F) | 0x80;
368 			buf[2] = (c & 0x3F) | 0x80;
369 			l = 3;
370 		}
371 		else if(c < 0x200000) {
372 			buf[0] = (c >> 18) | 0xF0;
373 			buf[1] = ((c >> 12) & 0x3F) | 0x80;
374 			buf[2] = ((c >> 6) & 0x3F) | 0x80;
375 			buf[3] = (c & 0x3F) | 0x80;
376 			l = 4;
377 		}
378 		else if(c < 0x4000000) {
379 			buf[0] = (c >> 24) | 0xF8;
380 			buf[1] = ((c >> 18) & 0x3F) | 0x80;
381 			buf[2] = ((c >> 12) & 0x3F) | 0x80;
382 			buf[3] = ((c >> 6) & 0x3F) | 0x80;
383 			buf[4] = (c & 0x3F) | 0x80;
384 			l = 5;
385 		}
386 		else if(c > 0) {	// <=> (signed long) c < 0x80000000
387 			buf[0] = (c >> 30) | 0xFC;
388 			buf[1] = ((c >> 24) & 0x3F) | 0x80;
389 			buf[2] = ((c >> 18) & 0x3F) | 0x80;
390 			buf[3] = ((c >> 12) & 0x3F) | 0x80;
391 			buf[4] = ((c >> 6) & 0x3F) | 0x80;
392 			buf[5] = (c & 0x3F) | 0x80;
393 			l = 6;
394 		}
395 		else {
396 			/* an invalid wide character (negative!) */
397 			return -1;
398 		}
399 		if(l < mb_len) {
400 			mb_len -= l;
401 			memcpy(mb, buf, l);
402 			mb += l;
403 		}
404 		else {
405 			/* overflow error */
406 			return -1;
407 		}
408 	}
409 
410 	*mb = '\0';
411 
412 	mb_len++;	// put the '\0' back in what's left
413 
414 	return 0;
415 }
416 
417 
418 // WARNING: this function appends the string mb to
419 //	    the current string in this object
FromUTF8(const char * mb,size_t mb_len)420 int String::FromUTF8(const char *mb, size_t mb_len)
421 {
422 	unsigned char	c;
423 	long		w;
424 	size_t		l;
425 
426 	while(mb_len > 0) {
427 		mb_len--;
428 		c = (unsigned char) *mb++;
429 		if(c < 0x80) {
430 			w = c;
431 		}
432 		else {
433 			if(c >= 0xC0 && c <= 0xDF) {
434 				l = 1;
435 				w = c & 0x1F;
436 			}
437 			else if(c >= 0xE0 && c <= 0xEF) {
438 				l = 2;
439 				w = c & 0x0F;
440 			}
441 			else if(c >= 0xF0 && c <= 0xF7) {
442 				l = 3;
443 				w = c & 0x07;
444 			}
445 			else if(c >= 0xF8 && c <= 0xFB) {
446 				l = 4;
447 				w = c & 0x03;
448 			}
449 			else if(c >= 0xFC && c <= 0xFD) {
450 				l = 5;
451 				w = c & 0x01;
452 			}
453 			else {
454 				return -1;
455 			}
456 			if(mb_len < l) {
457 				return -1;
458 			}
459 			mb_len -= l;
460 			while(l > 0) {
461 				c = (unsigned char) *mb++;
462 				if(c < 0x80 || c > 0xBF) {
463 					return -1;
464 				}
465 				l--;
466 				w = (w << 6) | (c & 0x3F);
467 			}
468 		}
469 		AppendChar(w);
470 	}
471 
472 	return 0;
473 }
474 
475 
GetUTF8(void) const476 char *String::GetUTF8(void) const
477 {
478 	size_t len = GetUTF8Length() + 2;
479 	char *str = new char[len];
480 	ToUTF8(str, len);
481 	return str;
482 }
483 
484 
485 
486 };	// namespace as
487 };	// namespace sswf
488