1 karl 1.98 //%2005////////////////////////////////////////////////////////////////////////
|
2 mike 1.27 //
|
3 karl 1.97 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
|
6 karl 1.85 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.97 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
|
9 karl 1.98 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 mike 1.27 //
12 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
13 kumpf 1.41 // of this software and associated documentation files (the "Software"), to
14 // deal in the Software without restriction, including without limitation the
15 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
16 mike 1.27 // sell copies of the Software, and to permit persons to whom the Software is
17 // furnished to do so, subject to the following conditions:
18 //
|
19 kumpf 1.41 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
|
20 mike 1.27 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
21 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
22 kumpf 1.41 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
23 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
25 mike 1.27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 //==============================================================================
29 //
30 // Author: Mike Brasher (mbrasher@bmc.com)
31 //
|
32 kumpf 1.39 // Modified By: Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
|
33 mike 1.27 //
34 //%/////////////////////////////////////////////////////////////////////////////
35
36
37 #include <cctype>
|
38 kumpf 1.64 #include <cstring>
|
39 mike 1.27 #include "String.h"
|
40 kumpf 1.43 #include "Array.h"
|
41 kumpf 1.48 #include "InternalException.h"
|
42 mike 1.27 #include <iostream>
|
43 kumpf 1.63 #include <fstream>
|
44 mike 1.27
|
45 david 1.69 #include "CommonUTF.h"
46
47 #ifdef PEGASUS_HAS_ICU
|
48 chuck 1.74 #include <unicode/unistr.h>
|
49 david 1.69 #endif
50
|
51 mike 1.28 PEGASUS_USING_STD;
52
|
53 mike 1.27 PEGASUS_NAMESPACE_BEGIN
54
|
55 kumpf 1.39 ///////////////////////////////////////////////////////////////////////////////
56 //
|
57 kumpf 1.54 // CString
58 //
59 ///////////////////////////////////////////////////////////////////////////////
60
61 CString::CString()
62 : _rep(0)
63 {
64 }
65
66 CString::CString(const CString& cstr)
67 {
|
68 kumpf 1.82 _rep = 0;
69
70 if (cstr._rep)
71 {
72 _rep = (void*)new char[strlen((char*)cstr._rep)+1];
73 strcpy((char*)_rep, (char*)cstr._rep);
74 }
|
75 kumpf 1.54 }
76
77 CString::CString(char* cstr)
78 : _rep(cstr)
79 {
80 }
81
82 CString::~CString()
83 {
84 if (_rep)
|
85 kumpf 1.82 {
|
86 kumpf 1.59 delete [] (char*)_rep;
|
87 kumpf 1.82 }
|
88 kumpf 1.54 }
89
|
90 kumpf 1.56 CString& CString::operator=(const CString& cstr)
91 {
|
92 kumpf 1.82 if (&cstr != this)
|
93 kumpf 1.81 {
|
94 kumpf 1.82 if (_rep)
95 {
96 delete [] (char*)_rep;
97 _rep = 0;
98 }
99 if (cstr._rep)
100 {
101 _rep = (char*)new char[strlen((char*)cstr._rep)+1];
102 strcpy((char*)_rep, (char*)cstr._rep);
103 }
|
104 kumpf 1.81 }
|
105 kumpf 1.56 return *this;
106 }
107
|
108 kumpf 1.54 CString::operator const char*() const
109 {
|
110 kumpf 1.59 return (char*)_rep;
|
111 kumpf 1.54 }
112
113 ///////////////////////////////////////////////////////////////////////////////
114 //
|
115 kumpf 1.39 // String
116 //
117 ///////////////////////////////////////////////////////////////////////////////
118
|
119 kumpf 1.37 const String String::EMPTY = String();
|
120 mike 1.27
|
121 kumpf 1.38 Uint32 _strnlen(const char* str, Uint32 n)
122 {
123 if (!str)
124 throw NullPointer();
125
126 for (Uint32 i=0; i<n; i++)
127 {
128 if (!*str)
129 {
130 return i;
131 }
132 }
133
134 return n;
135 }
136
137 Uint32 _strnlen(const Char16* str, Uint32 n)
138 {
139 if (!str)
140 throw NullPointer();
141
142 kumpf 1.38 for (Uint32 i=0; i<n; i++)
143 {
144 if (!*str)
145 {
146 return i;
147 }
148 }
149
150 return n;
151 }
152
|
153 kumpf 1.39 inline Uint32 _StrLen(const char* str)
|
154 mike 1.27 {
155 if (!str)
156 throw NullPointer();
157
158 return strlen(str);
159 }
160
|
161 kumpf 1.39 inline Uint32 _StrLen(const Char16* str)
|
162 mike 1.27 {
163 if (!str)
164 throw NullPointer();
165
166 Uint32 n = 0;
167
168 while (*str++)
169 n++;
170
171 return n;
172 }
173
|
174 kumpf 1.43 class StringRep
175 {
176 public:
177 StringRep()
178 {}
179 StringRep(const StringRep& r)
180 : c16a(r.c16a)
181 {}
182 StringRep(const Char16* str)
183 : c16a(str, _StrLen(str) + 1)
184 {}
185
186 Array<Char16> c16a;
187 };
188
|
189 mike 1.27 String::String()
190 {
|
191 kumpf 1.43 _rep = new StringRep;
192 _rep->c16a.append('\0');
|
193 mike 1.27 }
194
|
195 kumpf 1.39 String::String(const String& str)
|
196 mike 1.27 {
|
197 tony 1.66 if (str._rep != NULL)
198 {
|
199 kumpf 1.43 _rep = new StringRep(*str._rep);
|
200 tony 1.66 }
201 else
202 {
203 _rep = new StringRep();
204 }
|
205 kumpf 1.39 }
|
206 tony 1.66
|
207 mike 1.27
|
208 kumpf 1.39 String::String(const String& str, Uint32 n)
209 {
|
210 kumpf 1.43 _rep = new StringRep;
|
211 kumpf 1.55 assign(str.getChar16Data(), n);
|
212 kumpf 1.39 }
213
214 String::String(const Char16* str)
215 {
|
216 kumpf 1.43 _rep = new StringRep(str);
|
217 mike 1.27 }
218
|
219 kumpf 1.39 String::String(const Char16* str, Uint32 n)
220 {
|
221 kumpf 1.43 _rep = new StringRep;
|
222 kumpf 1.39 assign(str, n);
223 }
224
225 String::String(const char* str)
|
226 mike 1.27 {
|
227 kumpf 1.43 _rep = new StringRep;
|
228 kumpf 1.39 assign(str);
|
229 mike 1.27 }
230
|
231 kumpf 1.39 String::String(const char* str, Uint32 n)
|
232 mike 1.27 {
|
233 kumpf 1.43 _rep = new StringRep;
|
234 kumpf 1.39 assign(str, n);
235 }
|
236 mike 1.27
|
237 kumpf 1.39 String::~String()
238 {
|
239 kumpf 1.43 delete _rep;
|
240 mike 1.27 }
241
|
242 kumpf 1.39 String& String::operator=(const String& str)
|
243 mike 1.27 {
|
244 kumpf 1.82 if (&str != this)
245 {
246 assign(str);
247 }
248 return *this;
|
249 mike 1.27 }
250
|
251 kumpf 1.39 String& String::assign(const String& str)
|
252 mike 1.27 {
|
253 kumpf 1.43 _rep->c16a = str._rep->c16a;
|
254 kumpf 1.39 return *this;
|
255 mike 1.27 }
256
|
257 kumpf 1.39 String& String::assign(const Char16* str)
|
258 mike 1.27 {
|
259 kumpf 1.43 _rep->c16a.clear();
260 _rep->c16a.append(str, _StrLen(str) + 1);
|
261 mike 1.27 return *this;
262 }
263
264 String& String::assign(const Char16* str, Uint32 n)
265 {
|
266 kumpf 1.43 _rep->c16a.clear();
|
267 kumpf 1.38 Uint32 m = _strnlen(str, n);
|
268 kumpf 1.43 _rep->c16a.append(str, m);
269 _rep->c16a.append('\0');
|
270 mike 1.27 return *this;
271 }
272
|
273 kumpf 1.39 String& String::assign(const char* str, Uint32 n)
|
274 mike 1.27 {
|
275 david 1.90 char *tmpStr = new char[n+1];
276 memset(tmpStr,0x00,n+1);
|
277 mike 1.27
|
278 david 1.90 strncpy(tmpStr,str,n);
279 assign(tmpStr);
|
280 kumpf 1.96 delete [] tmpStr;
|
281 mike 1.27
282 return *this;
283 }
284
|
285 kumpf 1.39 void String::clear()
286 {
|
287 kumpf 1.43 _rep->c16a.clear();
288 _rep->c16a.append('\0');
|
289 kumpf 1.39 }
290
|
291 kumpf 1.43 void String::reserveCapacity(Uint32 capacity)
|
292 kumpf 1.39 {
|
293 kumpf 1.45 _rep->c16a.reserveCapacity(capacity + 1);
|
294 kumpf 1.39 }
295
296 Uint32 String::size() const
297 {
|
298 kumpf 1.43 return _rep->c16a.size() - 1;
|
299 kumpf 1.39 }
300
|
301 kumpf 1.55 const Char16* String::getChar16Data() const
|
302 kumpf 1.39 {
|
303 kumpf 1.43 return _rep->c16a.getData();
|
304 kumpf 1.39 }
305
|
306 kumpf 1.53 Char16& String::operator[](Uint32 index)
|
307 mike 1.27 {
|
308 kumpf 1.53 if (index > size())
|
309 kumpf 1.49 throw IndexOutOfBoundsException();
|
310 mike 1.27
|
311 kumpf 1.53 return _rep->c16a[index];
|
312 mike 1.27 }
313
|
314 kumpf 1.53 const Char16 String::operator[](Uint32 index) const
|
315 mike 1.27 {
|
316 kumpf 1.53 if (index > size())
|
317 kumpf 1.49 throw IndexOutOfBoundsException();
|
318 mike 1.27
|
319 kumpf 1.53 return _rep->c16a[index];
|
320 mike 1.27 }
321
|
322 kumpf 1.39 String& String::append(const Char16& c)
323 {
|
324 kumpf 1.43 _rep->c16a.insert(_rep->c16a.size() - 1, c);
|
325 kumpf 1.39 return *this;
326 }
327
|
328 mike 1.27 String& String::append(const Char16* str, Uint32 n)
329 {
|
330 kumpf 1.38 Uint32 m = _strnlen(str, n);
|
331 kumpf 1.45 _rep->c16a.reserveCapacity(_rep->c16a.size() + m);
|
332 kumpf 1.43 _rep->c16a.remove(_rep->c16a.size() - 1);
333 _rep->c16a.append(str, m);
334 _rep->c16a.append('\0');
|
335 mike 1.27 return *this;
336 }
337
|
338 kumpf 1.39 String& String::append(const String& str)
|
339 mike 1.27 {
|
340 kumpf 1.55 return append(str.getChar16Data(), str.size());
|
341 mike 1.27 }
342
|
343 kumpf 1.53 void String::remove(Uint32 index, Uint32 size)
|
344 mike 1.27 {
|
345 kumpf 1.39 if (size == PEG_NOT_FOUND)
|
346 kumpf 1.53 size = this->size() - index;
|
347 mike 1.27
|
348 kumpf 1.53 if (index + size > this->size())
|
349 kumpf 1.49 throw IndexOutOfBoundsException();
|
350 mike 1.27
|
351 kumpf 1.39 if (size)
|
352 kumpf 1.53 _rep->c16a.remove(index, size);
|
353 mike 1.27 }
354
|
355 kumpf 1.53 String String::subString(Uint32 index, Uint32 length) const
|
356 mike 1.27 {
|
357 kumpf 1.53 if (index < size())
|
358 mike 1.27 {
|
359 kumpf 1.57 if ((length == PEG_NOT_FOUND) || (length > size() - index))
|
360 kumpf 1.53 length = size() - index;
|
361 mike 1.27
|
362 kumpf 1.55 return String(getChar16Data() + index, length);
|
363 mike 1.27 }
364 else
365 return String();
366 }
367
368 Uint32 String::find(Char16 c) const
369 {
|
370 kumpf 1.55 const Char16* first = getChar16Data();
|
371 mike 1.27
372 for (const Char16* p = first; *p; p++)
373 {
374 if (*p == c)
375 return p - first;
376 }
377
378 return PEG_NOT_FOUND;
379 }
380
|
381 kumpf 1.53 Uint32 String::find(Uint32 index, Char16 c) const
|
382 mike 1.30 {
|
383 kumpf 1.55 const Char16* data = getChar16Data();
|
384 mike 1.30
|
385 kumpf 1.53 for (Uint32 i = index, n = size(); i < n; i++)
|
386 mike 1.30 {
387 if (data[i] == c)
388 return i;
389 }
390
391 return PEG_NOT_FOUND;
392 }
393
|
394 mike 1.27 Uint32 String::find(const String& s) const
395 {
|
396 kumpf 1.55 const Char16* pSubStr = s.getChar16Data();
397 const Char16* pStr = getChar16Data();
|
398 mike 1.27 Uint32 subStrLen = s.size();
399 Uint32 strLen = size();
400
|
401 mike 1.30 if (subStrLen > strLen)
402 {
403 return PEG_NOT_FOUND;
404 }
405
|
406 mike 1.27 // loop to find first char match
407 Uint32 loc = 0;
408 for( ; loc <= (strLen-subStrLen); loc++)
409 {
410 if (*pStr++ == *pSubStr) // match first char
411 {
412 // point to substr 2nd char
413 const Char16* p = pSubStr + 1;
414
415 // Test remaining chars for equal
416 Uint32 i = 1;
417 for (; i < subStrLen; i++)
418 if (*pStr++ != *p++ )
|
419 humberto 1.88 {pStr-=i; break;} // break from loop
|
420 mike 1.27 if (i == subStrLen)
421 return loc;
422 }
423 }
424 return PEG_NOT_FOUND;
425 }
426
427 Uint32 String::reverseFind(Char16 c) const
428 {
|
429 kumpf 1.55 const Char16* first = getChar16Data();
430 const Char16* last = getChar16Data() + size();
|
431 mike 1.27
432 while (last != first)
433 {
434 if (*--last == c)
435 return last - first;
436 }
437
438 return PEG_NOT_FOUND;
439 }
440
441 void String::toLower()
442 {
|
443 david 1.90 const char * noLocale = NULL;
444 String::toLower(noLocale);
445 }
446 void String::toLower(const char * strLocale)
447 {
|
448 david 1.69 #ifdef PEGASUS_HAS_ICU
|
449 chuck 1.78 UnicodeString UniStr((const UChar *)_rep->c16a.getData());
|
450 david 1.90 if(strLocale == NULL)
451 {
452 UniStr.toLower();
453 }
454 else
455 {
456 Locale loc(strLocale);
457 if(loc.isBogus())
458 {
459 throw InvalidNameException(String(strLocale));
460 }
461 UniStr.toLower(loc);
462 }
|
463 david 1.80 UniStr.append((UChar)'\0');
464
465 assign((Char16*)UniStr.getBuffer());
|
466 david 1.69 #else
|
467 kumpf 1.43 for (Char16* p = &_rep->c16a[0]; *p; p++)
|
468 mike 1.27 {
|
469 kumpf 1.46 if (*p <= PEGASUS_MAX_PRINTABLE_CHAR)
|
470 mike 1.27 *p = tolower(*p);
471 }
|
472 david 1.69 #endif
|
473 kumpf 1.39 }
474
|
475 david 1.90 void String::toUpper(const char * strLocale)
476 {
477 #ifdef PEGASUS_HAS_ICU
478 UnicodeString UniStr((const UChar *)_rep->c16a.getData());
479 if(strLocale == NULL)
480 {
481 UniStr.toUpper();
482 }
483 else
484 {
485 Locale loc(strLocale);
486 if(loc.isBogus())
487 {
488 throw InvalidNameException(String(strLocale));
489 }
490 UniStr.toUpper(loc);
491 }
492 UniStr.append((UChar)'\0');
493
494 assign((Char16*)UniStr.getBuffer());
|
495 david 1.91 #else
496 for (Char16* p = &_rep->c16a[0]; *p; p++)
497 {
498 if (*p <= PEGASUS_MAX_PRINTABLE_CHAR)
499 *p = toupper(*p);
500 }
|
501 david 1.90 #endif
502 }
503
|
504 kumpf 1.43 int String::compare(const String& s1, const String& s2, Uint32 n)
|
505 kumpf 1.39 {
|
506 kumpf 1.55 const Char16* s1c16 = s1.getChar16Data();
507 const Char16* s2c16 = s2.getChar16Data();
|
508 kumpf 1.39
509 while (n--)
|
510 mike 1.27 {
|
511 kumpf 1.43 int r = *s1c16++ - *s2c16++;
|
512 mike 1.27
513 if (r)
514 return r;
515 }
516
517 return 0;
518 }
519
|
520 kumpf 1.43 int String::compare(const String& s1, const String& s2)
|
521 mike 1.30 {
|
522 kumpf 1.55 const Char16* s1c16 = s1.getChar16Data();
523 const Char16* s2c16 = s2.getChar16Data();
|
524 kumpf 1.43
525 while (*s1c16 && *s2c16)
|
526 mike 1.30 {
|
527 kumpf 1.43 int r = *s1c16++ - *s2c16++;
|
528 mike 1.30
529 if (r)
530 return r;
531 }
532
|
533 kumpf 1.43 if (*s2c16)
|
534 mike 1.30 return -1;
|
535 kumpf 1.43 else if (*s1c16)
|
536 mike 1.30 return 1;
537
538 return 0;
539 }
540
|
541 kumpf 1.40 int String::compareNoCase(const String& s1, const String& s2)
542 {
|
543 david 1.90 const char * noLocale = NULL;
544 return String::compareNoCase(s1, s2, noLocale);
545 }
546
547 int String::compareNoCase(const String& s1, const String& s2,const char * strLocale)
548 {
|
549 david 1.69 #ifdef PEGASUS_HAS_ICU
550 UnicodeString UniStr1((const UChar *)s1.getChar16Data(), (int32_t)s1.size());
551 UnicodeString UniStr2((const UChar *)s2.getChar16Data(), (int32_t)s2.size());
|
552 david 1.90 if(strLocale == NULL)
553 {
554 UniStr1.toLower();
555 UniStr2.toLower();
556 }
557 else
558 {
559 Locale loc(strLocale);
560 if(loc.isBogus())
561 {
562 throw InvalidNameException(String(strLocale));
563 }
564 UniStr1.toLower(loc);
565 UniStr2.toLower(loc);
566 }
|
567 chuck 1.89 // Note: the ICU 2.6.1 documentation for UnicodeString::compare( ) is
568 // backwards! The API actually returns +1 if this is greater than text.
569 // This is why the line below appears wrong based on the 2.6.1 docs.
570 // (ref. bugzilla 1207)
571 return (UniStr1.compare(UniStr2));
|
572 david 1.69 #else
|
573 kumpf 1.55 const Char16* _s1 = s1.getChar16Data();
574 const Char16* _s2 = s2.getChar16Data();
|
575 kumpf 1.40
576 while (*_s1 && *_s2)
577 {
578 int r;
579
|
580 kumpf 1.46 if (*_s1 <= PEGASUS_MAX_PRINTABLE_CHAR &&
581 *_s2 <= PEGASUS_MAX_PRINTABLE_CHAR)
|
582 kumpf 1.40 {
583 r = tolower(*_s1++) - tolower(*_s2++);
584 }
585 else
586 {
587 r = *_s1++ - *_s2++;
588 }
589
590 if (r)
591 return r;
592 }
593
594 if (*_s2)
595 return -1;
596 else if (*_s1)
597 return 1;
598
599 return 0;
|
600 david 1.69 #endif
|
601 kumpf 1.40 }
602
|
603 kumpf 1.39 Boolean String::equal(const String& str1, const String& str2)
|
604 mike 1.27 {
|
605 kumpf 1.43 return String::compare(str1, str2) == 0;
|
606 mike 1.27 }
607
|
608 kumpf 1.39 Boolean String::equalNoCase(const String& str1, const String& str2)
|
609 mike 1.27 {
|
610 david 1.90 const char * noLocale = NULL;
611 return String::equalNoCase(str1, str2, noLocale);
612 }
613
614 Boolean String::equalNoCase(const String& str1, const String& str2,const char * strLocale)
615 {
|
616 david 1.69 #ifdef PEGASUS_HAS_ICU
617 UnicodeString UniStr1((const UChar *)str1.getChar16Data(), (int32_t)str1.size());
618 UnicodeString UniStr2((const UChar *)str2.getChar16Data(), (int32_t)str2.size());
|
619 david 1.90 if(strLocale == NULL)
620 {
621 UniStr1.toLower();
622 UniStr2.toLower();
623 }
624 else
625 {
626 Locale loc(strLocale);
627 if(loc.isBogus())
628 {
629 throw InvalidNameException(String(strLocale));
630 }
631 UniStr1.toLower(loc);
632 UniStr2.toLower(loc);
633 }
|
634 david 1.69 return (UniStr1 == UniStr2);
635 #else
|
636 kumpf 1.39 if (str1.size() != str2.size())
637 return false;
638
|
639 kumpf 1.55 const Char16* p = str1.getChar16Data();
640 const Char16* q = str2.getChar16Data();
|
641 kumpf 1.39
642 Uint32 n = str1.size();
|
643 mike 1.27
|
644 kumpf 1.39 while (n--)
645 {
|
646 kumpf 1.46 if (*p <= PEGASUS_MAX_PRINTABLE_CHAR &&
647 *q <= PEGASUS_MAX_PRINTABLE_CHAR)
|
648 kumpf 1.39 {
649 if (tolower(*p++) != tolower(*q++))
650 return false;
651 }
652 else if (*p++ != *q++)
653 return false;
654 }
|
655 mike 1.28
|
656 kumpf 1.39 return true;
|
657 david 1.69 #endif
658 }
659
660 // UTF8 specific code:
|
661 david 1.90 String& String::assign(const char* str)
662 {
663 _rep->c16a.clear();
664 Uint32 n = strlen(str) + 1;
665
666 const Uint8 *strsrc = (Uint8 *)str;
667 Uint8 *endsrc = (Uint8 *)&str[n-1];
668
669 Char16 *msg16 = new Char16[n];
670 Uint16 *strtgt = (Uint16 *)msg16;
671 Uint16 *endtgt = (Uint16 *)&msg16[n];
672
673 UTF8toUTF16(&strsrc,
674 endsrc,
675 &strtgt,
676 endtgt);
677
678 Uint32 count;
679
680 for(count = 0; ((msg16[count]) != Char16(0x00)) && (count < (n - 1)); ++count);
681
682 david 1.90 _rep->c16a.append(msg16, count);
683
684 _rep->c16a.append('\0');
685
686 delete [] msg16;
687
688 return *this;
689 }
|
690 mike 1.27
|
691 david 1.90 CString String::getCString() const
|
692 david 1.69 {
|
693 david 1.79 Uint32 n = 3*size() + 1;
|
694 david 1.69 char* str = new char[n];
695
696 const Char16* msg16 = getChar16Data();
697
698 const Uint16 *strsrc = (Uint16 *)msg16;
|
699 david 1.71 Uint16 *endsrc = (Uint16 *)&msg16[size()+1];
|
700 david 1.69
701 Uint8 *strtgt = (Uint8 *)str;
702 Uint8 *endtgt = (Uint8 *)&str[n];
703
704 UTF16toUTF8 (&strsrc,
705 endsrc,
706 &strtgt,
707 endtgt);
708
|
709 david 1.71 char* str1 = new char[strlen(str)+1];
710 strcpy(str1,str);
|
711 david 1.72 delete [] str;
|
712 david 1.71
713 return CString(str1);
|
714 david 1.69 }
|
715 kumpf 1.42
|
716 kumpf 1.65 #if 0
|
717 kumpf 1.42 // ATTN-RK-P3-20020603: This code is not completely correct
|
718 karl 1.36 // Wildcard String matching function that may be useful in the future
719 // The following code was provided by Bob Blair.
720
721 /* _StringMatch Match input MatchString against a GLOB style pattern
722 Note that MatchChar is the char type so that this source
723 in portable to different string types. This is an internal function
724
725 Results: The return value is 1 if string matches pattern, and
726 0 otherwise. The matching operation permits the following
727 special characters in the pattern: *?\[] (see the manual
728 entry for details on what these mean).
|
729 chuck 1.78
|
730 karl 1.36
731 Side effects: None.
732 */
|
733 chuck 1.78
|
734 karl 1.36 /* MatchChar defined as a separate entity because this function source used
735 elsewhere was an unsigned char *. Here we use Uint16 to maintain 16 bit
736 size.
737 */
738 typedef Uint16 MatchChar;
739
740 inline Uint16 _ToLower(Uint16 ch)
741 {
|
742 david 1.69 // ICU_TODO: If ICU is available we should do this the correct way.
|
743 kumpf 1.46 return ch <= PEGASUS_MAX_PRINTABLE_CHAR ? tolower(char(ch)) : ch;
|
744 karl 1.36 }
745
746 inline Boolean _Equal(MatchChar ch1, MatchChar ch2, int nocase)
747 {
|
748 david 1.69 // ICU_TODO: If ICU is available we should do this the correct way.
|
749 karl 1.36 if (nocase)
750 return _ToLower(ch1) == _ToLower(ch2);
751 else
752 return ch1 == ch2;
753 }
|
754 mike 1.28
|
755 kumpf 1.35
|
756 karl 1.36 static const MatchChar *
757 _matchrange(const MatchChar *range, MatchChar c, int nocase)
758 {
759 const MatchChar *p = range;
760 const MatchChar *rstart = range + 1;
761 const MatchChar *rend = 0;
762 MatchChar compchar;
763
|
764 kumpf 1.35 for (rend = rstart; *rend && *rend != ']'; rend++);
|
765 karl 1.36 if (*rend == ']') { // if there is an end to this pattern
|
766 kumpf 1.35 for (compchar = *rstart; rstart != rend; rstart++) {
|
767 karl 1.36 if (_Equal(*rstart, c, nocase))
|
768 kumpf 1.35 return ++rend;
769 if (*rstart == '-') {
770 rstart++;
771 if (c >= compchar && c <= *rstart)
772 return ++rend;
773 }
774 }
775 }
|
776 karl 1.36 return (const MatchChar *)0;
|
777 kumpf 1.35 }
778
779 static int
|
780 karl 1.36 _StringMatch(
781 const MatchChar *testString,
782 const MatchChar *pattern,
783 int nocase ) /* Ignore case if this is true */
784 {
785 const MatchChar *pat = pattern;
786 const MatchChar *str = testString;
|
787 kumpf 1.35 unsigned int done = 0;
788 unsigned int res = 0; // the result: 1 == match
789
790 while (!done) { // main loop walks through pattern and test string
791 //cerr << "Comparing <" << *pat << "> and <" << *str << ">" << endl;
792 if (!*pat) { //end of pattern
793 done = 1; // we're done
794 if (!*str) //end of test, too?
795 res = 1; // then we matched
796 } else { //Not end of pattern
797 if (!*str) { // but end of test
798 done = 1; // We're done
799 if (*pat == '*') // If pattern openends
800 res = 1; // then we matched
801 } else { //Not end of test
802 if (*pat == '*') { //Ambiguuity found
803 if (!*++pat) { //and it ends pattern
804 done = 1; // then we're done
805 res = 1; // and match
806 } else { //if it doesn't end
807 while (!done) { // until we're done
|
808 karl 1.36 if (_StringMatch(str, pat, nocase)) { // we recurse
|
809 kumpf 1.35 done = 1; //if it recurses true
810 res = 1; // we done and match
811 } else { //it recurses false
812 if (!*str) // see if test is done
813 done = 1; // yes: we done
814 else // not done:
815 str++; // keep testing
816 } // end test on recursive call
817 } // end looping on recursive calls
818 } // end logic when pattern is ambiguous
819 } else { //pattern not ambiguus
820 if (*pat == '?') { //pattern is 'any'
821 pat++, str++; // so move along
822 } else if (*pat == '[') { //see if it's a range
|
823 karl 1.36 pat = _matchrange(pat, *str, nocase); // and is a match
|
824 kumpf 1.35 if (!pat) { //It is not a match
825 done = 1; // we're done
|
826 kumpf 1.42 res = 0; // no match
|
827 kumpf 1.35 } else { //Range matches
828 str++, pat++; // keep going
829 }
830 } else { // only case left is individual characters
|
831 karl 1.36 if (!_Equal(*pat++, *str++, nocase)) // if they don't match
|
832 kumpf 1.35 done = 1; // bail.
833 }
834 } // end ("pattern is not ambiguous (*)" logic
835 } // end logic when pattern and string still have data
836 } // end logic when pattern still has data
837 } // end main loop
838 return res;
839 }
840
|
841 kumpf 1.39
|
842 kumpf 1.65 /** match matches a string against a GLOB style pattern.
843 Return trues if the String parameter matches the pattern. C-Shell style
844 glob matching is used.
845 @param str String to be matched against the pattern
846 @param pattern Pattern to use in the match
847 @return Boolean true if str matches pattern
848 The pattern definition is as follows:
849 <pre>
850 * Matches any number of any characters
851 ? Match exactly one character
852 [chars] Match any character in chars
853 [chara-charb] Match any character in the range between chara and charb
854 </pre>
855 The literal characters *, ?, [, ] can be included in a string by
856 escaping them with backslash "\". Ranges of characters can be concatenated.
857 <pre>
858 examples:
859 Boolean result = String::match("This is a test", "*is*");
860 Boolean works = String::match("abcdef123", "*[0-9]");
861 </pre>
862 */
|
863 karl 1.36 Boolean String::match(const String& str, const String& pattern)
864 {
865 return _StringMatch(
|
866 kumpf 1.55 (Uint16*)str.getChar16Data(), (Uint16*)pattern.getChar16Data(), 0) != 0;
|
867 karl 1.36 }
868
|
869 kumpf 1.65 /** matchNoCase Matches a String against a GLOB style pattern independent
870 of case.
871 Returns true if the str parameter matches the pattern. C-Shell style
872 glob matching is used. Ignore case in all comparisons. Case is
873 ignored in the match.
874 @parm str String containing the string to be matched\
875 @parm pattern GLOB style patterh to use in the match.
876 @return Boolean true if str matches patterh
877 @SeeAlso match
878 */
|
879 karl 1.36 Boolean String::matchNoCase(const String& str, const String& pattern)
880 {
881 return _StringMatch(
|
882 kumpf 1.55 (Uint16*)str.getChar16Data(), (Uint16*)pattern.getChar16Data(), 1) != 0;
|
883 kumpf 1.39 }
|
884 kumpf 1.65 #endif
|
885 kumpf 1.39
886
887 ///////////////////////////////////////////////////////////////////////////////
888 //
889 // String-related functions
890 //
891 ///////////////////////////////////////////////////////////////////////////////
892
893 Boolean operator==(const String& str1, const String& str2)
894 {
895 return String::equal(str1, str2);
896 }
897
898 Boolean operator==(const String& str1, const char* str2)
899 {
900 return String::equal(str1, str2);
901 }
902
903 Boolean operator==(const char* str1, const String& str2)
904 {
905 return String::equal(str1, str2);
906 kumpf 1.39 }
907
908 Boolean operator!=(const String& str1, const String& str2)
909 {
910 return !String::equal(str1, str2);
911 }
912
|
913 kumpf 1.47 PEGASUS_STD(ostream)& operator<<(PEGASUS_STD(ostream)& os, const String& str)
|
914 kumpf 1.39 {
|
915 david 1.72
|
916 david 1.69 #if defined(PEGASUS_OS_OS400)
|
917 david 1.93 CString cstr = str.getCString();
|
918 david 1.69 const char* utf8str = cstr;
919
920 os << utf8str;
921
|
922 humberto 1.76 #elif defined(PEGASUS_HAS_ICU)
|
923 humberto 1.83 if(os == cout || os == cerr){
924 char *buf = NULL;
925 const int size = str.size() * 6;
926 UnicodeString UniStr((const UChar *)str.getChar16Data(), (int32_t)str.size());
927 Uint32 bufsize = UniStr.extract(0,size,buf);
928
929 buf = new char[bufsize+1];
930 UniStr.extract(0,bufsize,buf);
931 os << buf;
932 os.flush();
933 delete [] buf;
934 }else{
|
935 david 1.93 CString cstr = str.getCString();
|
936 humberto 1.83 const char* utf8str = cstr;
937 os << utf8str;
938 }
|
939 humberto 1.76
|
940 david 1.69 #else
|
941 humberto 1.83 for (Uint32 i = 0, n = str.size(); i < n; i++)
942 {
943 Uint16 code = str[i];
|
944 david 1.69
|
945 humberto 1.83 if (code > 0 && code <= PEGASUS_MAX_PRINTABLE_CHAR)
946 {
947 os << char(code);
948 }
949 else
950 {
951 // Print in hex format:
952 char buffer[8];
953 sprintf(buffer, "\\x%04X", code);
954 os << buffer;
955 }
956 }
|
957 david 1.69 #endif // End of PEGASUS_HAS_ICU #else leg.
|
958 kumpf 1.39
959 return os;
960 }
961
962 String operator+(const String& str1, const String& str2)
963 {
964 return String(str1).append(str2);
965 }
966
967 Boolean operator<(const String& str1, const String& str2)
968 {
|
969 kumpf 1.43 return String::compare(str1, str2) < 0;
|
970 kumpf 1.39 }
971
972 Boolean operator<=(const String& str1, const String& str2)
973 {
|
974 kumpf 1.43 return String::compare(str1, str2) <= 0;
|
975 kumpf 1.39 }
976
977 Boolean operator>(const String& str1, const String& str2)
978 {
|
979 kumpf 1.43 return String::compare(str1, str2) > 0;
|
980 kumpf 1.39 }
981
982 Boolean operator>=(const String& str1, const String& str2)
983 {
|
984 kumpf 1.43 return String::compare(str1, str2) >= 0;
|
985 kumpf 1.39 }
986
|
987 mike 1.27 PEGASUS_NAMESPACE_END
|