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 david 1.91 #else
509 for (Char16* p = &_rep->c16a[0]; *p; p++)
510 {
511 if (*p <= PEGASUS_MAX_PRINTABLE_CHAR)
512 *p = toupper(*p);
513 }
|
514 david 1.90 #endif
515 }
516
|
517 kumpf 1.43 int String::compare(const String& s1, const String& s2, Uint32 n)
|
518 kumpf 1.39 {
|
519 kumpf 1.55 const Char16* s1c16 = s1.getChar16Data();
520 const Char16* s2c16 = s2.getChar16Data();
|
521 kumpf 1.39
522 while (n--)
|
523 mike 1.27 {
|
524 kumpf 1.43 int r = *s1c16++ - *s2c16++;
|
525 mike 1.27
526 if (r)
527 return r;
528 }
529
530 return 0;
531 }
532
|
533 kumpf 1.43 int String::compare(const String& s1, const String& s2)
|
534 mike 1.30 {
|
535 kumpf 1.55 const Char16* s1c16 = s1.getChar16Data();
536 const Char16* s2c16 = s2.getChar16Data();
|
537 kumpf 1.43
538 while (*s1c16 && *s2c16)
|
539 mike 1.30 {
|
540 kumpf 1.43 int r = *s1c16++ - *s2c16++;
|
541 mike 1.30
542 if (r)
543 return r;
544 }
545
|
546 kumpf 1.43 if (*s2c16)
|
547 mike 1.30 return -1;
|
548 kumpf 1.43 else if (*s1c16)
|
549 mike 1.30 return 1;
550
551 return 0;
552 }
553
|
554 kumpf 1.40 int String::compareNoCase(const String& s1, const String& s2)
555 {
|
556 david 1.90 const char * noLocale = NULL;
557 return String::compareNoCase(s1, s2, noLocale);
558 }
559
560 int String::compareNoCase(const String& s1, const String& s2,const char * strLocale)
561 {
|
562 david 1.69 #ifdef PEGASUS_HAS_ICU
563 UnicodeString UniStr1((const UChar *)s1.getChar16Data(), (int32_t)s1.size());
564 UnicodeString UniStr2((const UChar *)s2.getChar16Data(), (int32_t)s2.size());
|
565 david 1.90 if(strLocale == NULL)
566 {
567 UniStr1.toLower();
568 UniStr2.toLower();
569 }
570 else
571 {
572 Locale loc(strLocale);
573 if(loc.isBogus())
574 {
575 throw InvalidNameException(String(strLocale));
576 }
577 UniStr1.toLower(loc);
578 UniStr2.toLower(loc);
579 }
|
580 chuck 1.89 // Note: the ICU 2.6.1 documentation for UnicodeString::compare( ) is
581 // backwards! The API actually returns +1 if this is greater than text.
582 // This is why the line below appears wrong based on the 2.6.1 docs.
583 // (ref. bugzilla 1207)
584 return (UniStr1.compare(UniStr2));
|
585 david 1.69 #else
|
586 kumpf 1.55 const Char16* _s1 = s1.getChar16Data();
587 const Char16* _s2 = s2.getChar16Data();
|
588 kumpf 1.40
589 while (*_s1 && *_s2)
590 {
591 int r;
592
|
593 kumpf 1.46 if (*_s1 <= PEGASUS_MAX_PRINTABLE_CHAR &&
594 *_s2 <= PEGASUS_MAX_PRINTABLE_CHAR)
|
595 kumpf 1.40 {
596 r = tolower(*_s1++) - tolower(*_s2++);
597 }
598 else
599 {
600 r = *_s1++ - *_s2++;
601 }
602
603 if (r)
604 return r;
605 }
606
607 if (*_s2)
608 return -1;
609 else if (*_s1)
610 return 1;
611
612 return 0;
|
613 david 1.69 #endif
|
614 kumpf 1.40 }
615
|
616 kumpf 1.39 Boolean String::equal(const String& str1, const String& str2)
|
617 mike 1.27 {
|
618 kumpf 1.43 return String::compare(str1, str2) == 0;
|
619 mike 1.27 }
620
|
621 kumpf 1.39 Boolean String::equalNoCase(const String& str1, const String& str2)
|
622 mike 1.27 {
|
623 david 1.90 const char * noLocale = NULL;
624 return String::equalNoCase(str1, str2, noLocale);
625 }
626
627 Boolean String::equalNoCase(const String& str1, const String& str2,const char * strLocale)
628 {
|
629 david 1.69 #ifdef PEGASUS_HAS_ICU
630 UnicodeString UniStr1((const UChar *)str1.getChar16Data(), (int32_t)str1.size());
631 UnicodeString UniStr2((const UChar *)str2.getChar16Data(), (int32_t)str2.size());
|
632 david 1.90 if(strLocale == NULL)
633 {
634 UniStr1.toLower();
635 UniStr2.toLower();
636 }
637 else
638 {
639 Locale loc(strLocale);
640 if(loc.isBogus())
641 {
642 throw InvalidNameException(String(strLocale));
643 }
644 UniStr1.toLower(loc);
645 UniStr2.toLower(loc);
646 }
|
647 david 1.69 return (UniStr1 == UniStr2);
648 #else
|
649 kumpf 1.39 if (str1.size() != str2.size())
650 return false;
651
|
652 kumpf 1.55 const Char16* p = str1.getChar16Data();
653 const Char16* q = str2.getChar16Data();
|
654 kumpf 1.39
655 Uint32 n = str1.size();
|
656 mike 1.27
|
657 kumpf 1.39 while (n--)
658 {
|
659 kumpf 1.46 if (*p <= PEGASUS_MAX_PRINTABLE_CHAR &&
660 *q <= PEGASUS_MAX_PRINTABLE_CHAR)
|
661 kumpf 1.39 {
662 if (tolower(*p++) != tolower(*q++))
663 return false;
664 }
665 else if (*p++ != *q++)
666 return false;
667 }
|
668 mike 1.28
|
669 kumpf 1.39 return true;
|
670 david 1.69 #endif
671 }
672
673 // UTF8 specific code:
|
674 david 1.90 String& String::assign(const char* str)
675 {
676 _rep->c16a.clear();
677 Uint32 n = strlen(str) + 1;
678
679 const Uint8 *strsrc = (Uint8 *)str;
680 Uint8 *endsrc = (Uint8 *)&str[n-1];
681
682 Char16 *msg16 = new Char16[n];
683 Uint16 *strtgt = (Uint16 *)msg16;
684 Uint16 *endtgt = (Uint16 *)&msg16[n];
685
686 UTF8toUTF16(&strsrc,
687 endsrc,
688 &strtgt,
689 endtgt);
690
691 Uint32 count;
692
693 for(count = 0; ((msg16[count]) != Char16(0x00)) && (count < (n - 1)); ++count);
694
695 david 1.90 _rep->c16a.append(msg16, count);
696
697 _rep->c16a.append('\0');
698
699 delete [] msg16;
700
701 return *this;
702 }
|
703 mike 1.27
|
704 david 1.90 CString String::getCString() const
|
705 david 1.69 {
|
706 david 1.79 Uint32 n = 3*size() + 1;
|
707 david 1.69 char* str = new char[n];
708
709 const Char16* msg16 = getChar16Data();
710
711 const Uint16 *strsrc = (Uint16 *)msg16;
|
712 david 1.71 Uint16 *endsrc = (Uint16 *)&msg16[size()+1];
|
713 david 1.69
714 Uint8 *strtgt = (Uint8 *)str;
715 Uint8 *endtgt = (Uint8 *)&str[n];
716
717 UTF16toUTF8 (&strsrc,
718 endsrc,
719 &strtgt,
720 endtgt);
721
|
722 david 1.71 char* str1 = new char[strlen(str)+1];
723 strcpy(str1,str);
|
724 david 1.72 delete [] str;
|
725 david 1.71
726 return CString(str1);
|
727 david 1.69 }
|
728 kumpf 1.42
|
729 kumpf 1.65 #if 0
|
730 kumpf 1.42 // ATTN-RK-P3-20020603: This code is not completely correct
|
731 karl 1.36 // Wildcard String matching function that may be useful in the future
732 // The following code was provided by Bob Blair.
733
734 /* _StringMatch Match input MatchString against a GLOB style pattern
735 Note that MatchChar is the char type so that this source
736 in portable to different string types. This is an internal function
737
738 Results: The return value is 1 if string matches pattern, and
739 0 otherwise. The matching operation permits the following
740 special characters in the pattern: *?\[] (see the manual
741 entry for details on what these mean).
|
742 chuck 1.78
|
743 karl 1.36
744 Side effects: None.
745 */
|
746 chuck 1.78
|
747 karl 1.36 /* MatchChar defined as a separate entity because this function source used
748 elsewhere was an unsigned char *. Here we use Uint16 to maintain 16 bit
749 size.
750 */
751 typedef Uint16 MatchChar;
752
753 inline Uint16 _ToLower(Uint16 ch)
754 {
|
755 david 1.69 // ICU_TODO: If ICU is available we should do this the correct way.
|
756 kumpf 1.46 return ch <= PEGASUS_MAX_PRINTABLE_CHAR ? tolower(char(ch)) : ch;
|
757 karl 1.36 }
758
759 inline Boolean _Equal(MatchChar ch1, MatchChar ch2, int nocase)
760 {
|
761 david 1.69 // ICU_TODO: If ICU is available we should do this the correct way.
|
762 karl 1.36 if (nocase)
763 return _ToLower(ch1) == _ToLower(ch2);
764 else
765 return ch1 == ch2;
766 }
|
767 mike 1.28
|
768 kumpf 1.35
|
769 karl 1.36 static const MatchChar *
770 _matchrange(const MatchChar *range, MatchChar c, int nocase)
771 {
772 const MatchChar *p = range;
773 const MatchChar *rstart = range + 1;
774 const MatchChar *rend = 0;
775 MatchChar compchar;
776
|
777 kumpf 1.35 for (rend = rstart; *rend && *rend != ']'; rend++);
|
778 karl 1.36 if (*rend == ']') { // if there is an end to this pattern
|
779 kumpf 1.35 for (compchar = *rstart; rstart != rend; rstart++) {
|
780 karl 1.36 if (_Equal(*rstart, c, nocase))
|
781 kumpf 1.35 return ++rend;
782 if (*rstart == '-') {
783 rstart++;
784 if (c >= compchar && c <= *rstart)
785 return ++rend;
786 }
787 }
788 }
|
789 karl 1.36 return (const MatchChar *)0;
|
790 kumpf 1.35 }
791
792 static int
|
793 karl 1.36 _StringMatch(
794 const MatchChar *testString,
795 const MatchChar *pattern,
796 int nocase ) /* Ignore case if this is true */
797 {
798 const MatchChar *pat = pattern;
799 const MatchChar *str = testString;
|
800 kumpf 1.35 unsigned int done = 0;
801 unsigned int res = 0; // the result: 1 == match
802
803 while (!done) { // main loop walks through pattern and test string
804 //cerr << "Comparing <" << *pat << "> and <" << *str << ">" << endl;
805 if (!*pat) { //end of pattern
806 done = 1; // we're done
807 if (!*str) //end of test, too?
808 res = 1; // then we matched
809 } else { //Not end of pattern
810 if (!*str) { // but end of test
811 done = 1; // We're done
812 if (*pat == '*') // If pattern openends
813 res = 1; // then we matched
814 } else { //Not end of test
815 if (*pat == '*') { //Ambiguuity found
816 if (!*++pat) { //and it ends pattern
817 done = 1; // then we're done
818 res = 1; // and match
819 } else { //if it doesn't end
820 while (!done) { // until we're done
|
821 karl 1.36 if (_StringMatch(str, pat, nocase)) { // we recurse
|
822 kumpf 1.35 done = 1; //if it recurses true
823 res = 1; // we done and match
824 } else { //it recurses false
825 if (!*str) // see if test is done
826 done = 1; // yes: we done
827 else // not done:
828 str++; // keep testing
829 } // end test on recursive call
830 } // end looping on recursive calls
831 } // end logic when pattern is ambiguous
832 } else { //pattern not ambiguus
833 if (*pat == '?') { //pattern is 'any'
834 pat++, str++; // so move along
835 } else if (*pat == '[') { //see if it's a range
|
836 karl 1.36 pat = _matchrange(pat, *str, nocase); // and is a match
|
837 kumpf 1.35 if (!pat) { //It is not a match
838 done = 1; // we're done
|
839 kumpf 1.42 res = 0; // no match
|
840 kumpf 1.35 } else { //Range matches
841 str++, pat++; // keep going
842 }
843 } else { // only case left is individual characters
|
844 karl 1.36 if (!_Equal(*pat++, *str++, nocase)) // if they don't match
|
845 kumpf 1.35 done = 1; // bail.
846 }
847 } // end ("pattern is not ambiguous (*)" logic
848 } // end logic when pattern and string still have data
849 } // end logic when pattern still has data
850 } // end main loop
851 return res;
852 }
853
|
854 kumpf 1.39
|
855 kumpf 1.65 /** match matches a string against a GLOB style pattern.
856 Return trues if the String parameter matches the pattern. C-Shell style
857 glob matching is used.
858 @param str String to be matched against the pattern
859 @param pattern Pattern to use in the match
860 @return Boolean true if str matches pattern
861 The pattern definition is as follows:
862 <pre>
863 * Matches any number of any characters
864 ? Match exactly one character
865 [chars] Match any character in chars
866 [chara-charb] Match any character in the range between chara and charb
867 </pre>
868 The literal characters *, ?, [, ] can be included in a string by
869 escaping them with backslash "\". Ranges of characters can be concatenated.
870 <pre>
871 examples:
872 Boolean result = String::match("This is a test", "*is*");
873 Boolean works = String::match("abcdef123", "*[0-9]");
874 </pre>
875 */
|
876 karl 1.36 Boolean String::match(const String& str, const String& pattern)
877 {
878 return _StringMatch(
|
879 kumpf 1.55 (Uint16*)str.getChar16Data(), (Uint16*)pattern.getChar16Data(), 0) != 0;
|
880 karl 1.36 }
881
|
882 kumpf 1.65 /** matchNoCase Matches a String against a GLOB style pattern independent
883 of case.
884 Returns true if the str parameter matches the pattern. C-Shell style
885 glob matching is used. Ignore case in all comparisons. Case is
886 ignored in the match.
887 @parm str String containing the string to be matched\
888 @parm pattern GLOB style patterh to use in the match.
889 @return Boolean true if str matches patterh
890 @SeeAlso match
891 */
|
892 karl 1.36 Boolean String::matchNoCase(const String& str, const String& pattern)
893 {
894 return _StringMatch(
|
895 kumpf 1.55 (Uint16*)str.getChar16Data(), (Uint16*)pattern.getChar16Data(), 1) != 0;
|
896 kumpf 1.39 }
|
897 kumpf 1.65 #endif
|
898 kumpf 1.39
899
900 ///////////////////////////////////////////////////////////////////////////////
901 //
902 // String-related functions
903 //
904 ///////////////////////////////////////////////////////////////////////////////
905
906 Boolean operator==(const String& str1, const String& str2)
907 {
908 return String::equal(str1, str2);
909 }
910
911 Boolean operator==(const String& str1, const char* str2)
912 {
913 return String::equal(str1, str2);
914 }
915
916 Boolean operator==(const char* str1, const String& str2)
917 {
918 return String::equal(str1, str2);
919 kumpf 1.39 }
920
921 Boolean operator!=(const String& str1, const String& str2)
922 {
923 return !String::equal(str1, str2);
924 }
925
|
926 kumpf 1.47 PEGASUS_STD(ostream)& operator<<(PEGASUS_STD(ostream)& os, const String& str)
|
927 kumpf 1.39 {
|
928 david 1.72
|
929 david 1.69 #if defined(PEGASUS_OS_OS400)
|
930 david 1.93 CString cstr = str.getCString();
|
931 david 1.69 const char* utf8str = cstr;
932
933 os << utf8str;
934
|
935 humberto 1.76 #elif defined(PEGASUS_HAS_ICU)
|
936 humberto 1.83 if(os == cout || os == cerr){
937 char *buf = NULL;
938 const int size = str.size() * 6;
939 UnicodeString UniStr((const UChar *)str.getChar16Data(), (int32_t)str.size());
940 Uint32 bufsize = UniStr.extract(0,size,buf);
941
942 buf = new char[bufsize+1];
943 UniStr.extract(0,bufsize,buf);
944 os << buf;
945 os.flush();
946 delete [] buf;
947 }else{
|
948 david 1.93 CString cstr = str.getCString();
|
949 humberto 1.83 const char* utf8str = cstr;
950 os << utf8str;
951 }
|
952 humberto 1.76
|
953 david 1.69 #else
|
954 humberto 1.83 for (Uint32 i = 0, n = str.size(); i < n; i++)
955 {
956 Uint16 code = str[i];
|
957 david 1.69
|
958 humberto 1.83 if (code > 0 && code <= PEGASUS_MAX_PRINTABLE_CHAR)
959 {
960 os << char(code);
961 }
962 else
963 {
964 // Print in hex format:
965 char buffer[8];
966 sprintf(buffer, "\\x%04X", code);
967 os << buffer;
968 }
969 }
|
970 david 1.69 #endif // End of PEGASUS_HAS_ICU #else leg.
|
971 kumpf 1.39
972 return os;
973 }
974
975 String operator+(const String& str1, const String& str2)
976 {
977 return String(str1).append(str2);
978 }
979
980 Boolean operator<(const String& str1, const String& str2)
981 {
|
982 kumpf 1.43 return String::compare(str1, str2) < 0;
|
983 kumpf 1.39 }
984
985 Boolean operator<=(const String& str1, const String& str2)
986 {
|
987 kumpf 1.43 return String::compare(str1, str2) <= 0;
|
988 kumpf 1.39 }
989
990 Boolean operator>(const String& str1, const String& str2)
991 {
|
992 kumpf 1.43 return String::compare(str1, str2) > 0;
|
993 kumpf 1.39 }
994
995 Boolean operator>=(const String& str1, const String& str2)
996 {
|
997 kumpf 1.43 return String::compare(str1, str2) >= 0;
|
998 kumpf 1.39 }
999
|
1000 kumpf 1.86 #ifdef PEGASUS_USE_DEPRECATED_INTERFACES
|
1001 kumpf 1.39 int CompareNoCase(const char* s1, const char* s2)
1002 {
|
1003 kumpf 1.60 return System::strcasecmp(s1, s2);
|
1004 kumpf 1.39 }
|
1005 kumpf 1.60 #endif
|
1006 kumpf 1.39
|
1007 mike 1.27 PEGASUS_NAMESPACE_END
|