Mercurial > projects > hoofbaby
comparison deps/Platinum/ThirdParty/Neptune/Source/Core/NptStrings.cpp @ 0:3425707ddbf6
Initial import (hopefully this mercurial stuff works...)
author | fraserofthenight |
---|---|
date | Mon, 06 Jul 2009 08:06:28 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:3425707ddbf6 |
---|---|
1 /***************************************************************** | |
2 | | |
3 | Neptune - String Objects | |
4 | | |
5 | Copyright (c) 2002-2008, Axiomatic Systems, LLC. | |
6 | All rights reserved. | |
7 | | |
8 | Redistribution and use in source and binary forms, with or without | |
9 | modification, are permitted provided that the following conditions are met: | |
10 | * Redistributions of source code must retain the above copyright | |
11 | notice, this list of conditions and the following disclaimer. | |
12 | * Redistributions in binary form must reproduce the above copyright | |
13 | notice, this list of conditions and the following disclaimer in the | |
14 | documentation and/or other materials provided with the distribution. | |
15 | * Neither the name of Axiomatic Systems nor the | |
16 | names of its contributors may be used to endorse or promote products | |
17 | derived from this software without specific prior written permission. | |
18 | | |
19 | THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY | |
20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
22 | DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY | |
23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 | | |
30 ****************************************************************/ | |
31 | |
32 /*---------------------------------------------------------------------- | |
33 | includes | |
34 +---------------------------------------------------------------------*/ | |
35 #include "NptConfig.h" | |
36 #include "NptTypes.h" | |
37 #include "NptConstants.h" | |
38 #include "NptStrings.h" | |
39 #include "NptResults.h" | |
40 #include "NptUtils.h" | |
41 #include "NptDebug.h" | |
42 | |
43 /*---------------------------------------------------------------------- | |
44 | constants | |
45 +---------------------------------------------------------------------*/ | |
46 #define NPT_STRINGS_WHITESPACE_CHARS "\r\n\t " | |
47 | |
48 const unsigned int NPT_STRING_FORMAT_BUFFER_DEFAULT_SIZE = 256; | |
49 const unsigned int NPT_STRING_FORMAT_BUFFER_MAX_SIZE = 0x80000; // 512k | |
50 | |
51 /*---------------------------------------------------------------------- | |
52 | helpers | |
53 +---------------------------------------------------------------------*/ | |
54 inline char NPT_Uppercase(char x) { | |
55 return (x >= 'a' && x <= 'z') ? x&0xdf : x; | |
56 } | |
57 | |
58 inline char NPT_Lowercase(char x) { | |
59 return (x >= 'A' && x <= 'Z') ? x^32 : x; | |
60 } | |
61 | |
62 /*---------------------------------------------------------------------- | |
63 | NPT_String::EmptyString | |
64 +---------------------------------------------------------------------*/ | |
65 char NPT_String::EmptyString = '\0'; | |
66 | |
67 /*---------------------------------------------------------------------- | |
68 | NPT_String::FromInteger | |
69 +---------------------------------------------------------------------*/ | |
70 NPT_String | |
71 NPT_String::FromInteger(NPT_Int64 value) | |
72 { | |
73 char str[32]; | |
74 char* c = &str[31]; | |
75 *c-- = '\0'; | |
76 | |
77 // handle the sign | |
78 bool negative = false; | |
79 if (value < 0) { | |
80 negative = true; | |
81 value = -value; | |
82 } | |
83 | |
84 // process the digits | |
85 do { | |
86 int digit = (int)(value%10); | |
87 *c-- = '0'+digit; | |
88 value /= 10; | |
89 } while(value); | |
90 | |
91 if (negative) { | |
92 *c = '-'; | |
93 } else { | |
94 ++c; | |
95 } | |
96 | |
97 return NPT_String(c); | |
98 } | |
99 | |
100 /*---------------------------------------------------------------------- | |
101 | NPT_String::FromIntegerU | |
102 +---------------------------------------------------------------------*/ | |
103 NPT_String | |
104 NPT_String::FromIntegerU(NPT_UInt64 value) | |
105 { | |
106 char str[32]; | |
107 char* c = &str[31]; | |
108 *c = '\0'; | |
109 | |
110 // process the digits | |
111 do { | |
112 int digit = (int)(value%10); | |
113 *--c = '0'+digit; | |
114 value /= 10; | |
115 } while(value); | |
116 | |
117 return NPT_String(c); | |
118 } | |
119 | |
120 /*---------------------------------------------------------------------- | |
121 | NPT_String::Format | |
122 +---------------------------------------------------------------------*/ | |
123 NPT_String | |
124 NPT_String::Format(const char* format, ...) | |
125 { | |
126 NPT_String result; | |
127 NPT_Size buffer_size = NPT_STRING_FORMAT_BUFFER_DEFAULT_SIZE; // default value | |
128 | |
129 va_list args; | |
130 va_start(args, format); | |
131 | |
132 for(;;) { | |
133 /* try to format (it might not fit) */ | |
134 result.Reserve(buffer_size); | |
135 char* buffer = result.UseChars(); | |
136 int f_result = NPT_FormatStringVN(buffer, buffer_size, format, args); | |
137 if (f_result >= (int)(buffer_size)) f_result = -1; | |
138 if (f_result >= 0) { | |
139 result.SetLength(f_result); | |
140 break; | |
141 } | |
142 | |
143 /* the buffer was too small, try something bigger */ | |
144 /* (we don't trust the return value of NPT_FormatStringVN */ | |
145 /* for the actual size needed) */ | |
146 buffer_size *= 2; | |
147 if (buffer_size > NPT_STRING_FORMAT_BUFFER_MAX_SIZE) break; | |
148 } | |
149 | |
150 va_end(args); | |
151 | |
152 return result; | |
153 } | |
154 | |
155 /*---------------------------------------------------------------------- | |
156 | NPT_String::NPT_String | |
157 +---------------------------------------------------------------------*/ | |
158 NPT_String::NPT_String(const char* str) | |
159 { | |
160 if (str == NULL) { | |
161 m_Chars = NULL; | |
162 } else { | |
163 m_Chars = Buffer::Create(str); | |
164 } | |
165 } | |
166 | |
167 /*---------------------------------------------------------------------- | |
168 | NPT_String::NPT_String | |
169 +---------------------------------------------------------------------*/ | |
170 NPT_String::NPT_String(const char* str, NPT_Size length) | |
171 { | |
172 if (str == NULL || length == 0) { | |
173 m_Chars = NULL; | |
174 } else { | |
175 m_Chars = Buffer::Create(str, length); | |
176 } | |
177 } | |
178 | |
179 /*---------------------------------------------------------------------- | |
180 | NPT_String::NPT_String | |
181 +---------------------------------------------------------------------*/ | |
182 NPT_String::NPT_String(const NPT_String& str) | |
183 { | |
184 if (str.GetLength() == 0) { | |
185 m_Chars = NULL; | |
186 } else { | |
187 m_Chars = Buffer::Create(str.GetChars(), str.GetLength()); | |
188 } | |
189 } | |
190 | |
191 /*---------------------------------------------------------------------- | |
192 | NPT_String::NPT_String | |
193 +---------------------------------------------------------------------*/ | |
194 NPT_String::NPT_String(const char* str, | |
195 NPT_Ordinal first, | |
196 NPT_Size length) | |
197 { | |
198 // shortcut | |
199 if (str != NULL && length != 0) { | |
200 // truncate length | |
201 NPT_Size str_length = StringLength(str); | |
202 if (first < str_length) { | |
203 if (first+length > str_length) { | |
204 length = str_length-first; | |
205 } | |
206 if (length != 0) { | |
207 m_Chars = Buffer::Create(str+first, length); | |
208 return; | |
209 } | |
210 } | |
211 } | |
212 m_Chars = NULL; | |
213 } | |
214 | |
215 /*---------------------------------------------------------------------- | |
216 | NPT_String::NPT_String | |
217 +---------------------------------------------------------------------*/ | |
218 NPT_String::NPT_String(char c, NPT_Cardinal repeat) | |
219 { | |
220 if (repeat != 0) { | |
221 m_Chars = Buffer::Create(c, repeat); | |
222 } else { | |
223 m_Chars = NULL; | |
224 } | |
225 } | |
226 | |
227 /*---------------------------------------------------------------------- | |
228 | NPT_String::SetLength | |
229 +---------------------------------------------------------------------*/ | |
230 NPT_Result | |
231 NPT_String::SetLength(NPT_Size length, bool pad) | |
232 { | |
233 // special case for 0 | |
234 if (length == 0) { | |
235 Reset(); | |
236 return NPT_SUCCESS; | |
237 } | |
238 | |
239 // reserve the space | |
240 Reserve(length); | |
241 | |
242 // pad with spaces if necessary | |
243 char* chars = UseChars(); | |
244 if (pad) { | |
245 unsigned int current_length = GetLength(); | |
246 if (length > current_length) { | |
247 unsigned int pad_length = length-current_length; | |
248 NPT_SetMemory(chars+current_length, ' ', pad_length); | |
249 } | |
250 } | |
251 | |
252 // update the length and terminate the buffer | |
253 GetBuffer()->SetLength(length); | |
254 chars[length] = '\0'; | |
255 | |
256 return NPT_SUCCESS; | |
257 } | |
258 | |
259 /*---------------------------------------------------------------------- | |
260 | NPT_String::PrepareToWrite | |
261 +---------------------------------------------------------------------*/ | |
262 inline char* | |
263 NPT_String::PrepareToWrite(NPT_Size length) | |
264 { | |
265 NPT_ASSERT(length != 0); | |
266 if (m_Chars == NULL || GetBuffer()->GetAllocated() < length) { | |
267 // the buffer is too small, we need to allocate a new one. | |
268 NPT_Size needed = length; | |
269 if (m_Chars != NULL) { | |
270 NPT_Size grow = GetBuffer()->GetAllocated()*2; | |
271 if (grow > length) needed = grow; | |
272 delete GetBuffer(); | |
273 } | |
274 m_Chars = Buffer::Create(needed); | |
275 } | |
276 GetBuffer()->SetLength(length); | |
277 return m_Chars; | |
278 } | |
279 | |
280 /*---------------------------------------------------------------------- | |
281 | NPT_String::Reserve | |
282 +---------------------------------------------------------------------*/ | |
283 void | |
284 NPT_String::Reserve(NPT_Size allocate) | |
285 { | |
286 if (m_Chars == NULL || GetBuffer()->GetAllocated() < allocate) { | |
287 // the buffer is too small, we need to allocate a new one. | |
288 NPT_Size needed = allocate; | |
289 if (m_Chars != NULL) { | |
290 NPT_Size grow = GetBuffer()->GetAllocated()*2; | |
291 if (grow > allocate) needed = grow; | |
292 } | |
293 NPT_Size length = GetLength(); | |
294 char* copy = Buffer::Create(needed, length); | |
295 if (m_Chars != NULL) { | |
296 CopyString(copy, m_Chars); | |
297 delete GetBuffer(); | |
298 } else { | |
299 copy[0] = '\0'; | |
300 } | |
301 m_Chars = copy; | |
302 } | |
303 } | |
304 | |
305 /*---------------------------------------------------------------------- | |
306 | NPT_String::Assign | |
307 +---------------------------------------------------------------------*/ | |
308 void | |
309 NPT_String::Assign(const char* str, NPT_Size length) | |
310 { | |
311 if (str == NULL || length == 0) { | |
312 Reset(); | |
313 } else { | |
314 PrepareToWrite(length); | |
315 CopyBuffer(m_Chars, str, length); | |
316 m_Chars[length] = '\0'; | |
317 } | |
318 } | |
319 | |
320 /*---------------------------------------------------------------------- | |
321 | NPT_String::operator= | |
322 +---------------------------------------------------------------------*/ | |
323 NPT_String& | |
324 NPT_String::operator=(const char* str) | |
325 { | |
326 if (str == NULL) { | |
327 Reset(); | |
328 } else { | |
329 NPT_Size length = StringLength(str); | |
330 if (length == 0) { | |
331 Reset(); | |
332 } else { | |
333 CopyString(PrepareToWrite(length), str); | |
334 } | |
335 } | |
336 | |
337 return *this; | |
338 } | |
339 | |
340 /*---------------------------------------------------------------------- | |
341 | NPT_String::operator= | |
342 +---------------------------------------------------------------------*/ | |
343 NPT_String& | |
344 NPT_String::operator=(const NPT_String& str) | |
345 { | |
346 // do nothing if we're assigning to ourselves | |
347 if (this != &str) { | |
348 Assign(str.GetChars(), str.GetLength()); | |
349 } | |
350 return *this; | |
351 } | |
352 | |
353 /*---------------------------------------------------------------------- | |
354 | NPT_String::Append | |
355 +---------------------------------------------------------------------*/ | |
356 void | |
357 NPT_String::Append(const char* str, NPT_Size length) | |
358 { | |
359 // shortcut | |
360 if (str == NULL || length == 0) return; | |
361 | |
362 // compute the new length | |
363 NPT_Size old_length = GetLength(); | |
364 NPT_Size new_length = old_length + length; | |
365 | |
366 // allocate enough space | |
367 Reserve(new_length); | |
368 | |
369 // append the new string at the end of the current one | |
370 CopyBuffer(m_Chars+old_length, str, length); | |
371 m_Chars[new_length] = '\0'; | |
372 | |
373 // update the length | |
374 GetBuffer()->SetLength(new_length); | |
375 } | |
376 | |
377 /*---------------------------------------------------------------------- | |
378 | NPT_String::Compare | |
379 +---------------------------------------------------------------------*/ | |
380 int | |
381 NPT_String::Compare(const char *s, bool ignore_case) const | |
382 { | |
383 return NPT_String::Compare(GetChars(), s, ignore_case); | |
384 } | |
385 | |
386 /*---------------------------------------------------------------------- | |
387 | NPT_String::Compare | |
388 +---------------------------------------------------------------------*/ | |
389 int | |
390 NPT_String::Compare(const char *s1, const char *s2, bool ignore_case) | |
391 { | |
392 const char *r1 = s1; | |
393 const char *r2 = s2; | |
394 | |
395 if (ignore_case) { | |
396 while (NPT_Uppercase(*r1) == NPT_Uppercase(*r2)) { | |
397 if (*r1++ == '\0') { | |
398 return 0; | |
399 } | |
400 r2++; | |
401 } | |
402 return NPT_Uppercase(*r1) - NPT_Uppercase(*r2); | |
403 } else { | |
404 while (*r1 == *r2) { | |
405 if (*r1++ == '\0') { | |
406 return 0; | |
407 } | |
408 r2++; | |
409 } | |
410 return (*r1 - *r2); | |
411 } | |
412 } | |
413 | |
414 /*---------------------------------------------------------------------- | |
415 | NPT_String::CompareN | |
416 +---------------------------------------------------------------------*/ | |
417 int | |
418 NPT_String::CompareN(const char *s, NPT_Size count, bool ignore_case) const | |
419 { | |
420 return NPT_String::CompareN(GetChars(), s, count, ignore_case); | |
421 } | |
422 | |
423 /*---------------------------------------------------------------------- | |
424 | NPT_String::CompareN | |
425 +---------------------------------------------------------------------*/ | |
426 int | |
427 NPT_String::CompareN(const char* s1, const char *s2, NPT_Size count, bool ignore_case) | |
428 { | |
429 const char* me = s1; | |
430 | |
431 if (ignore_case) { | |
432 for (unsigned int i=0; i<count; i++) { | |
433 if (NPT_Uppercase(me[i]) != NPT_Uppercase(s2[i])) { | |
434 return NPT_Uppercase(me[i]) - NPT_Uppercase(s2[i]); | |
435 } | |
436 } | |
437 return 0; | |
438 } else { | |
439 for (unsigned int i=0; i<count; i++) { | |
440 if (me[i] != s2[i]) { | |
441 return (me[i] - s2[i]); | |
442 } | |
443 } | |
444 return 0; | |
445 } | |
446 } | |
447 | |
448 /*---------------------------------------------------------------------- | |
449 | NPT_String::Split | |
450 +---------------------------------------------------------------------*/ | |
451 NPT_List<NPT_String> | |
452 NPT_String::Split(const char* separator) const | |
453 { | |
454 NPT_List<NPT_String> result; | |
455 NPT_Size separator_length = NPT_StringLength(separator); | |
456 | |
457 // sepcial case for empty separators | |
458 if (separator_length == 0) { | |
459 result.Add(*this); | |
460 return result; | |
461 } | |
462 | |
463 int current = 0; | |
464 int next; | |
465 do { | |
466 next = Find(separator, current); | |
467 unsigned int end = (next>=0?next:GetLength()); | |
468 result.Add(SubString(current, end-current)); | |
469 current = next+separator_length; | |
470 } while (next >= 0); | |
471 | |
472 return result; | |
473 } | |
474 | |
475 /*---------------------------------------------------------------------- | |
476 | NPT_String::SubString | |
477 +---------------------------------------------------------------------*/ | |
478 NPT_String | |
479 NPT_String::SubString(NPT_Ordinal first, NPT_Size length) const | |
480 { | |
481 if (first >= GetLength()) { | |
482 first = GetLength(); | |
483 length = 0; | |
484 } else if (first+length >= GetLength()) { | |
485 length = GetLength()-first; | |
486 } | |
487 return NPT_String(GetChars()+first, length); | |
488 } | |
489 | |
490 /*---------------------------------------------------------------------- | |
491 | NPT_StringStartsWith | |
492 | | |
493 | returns: | |
494 | 1 if str starts with sub, | |
495 | 0 if str is large enough but does not start with sub | |
496 | -1 if str is too short to start with sub | |
497 +---------------------------------------------------------------------*/ | |
498 static inline int | |
499 NPT_StringStartsWith(const char* str, const char* sub, bool ignore_case) | |
500 { | |
501 if (ignore_case) { | |
502 while (NPT_Uppercase(*str) == NPT_Uppercase(*sub)) { | |
503 if (*str++ == '\0') { | |
504 return 1; | |
505 } | |
506 sub++; | |
507 } | |
508 } else { | |
509 while (*str == *sub) { | |
510 if (*str++ == '\0') { | |
511 return 1; | |
512 } | |
513 sub++; | |
514 } | |
515 } | |
516 return (*sub == '\0') ? 1 : (*str == '\0' ? -1 : 0); | |
517 } | |
518 | |
519 /*---------------------------------------------------------------------- | |
520 | NPT_String::StartsWith | |
521 +---------------------------------------------------------------------*/ | |
522 bool | |
523 NPT_String::StartsWith(const char *s, bool ignore_case) const | |
524 { | |
525 if (s == NULL) return false; | |
526 return NPT_StringStartsWith(GetChars(), s, ignore_case) == 1; | |
527 } | |
528 | |
529 /*---------------------------------------------------------------------- | |
530 | NPT_String::EndsWith | |
531 +---------------------------------------------------------------------*/ | |
532 bool | |
533 NPT_String::EndsWith(const char *s, bool ignore_case) const | |
534 { | |
535 if (s == NULL) return false; | |
536 NPT_Size str_length = NPT_StringLength(s); | |
537 if (str_length > GetLength()) return false; | |
538 return NPT_StringStartsWith(GetChars()+GetLength()-str_length, s, ignore_case) == 1; | |
539 } | |
540 | |
541 /*---------------------------------------------------------------------- | |
542 | NPT_String::Find | |
543 +---------------------------------------------------------------------*/ | |
544 int | |
545 NPT_String::Find(const char* str, NPT_Ordinal start, bool ignore_case) const | |
546 { | |
547 // check args | |
548 if (str == NULL || start >= GetLength()) return -1; | |
549 | |
550 // skip to start position | |
551 const char* src = m_Chars + start; | |
552 | |
553 // look for a substring | |
554 while (*src) { | |
555 int cmp = NPT_StringStartsWith(src, str, ignore_case); | |
556 switch (cmp) { | |
557 case -1: | |
558 // ref is too short, abort | |
559 return -1; | |
560 case 1: | |
561 // match | |
562 return (int)(src-m_Chars); | |
563 } | |
564 src++; | |
565 } | |
566 | |
567 return -1; | |
568 } | |
569 | |
570 /*---------------------------------------------------------------------- | |
571 | NPT_String::Find | |
572 +---------------------------------------------------------------------*/ | |
573 int | |
574 NPT_String::Find(char c, NPT_Ordinal start, bool ignore_case) const | |
575 { | |
576 // check args | |
577 if (start >= GetLength()) return -1; | |
578 | |
579 // skip to start position | |
580 const char* src = m_Chars + start; | |
581 | |
582 // look for the character | |
583 if (ignore_case) { | |
584 while (*src) { | |
585 if (NPT_Uppercase(*src) == NPT_Uppercase(c)) { | |
586 return (int)(src-m_Chars); | |
587 } | |
588 src++; | |
589 } | |
590 } else { | |
591 while (*src) { | |
592 if (*src == c) return (int)(src-m_Chars); | |
593 src++; | |
594 } | |
595 } | |
596 | |
597 return -1; | |
598 } | |
599 | |
600 /*---------------------------------------------------------------------- | |
601 | NPT_String::ReverseFind | |
602 +---------------------------------------------------------------------*/ | |
603 int | |
604 NPT_String::ReverseFind(const char* str, NPT_Ordinal start, bool ignore_case) const | |
605 { | |
606 // check args | |
607 if (str == NULL || *str == '\0') return -1; | |
608 | |
609 // look for a substring | |
610 NPT_Size my_length = GetLength(); | |
611 NPT_Size str_length = NPT_StringLength(str); | |
612 int i=my_length-start-str_length; | |
613 const char* src = GetChars(); | |
614 if (i<0) return -1; | |
615 for (;i>=0; i--) { | |
616 int cmp = NPT_StringStartsWith(src+i, str, ignore_case); | |
617 if (cmp == 1) { | |
618 // match | |
619 return i; | |
620 } | |
621 } | |
622 | |
623 return -1; | |
624 } | |
625 | |
626 /*---------------------------------------------------------------------- | |
627 | NPT_String::ReverseFind | |
628 +---------------------------------------------------------------------*/ | |
629 int | |
630 NPT_String::ReverseFind(char c, NPT_Ordinal start, bool ignore_case) const | |
631 { | |
632 // check args | |
633 NPT_Size length = GetLength(); | |
634 int i = length-start-1; | |
635 if (i < 0) return -1; | |
636 | |
637 // look for the character | |
638 const char* src = GetChars(); | |
639 if (ignore_case) { | |
640 for (;i>=0;i--) { | |
641 if (NPT_Uppercase(src[i]) == NPT_Uppercase(c)) { | |
642 return i; | |
643 } | |
644 } | |
645 } else { | |
646 for (;i>=0;i--) { | |
647 if (src[i] == c) return i; | |
648 } | |
649 } | |
650 | |
651 return -1; | |
652 } | |
653 | |
654 /*---------------------------------------------------------------------- | |
655 | NPT_String::MakeLowercase | |
656 +---------------------------------------------------------------------*/ | |
657 void | |
658 NPT_String::MakeLowercase() | |
659 { | |
660 // the source is the current buffer | |
661 const char* src = GetChars(); | |
662 | |
663 // convert all the characters of the existing buffer | |
664 char* dst = const_cast<char*>(src); | |
665 while (*dst != '\0') { | |
666 *dst = NPT_Lowercase(*dst); | |
667 dst++; | |
668 } | |
669 } | |
670 | |
671 /*---------------------------------------------------------------------- | |
672 | NPT_String::MakeUppercase | |
673 +---------------------------------------------------------------------*/ | |
674 void | |
675 NPT_String::MakeUppercase() | |
676 { | |
677 // the source is the current buffer | |
678 const char* src = GetChars(); | |
679 | |
680 // convert all the characters of the existing buffer | |
681 char* dst = const_cast<char*>(src); | |
682 while (*dst != '\0') { | |
683 *dst = NPT_Uppercase(*dst); | |
684 dst++; | |
685 } | |
686 } | |
687 | |
688 /*---------------------------------------------------------------------- | |
689 | NPT_String::ToLowercase | |
690 +---------------------------------------------------------------------*/ | |
691 NPT_String | |
692 NPT_String::ToLowercase() const | |
693 { | |
694 NPT_String result(*this); | |
695 result.MakeLowercase(); | |
696 return result; | |
697 } | |
698 | |
699 /*---------------------------------------------------------------------- | |
700 | NPT_String::ToUppercase | |
701 +---------------------------------------------------------------------*/ | |
702 NPT_String | |
703 NPT_String::ToUppercase() const | |
704 { | |
705 NPT_String result(*this); | |
706 result.MakeUppercase(); | |
707 return result; | |
708 } | |
709 | |
710 /*---------------------------------------------------------------------- | |
711 | NPT_String::Replace | |
712 +---------------------------------------------------------------------*/ | |
713 void | |
714 NPT_String::Replace(char a, char b) | |
715 { | |
716 // check args | |
717 if (m_Chars == NULL || a == '\0' || b == '\0') return; | |
718 | |
719 // we are going to modify the characters | |
720 char* src = m_Chars; | |
721 | |
722 // process the buffer in place | |
723 while (*src) { | |
724 if (*src == a) *src = b; | |
725 src++; | |
726 } | |
727 } | |
728 | |
729 /*---------------------------------------------------------------------- | |
730 | NPT_String::Replace | |
731 +---------------------------------------------------------------------*/ | |
732 void | |
733 NPT_String::Replace(char a, const char* str) | |
734 { | |
735 // check args | |
736 if (m_Chars == NULL || a == '\0' || str == NULL || str[0] == '\0') return; | |
737 | |
738 // optimization | |
739 if (NPT_StringLength(str) == 1) return Replace(a, str[0]); | |
740 | |
741 // we are going to create a new string | |
742 NPT_String dst; | |
743 char* src = m_Chars; | |
744 | |
745 // reserve at least as much as input | |
746 dst.Reserve(GetLength()); | |
747 | |
748 // process the buffer | |
749 while (*src) { | |
750 if (*src == a) { | |
751 dst += str; | |
752 } else { | |
753 dst += *src; | |
754 } | |
755 src++; | |
756 } | |
757 | |
758 Assign(dst.GetChars(), dst.GetLength()); | |
759 } | |
760 | |
761 /*---------------------------------------------------------------------- | |
762 | NPT_String::Insert | |
763 +---------------------------------------------------------------------*/ | |
764 void | |
765 NPT_String::Insert(const char* str, NPT_Ordinal where) | |
766 { | |
767 // check args | |
768 if (str == NULL || where > GetLength()) return; | |
769 | |
770 // measure the string to insert | |
771 NPT_Size str_length = StringLength(str); | |
772 if (str_length == 0) return; | |
773 | |
774 // compute the size of the new string | |
775 NPT_Size old_length = GetLength(); | |
776 NPT_Size new_length = str_length + GetLength(); | |
777 | |
778 // prepare to write the new string | |
779 char* src = m_Chars; | |
780 char* nst = Buffer::Create(new_length, new_length); | |
781 char* dst = nst; | |
782 | |
783 // copy the beginning of the old string | |
784 if (where > 0) { | |
785 CopyBuffer(dst, src, where); | |
786 src += where; | |
787 dst += where; | |
788 } | |
789 | |
790 // copy the inserted string | |
791 CopyString(dst, str); | |
792 dst += str_length; | |
793 | |
794 // copy the end of the old string | |
795 if (old_length > where) { | |
796 CopyString(dst, src); | |
797 } | |
798 | |
799 // use the new string | |
800 if (m_Chars) delete GetBuffer(); | |
801 m_Chars = nst; | |
802 } | |
803 | |
804 /*---------------------------------------------------------------------- | |
805 | NPT_String::Erase | |
806 +---------------------------------------------------------------------*/ | |
807 void | |
808 NPT_String::Erase(NPT_Ordinal start, NPT_Cardinal count /* = 1 */) | |
809 { | |
810 // check bounds | |
811 NPT_Size length = GetLength(); | |
812 if (start+count > length) { | |
813 if (start >= length) return; | |
814 count = length-start; | |
815 } | |
816 if (count == 0) return; | |
817 | |
818 CopyString(m_Chars+start, m_Chars+start+count); | |
819 GetBuffer()->SetLength(length-count); | |
820 } | |
821 | |
822 /*---------------------------------------------------------------------- | |
823 | NPT_String::ToInteger | |
824 +---------------------------------------------------------------------*/ | |
825 NPT_Result | |
826 NPT_String::ToInteger(NPT_Int32& value, bool relaxed) const | |
827 { | |
828 return NPT_ParseInteger32(GetChars(), value, relaxed); | |
829 } | |
830 | |
831 /*---------------------------------------------------------------------- | |
832 | NPT_String::ToInteger | |
833 +---------------------------------------------------------------------*/ | |
834 NPT_Result | |
835 NPT_String::ToInteger(NPT_UInt32& value, bool relaxed) const | |
836 { | |
837 return NPT_ParseInteger32U(GetChars(), value, relaxed); | |
838 } | |
839 | |
840 /*---------------------------------------------------------------------- | |
841 | NPT_String::ToInteger | |
842 +---------------------------------------------------------------------*/ | |
843 NPT_Result | |
844 NPT_String::ToInteger(NPT_Int64& value, bool relaxed) const | |
845 { | |
846 return NPT_ParseInteger64(GetChars(), value, relaxed); | |
847 } | |
848 | |
849 /*---------------------------------------------------------------------- | |
850 | NPT_String::ToInteger | |
851 +---------------------------------------------------------------------*/ | |
852 NPT_Result | |
853 NPT_String::ToInteger(NPT_UInt64& value, bool relaxed) const | |
854 { | |
855 return NPT_ParseInteger64U(GetChars(), value, relaxed); | |
856 } | |
857 | |
858 /*---------------------------------------------------------------------- | |
859 | NPT_String::ToFloat | |
860 +---------------------------------------------------------------------*/ | |
861 NPT_Result | |
862 NPT_String::ToFloat(float& value, bool relaxed) const | |
863 { | |
864 return NPT_ParseFloat(GetChars(), value, relaxed); | |
865 } | |
866 | |
867 /*---------------------------------------------------------------------- | |
868 | NPT_String::TrimLeft | |
869 +---------------------------------------------------------------------*/ | |
870 void | |
871 NPT_String::TrimLeft() | |
872 { | |
873 TrimLeft(NPT_STRINGS_WHITESPACE_CHARS); | |
874 } | |
875 | |
876 /*---------------------------------------------------------------------- | |
877 | NPT_String::TrimLeft | |
878 +---------------------------------------------------------------------*/ | |
879 void | |
880 NPT_String::TrimLeft(char c) | |
881 { | |
882 char s[2] = {c, 0}; | |
883 TrimLeft((const char*)s); | |
884 } | |
885 | |
886 /*---------------------------------------------------------------------- | |
887 | NPT_String::TrimLeft | |
888 +---------------------------------------------------------------------*/ | |
889 void | |
890 NPT_String::TrimLeft(const char* chars) | |
891 { | |
892 if (m_Chars == NULL) return; | |
893 const char* s = m_Chars; | |
894 while (char c = *s) { | |
895 const char* x = chars; | |
896 while (*x) { | |
897 if (*x == c) break; | |
898 x++; | |
899 } | |
900 if (*x == 0) break; // not found | |
901 s++; | |
902 } | |
903 if (s == m_Chars) { | |
904 // nothing was trimmed | |
905 return; | |
906 } | |
907 | |
908 // shift chars to the left | |
909 char* d = m_Chars; | |
910 GetBuffer()->SetLength(GetLength()-(s-d)); | |
911 while ((*d++ = *s++)) {}; | |
912 } | |
913 | |
914 /*---------------------------------------------------------------------- | |
915 | NPT_String::TrimRight | |
916 +---------------------------------------------------------------------*/ | |
917 void | |
918 NPT_String::TrimRight() | |
919 { | |
920 TrimRight(NPT_STRINGS_WHITESPACE_CHARS); | |
921 } | |
922 | |
923 /*---------------------------------------------------------------------- | |
924 | NPT_String::TrimRight | |
925 +---------------------------------------------------------------------*/ | |
926 void | |
927 NPT_String::TrimRight(char c) | |
928 { | |
929 char s[2] = {c, 0}; | |
930 TrimRight((const char*)s); | |
931 } | |
932 | |
933 /*---------------------------------------------------------------------- | |
934 | NPT_String::TrimRight | |
935 +---------------------------------------------------------------------*/ | |
936 void | |
937 NPT_String::TrimRight(const char* chars) | |
938 { | |
939 if (m_Chars == NULL || m_Chars[0] == '\0') return; | |
940 char* tail = m_Chars+GetLength()-1; | |
941 char* s = tail; | |
942 while (s != m_Chars-1) { | |
943 const char* x = chars; | |
944 while (*x) { | |
945 if (*x == *s) { | |
946 *s = '\0'; | |
947 break; | |
948 } | |
949 x++; | |
950 } | |
951 if (*x == 0) break; // not found | |
952 s--; | |
953 } | |
954 if (s == tail) { | |
955 // nothing was trimmed | |
956 return; | |
957 } | |
958 GetBuffer()->SetLength(1+(int)(s-m_Chars)); | |
959 } | |
960 | |
961 /*---------------------------------------------------------------------- | |
962 | NPT_String::Trim | |
963 +---------------------------------------------------------------------*/ | |
964 void | |
965 NPT_String::Trim() | |
966 { | |
967 TrimLeft(); | |
968 TrimRight(); | |
969 } | |
970 | |
971 /*---------------------------------------------------------------------- | |
972 | NPT_String::Trim | |
973 +---------------------------------------------------------------------*/ | |
974 void | |
975 NPT_String::Trim(char c) | |
976 { | |
977 char s[2] = {c, 0}; | |
978 TrimLeft((const char*)s); | |
979 TrimRight((const char*)s); | |
980 } | |
981 | |
982 /*---------------------------------------------------------------------- | |
983 | NPT_String::Trim | |
984 +---------------------------------------------------------------------*/ | |
985 void | |
986 NPT_String::Trim(const char* chars) | |
987 { | |
988 TrimLeft(chars); | |
989 TrimRight(chars); | |
990 } | |
991 | |
992 /*---------------------------------------------------------------------- | |
993 | NPT_String::operator+(const NPT_String&, const char*) | |
994 +---------------------------------------------------------------------*/ | |
995 NPT_String | |
996 operator+(const NPT_String& s1, const char* s2) | |
997 { | |
998 // shortcut | |
999 if (s2 == NULL) return NPT_String(s1); | |
1000 | |
1001 // measure strings | |
1002 NPT_Size s1_length = s1.GetLength(); | |
1003 NPT_Size s2_length = NPT_String::StringLength(s2); | |
1004 | |
1005 // allocate space for the new string | |
1006 NPT_String result; | |
1007 char* start = result.PrepareToWrite(s1_length+s2_length); | |
1008 | |
1009 // concatenate the two strings into the result | |
1010 NPT_String::CopyBuffer(start, s1, s1_length); | |
1011 NPT_String::CopyString(start+s1_length, s2); | |
1012 | |
1013 return result; | |
1014 } | |
1015 | |
1016 /*---------------------------------------------------------------------- | |
1017 | NPT_String::operator+(const NPT_String& , const char*) | |
1018 +---------------------------------------------------------------------*/ | |
1019 NPT_String | |
1020 operator+(const char* s1, const NPT_String& s2) | |
1021 { | |
1022 // shortcut | |
1023 if (s1 == NULL) return NPT_String(s2); | |
1024 | |
1025 // measure strings | |
1026 NPT_Size s1_length = NPT_String::StringLength(s1); | |
1027 NPT_Size s2_length = s2.GetLength(); | |
1028 | |
1029 // allocate space for the new string | |
1030 NPT_String result; | |
1031 char* start = result.PrepareToWrite(s1_length+s2_length); | |
1032 | |
1033 // concatenate the two strings into the result | |
1034 NPT_String::CopyBuffer(start, s1, s1_length); | |
1035 NPT_String::CopyString(start+s1_length, s2.GetChars()); | |
1036 | |
1037 return result; | |
1038 } | |
1039 | |
1040 /*---------------------------------------------------------------------- | |
1041 | NPT_String::operator+(const NPT_String& , char) | |
1042 +---------------------------------------------------------------------*/ | |
1043 NPT_String | |
1044 operator+(const NPT_String& s1, char c) | |
1045 { | |
1046 // allocate space for the new string | |
1047 NPT_String result; | |
1048 result.Reserve(s1.GetLength()+1); | |
1049 | |
1050 // append | |
1051 result = s1; | |
1052 result += c; | |
1053 | |
1054 return result; | |
1055 } | |
1056 |