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