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