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