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