1 mike 1.27 //%/////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2000, 2001 The Open group, BMC Software, Tivoli Systems, IBM
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to
7 // deal in the Software without restriction, including without limitation the
8 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 // sell copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
13 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
14 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
15 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
16 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
17 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
18 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
19 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 //
21 //==============================================================================
22 mike 1.27 //
23 // Author: Mike Brasher (mbrasher@bmc.com)
24 //
25 // Modified By:
26 //
27 //%/////////////////////////////////////////////////////////////////////////////
28
29
30 #include <cctype>
31 #include "String.h"
32 #include "Exception.h"
33 #include "String.h"
34 #include <iostream>
35
36 PEGASUS_NAMESPACE_BEGIN
37
38 #define PEGASUS_ARRAY_T String
39 #include <Pegasus/Common/ArrayImpl.h>
40 #undef PEGASUS_ARRAY_T
41
42 const String String::EMPTY;
43 mike 1.27
44 static inline void _SkipWhitespace(const Char16*& p)
45 {
46 while (*p && isspace(*p))
47 p++;
48 }
49
50 inline Uint32 StrLen(const char* str)
51 {
52 if (!str)
53 throw NullPointer();
54
55 return strlen(str);
56 }
57
58 inline Uint32 StrLen(const Char16* str)
59 {
60 if (!str)
61 throw NullPointer();
62
63 Uint32 n = 0;
64 mike 1.27
65 while (*str++)
66 n++;
67
68 return n;
69 }
70
71 String::String()
72 {
73 _rep.append('\0');
74 }
75
76 String::String(const String& x) : _rep(x._rep)
77 {
78
79 }
80
81 String::String(const String& x, Uint32 n)
82 {
83 _rep.append('\0');
84 append(x.getData(), n);
85 mike 1.27 }
86
87 String::String(const Char16* x) : _rep(x, StrLen(x) + 1)
88 {
89
90 }
91
92 String::String(const Char16* x, Uint32 n)
93 {
94 assign(x, n);
95 }
96
97 String::String(const char* str)
98 {
99 Uint32 n = ::strlen(str) + 1;
100 reserve(n);
101
102 while (n--)
103 _rep.append(*str++);
104 }
105
106 mike 1.27 String::String(const char* str, Uint32 n_)
107 {
108 Uint32 n = _min(strlen(str), n_);
109 reserve(n + 1);
110
111 while (n--)
112 _rep.append(*str++);
113
114 _rep.append('\0');
115 }
116
117 String& String::assign(const Char16* x)
118 {
119 _rep.clear();
120 _rep.append(x, StrLen(x) + 1);
121 return *this;
122 }
123
124 String& String::assign(const Char16* str, Uint32 n)
125 {
126 _rep.clear();
127 mike 1.27 Uint32 m = _min(StrLen(str), n);
128 _rep.append(str, m);
129 _rep.append('\0');
130 return *this;
131 }
132
133 String& String::assign(const char* x)
134 {
135 _rep.clear();
136 Uint32 n = strlen(x);
137 _rep.reserve(n + 1);
138
139 while (n--)
140 _rep.append(*x++);
141
142 _rep.append('\0');
143
144 return *this;
145 }
146
147 String& String::assign(const char* x, Uint32 n_)
148 mike 1.27 {
149 _rep.clear();
150
151 Uint32 n = _min(strlen(x), n_);
152 _rep.reserve(n + 1);
153
154 while (n--)
155 _rep.append(*x++);
156
157 _rep.append('\0');
158
159 return *this;
160 }
161
162 char* String::allocateCString(Uint32 extraBytes, Boolean noThrow) const
163 {
164 Uint32 n = size() + 1;
165 char* str = new char[n + extraBytes];
166 char* p = str;
167 const Char16* q = getData();
168
169 mike 1.27 for (Uint32 i = 0; i < n; i++)
170 {
171 Uint16 c = *q++;
172 *p++ = char(c);
173
174 if ((c & 0xff00) && !noThrow)
175 throw TruncatedCharacter();
176 }
177
178 return str;
179 }
180
181 void String::appendToCString(
182 char* str,
183 Uint32 length,
184 Boolean noThrow) const
185 {
186 if (!str)
187 throw NullPointer();
188
189 Uint32 n = _min(size(), length);
190 mike 1.27
191 char* p = str + strlen(str);
192 const Char16* q = getData();
193
194 for (Uint32 i = 0; i < n; i++)
195 {
196 Uint16 c = *q++;
197 *p++ = char(c);
198
199 if ((c & 0xff00) && !noThrow)
200 throw TruncatedCharacter();
201 }
202
203 *p = '\0';
204 }
205
206 Char16& String::operator[](Uint32 i)
207 {
208 if (i > size())
209 ThrowOutOfBounds();
210
211 mike 1.27 return _rep[i];
212 }
213
214 const Char16 String::operator[](Uint32 i) const
215 {
216 if (i > size())
217 ThrowOutOfBounds();
218
219 return _rep[i];
220 }
221
222 String& String::append(const Char16* str, Uint32 n)
223 {
224 Uint32 m = _min(StrLen(str), n);
225 _rep.reserve(_rep.size() + m);
226 _rep.remove(_rep.size() - 1);
227 _rep.append(str, m);
228 _rep.append('\0');
229 return *this;
230 }
231
232 mike 1.27 void String::remove(Uint32 pos, Uint32 size)
233 {
234 if (size == PEG_NOT_FOUND)
235 size = this->size() - pos;
236
237 if (pos + size > this->size())
238 ThrowOutOfBounds();
239
240 if (size)
241 _rep.remove(pos, size);
242 }
243
244 int String::compare(const Char16* s1, const Char16* s2, Uint32 n)
245 {
246 while (n--)
247 {
248 int r = *s1++ - *s2++;
249
250 if (r)
251 return r;
252 }
253 mike 1.27
254 return 0;
255 }
256
257 int String::compareNoCase(const char* s1, const char* s2, Uint32 n)
258 {
259 while (n--)
260 {
261 int r = tolower(*s1++) - tolower(*s2++);
262
263 if (r)
264 return r;
265 }
266
267 return 0;
268 }
269
270 Boolean String::equal(const String& x, const String& y)
271 {
272 if (x.size() != y.size())
273 return false;
274 mike 1.27
275 return String::compare(x.getData(), y.getData(), x.size()) == 0;
276 }
277
278 Boolean String::equal(const String& x, const Char16* y)
279 {
280 if (x.size() != StrLen(y))
281 return false;
282
283 return String::compare(x.getData(), y, x.size()) == 0;
284 }
285
286 Boolean String::equal(const Char16* x, const String& y)
287 {
288 return equal(y, x);
289 }
290
291 Boolean String::equal(const String& x, const char* y)
292 {
293 return equal(x, String(y));
294 }
295 mike 1.27
296 Boolean String::equal(const char* x, const String& y)
297 {
298 return equal(String(x), y);
299 }
300
301 Boolean String::equalNoCase(const String& x, const String& y)
302 {
303 if (x.size() != y.size())
304 return false;
305
306 const Char16* p = x.getData();
307 const Char16* q = y.getData();
308
309 Uint32 n = x.size();
310
311 while (n--)
312 {
313 if (*p <= 127 && *q <= 127)
314 {
315 if (tolower(*p++) != tolower(*q++))
316 mike 1.27 return false;
317 }
318 else if (*p++ != *q++)
319 return false;
320 }
321
322 return true;
323 }
324
325 String String::subString(Uint32 pos, Uint32 length) const
326 {
327 if (pos < size())
328 {
329 if (length == PEG_NOT_FOUND)
330 length = size() - pos;
331
332 return String(getData() + pos, length);
333 }
334 else
335 return String();
336 }
337 mike 1.27
338 Uint32 String::find(Char16 c) const
339 {
340 const Char16* first = getData();
341
342 for (const Char16* p = first; *p; p++)
343 {
344 if (*p == c)
345 return p - first;
346 }
347
348 return PEG_NOT_FOUND;
349 }
350
351 Uint32 String::find(const String& s) const
352 {
353 const Char16* pSubStr = s.getData();
354 const Char16* pStr = getData();
355 Uint32 subStrLen = s.size();
356 Uint32 strLen = size();
357
358 mike 1.27 // loop to find first char match
359 Uint32 loc = 0;
360 for( ; loc <= (strLen-subStrLen); loc++)
361 {
362 if (*pStr++ == *pSubStr) // match first char
363 {
364 // point to substr 2nd char
365 const Char16* p = pSubStr + 1;
366
367 // Test remaining chars for equal
368 Uint32 i = 1;
369 for (; i < subStrLen; i++)
370 if (*pStr++ != *p++ )
371 {pStr--; break;} // break from loop
372 if (i == subStrLen)
373 return loc;
374 }
375 }
376 return PEG_NOT_FOUND;
377 }
378
379 mike 1.27 // ATTN:KS 5 apr 2000 Need to add the Char16* version.
380 Uint32 String::find(const char* s) const
381 {
382 return find(String(s));
383 }
384
385 Uint32 String::reverseFind(Char16 c) const
386 {
387 const Char16* first = getData();
388 const Char16* last = getData() + size();
389
390 while (last != first)
391 {
392 if (*--last == c)
393 return last - first;
394 }
395
396 return PEG_NOT_FOUND;
397 }
398
399 void String::toLower()
400 mike 1.27 {
401 for (Char16* p = &_rep[0]; *p; p++)
402 {
403 if (*p <= 127)
404 *p = tolower(*p);
405 }
406 }
407
408 void String::translate(Char16 fromChar, Char16 toChar)
409 {
410 for (Char16* p = &_rep[0]; *p; p++)
411 {
412 if (*p == fromChar)
413 *p = toChar;
414 }
415 }
416
417 int String::compare(const Char16* s1, const Char16* s2)
418 {
419 while (*s1 && *s2)
420 {
421 mike 1.27 int r = *s1++ - *s2++;
422
423 if (r)
424 return r;
425 }
426
427 if (*s2)
428 return -1;
429 else if (*s1)
430 return 1;
431
432 return 0;
433 }
434
435 PEGASUS_STD(ostream)& operator<<(PEGASUS_STD(ostream)& os, const String& x)
436 {
437 for (Uint32 i = 0, n = x.size(); i < n; i++)
438 os << x[i];
439
440 return os;
441 }
442 mike 1.27
443 void String::toLower(char* str)
444 {
445 while (*str)
446 tolower(*str++);
447 }
448
449 String ToLower(const String& str)
450 {
451 String tmp(str);
452
453 for (Uint32 i = 0, n = tmp.size(); i < n; i++)
454 {
455 Char16 c = tmp[i];
456
457 if (c <= 127)
458 tmp[i] = tolower(c);
459 }
460
461 return tmp;
462 }
463 mike 1.27
464 int CompareNoCase(const char* s1, const char* s2)
465 {
466 while (*s1 && *s2)
467 {
468 int r = tolower(*s1++) - tolower(*s2++);
469
470 if (r)
471 return r;
472 }
473
474 if (*s2)
475 return -1;
476 else if (*s1)
477 return 1;
478
479 return 0;
480 }
481
482 Boolean GetLine(PEGASUS_STD(istream)& is, String& line)
483 {
484 mike 1.27 line.clear();
485
486 Boolean gotChar = false;
487 char c;
488
489 while (is.get(c))
490 {
491 gotChar = true;
492
493 if (c == '\n')
494 break;
495
496 line.append(c);
497 }
498
499 return gotChar;
500 }
501
502 String::~String()
503 {
504 }
505 mike 1.27
506 String& String::assign(const String& x)
507 {
508 _rep = x._rep;
509 return *this;
510 }
511
512 String& String::append(const Char16& c)
513 {
514 _rep.insert(_rep.size() - 1, c);
515 return *this;
516 }
517
518 void String::clear()
519 {
520 _rep.clear();
521 _rep.append('\0');
522 }
523
524 void String::reserve(Uint32 capacity)
525 {
526 mike 1.27 _rep.reserve(capacity + 1);
527 }
528
529 const Array<String>& EmptyStringArray()
530 {
531 static Array<String> tmp;
532 return tmp;
533 }
534
535 PEGASUS_NAMESPACE_END
|