dcc52e2a3e7792b0b65c5fe66985bceebb070cb5
[blender.git] / intern / string / intern / STR_String.cpp
1 /**
2  * $Id$
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /**
30
31  * $Id$
32  * Copyright (C) 2001 NaN Technologies B.V.
33  * This file was formerly known as: GEN_StdString.cpp.
34  * @date        April, 25, 2001
35  */
36
37 #include <stdio.h>
38 #include <stdarg.h>
39 #include <stdlib.h> 
40 #include <ctype.h>
41 #include <string.h>
42 #include "STR_String.h"
43
44 /*-------------------------------------------------------------------------------------------------
45         Construction / destruction
46 -------------------------------------------------------------------------------------------------*/
47
48
49
50 //
51 // Construct an empty string
52 //
53 STR_String::STR_String() :
54         pData(new char [32]), 
55         Len(0),
56         Max(32)
57 {
58         pData[0] = 0;
59 }
60
61
62
63 //
64 // Construct a string of one character
65 //
66 STR_String::STR_String(char c) :
67         pData(new char [9]),
68         Len(1),
69         Max(9)
70 {
71         pData[0] = c;
72         pData[1] = 0;
73 }
74
75
76
77 //
78 // Construct a string of multiple repeating characters
79 //
80 STR_String::STR_String(char c, int len) :
81         pData(new char [len+8]),
82         Len(len),
83         Max(len+8)
84 {
85         assertd(pData != NULL);
86         memset(pData, c, len);
87         pData[len] = 0;
88 }
89
90
91
92 //
93 // Construct a string from a pointer-to-ASCIIZ-string
94 //
95 // MAART: Changed to test for null strings
96 STR_String::STR_String(const char *str)
97 {
98         if (str) {
99                 Len = ::strlen(str);
100                 Max = Len + 8;
101                 pData = new char [Max];
102                 assertd(pData != NULL);
103                 ::memcpy(pData, str, Len);
104                 pData[Len] = 0;
105         }
106         else {
107                 pData = 0;
108                 Len = 0;
109                 Max = 8;
110         }
111 }
112
113
114
115 //
116 // Construct a string from a pointer-to-ASCII-string and a length
117 //
118 STR_String::STR_String(const char *str, int len) :
119         pData(new char [len+8]),
120         Len(len),
121         Max(len+8)
122 {
123         assertd(pData != NULL);
124         memcpy(pData, str, len);
125         pData[len] = 0;
126 }
127
128
129
130 //
131 // Construct a string from another string
132 //
133 STR_String::STR_String(rcSTR_String str) :
134         pData(new char [str.Length()+8]),
135         Len(str.Length()),
136         Max(str.Length()+8)
137 {
138         assertd(pData != NULL);
139         assertd(str.pData != NULL);
140         memcpy(pData, str.pData, str.Length());
141         pData[str.Length()] = 0;
142 }
143
144
145
146 //
147 // Construct a string from the first number of characters in another string
148 //
149 STR_String::STR_String(rcSTR_String str, int len) :
150         pData(new char [len+8]),
151         Len(len),
152         Max(len+8)
153 {
154         assertd(pData != NULL);
155         assertd(str.pData != NULL);
156         memcpy(pData, str.pData, str.Length());
157         pData[str.Length()] = 0;
158 }
159
160
161
162 //
163 // Create a string by concatenating two sources
164 //
165 STR_String::STR_String(const char *src1, int len1, const char *src2, int len2) :
166         pData(new char [len1+len2+8]),
167         Len(len1+len2),
168         Max(len1+len2+8)
169 {
170         assertd(pData != NULL);
171         memcpy(pData, src1, len1);
172         memcpy(pData+len1, src2, len2);
173         pData[len1+len2] = 0;
174 }
175
176
177
178 //
179 // Create a string with an integer value
180 //
181 STR_String::STR_String(int val) :
182         pData(new char [32]),
183         Max(32)
184 {
185         assertd(pData != NULL);
186         Len=sprintf(pData, "%d", val);
187 }
188         
189
190
191
192 //
193 // Create a string with a dword value
194 //
195 STR_String::STR_String(dword val) :
196         pData(new char [32]),
197         Max(32)
198 {
199         assertd(pData != NULL);
200         Len=sprintf(pData, "%lu", val);
201 }
202
203
204
205 //
206 // Create a string with a floating point value
207 //
208 STR_String::STR_String(float val) :
209         pData(new char [32]),
210         Max(32)
211 {
212         assertd(pData != NULL);
213         Len=sprintf(pData, "%g", val);
214 }
215
216
217
218 //
219 // Create a string with a double value
220 //
221 STR_String::STR_String(double val) :
222         pData(new char [32]),
223         Max(32)
224 {
225         assertd(pData != NULL);
226         Len=sprintf(pData, "%g", val);
227 }
228
229
230
231 /*-------------------------------------------------------------------------------------------------
232         Buffer management
233 -------------------------------------------------------------------------------------------------*/
234
235
236
237 //
238 // Make sure that the allocated buffer is at least <len> in size
239 //
240 void STR_String::AllocBuffer(int len, bool keep_contents)
241 {
242         // Check if we have enough space
243         if (len+1 <= Max) return;
244
245         // Reallocate string
246         char *new_data = new char [len+8];
247         if (keep_contents) memcpy(new_data, pData, Len);
248         delete[] pData;
249
250         // Accept new data
251         Max = len+8;
252         pData = new_data;
253         assertd(pData != NULL);
254 }
255         
256
257
258 /*-------------------------------------------------------------------------------------------------
259         Basic string operations
260 -------------------------------------------------------------------------------------------------*/
261
262
263
264 //
265 // Format string (as does sprintf)
266 //
267 STR_String& STR_String::Format(const char *fmt, ...)
268 {
269         AllocBuffer(2048, false);
270
271         assertd(pData != NULL);
272         // Expand arguments and format to string
273         va_list args;
274         va_start(args, fmt);
275         Len = vsprintf(pData, fmt, args);
276         assertd(Len <= 2048);
277         va_end(args);
278
279         return *this;
280 }
281
282
283
284 //
285 // Format string (as does sprintf)
286 //
287 STR_String& STR_String::FormatAdd(const char *fmt, ...)
288 {
289         AllocBuffer(2048, false);
290
291         assertd(pData != NULL);
292         // Expand arguments and format to string
293         va_list args;
294         va_start(args, fmt);
295         Len += vsprintf(pData+Len, fmt, args);
296         assertd(Len <= 2048);
297         va_end(args);
298
299         return *this;
300 }
301
302
303
304 /*-------------------------------------------------------------------------------------------------
305         Properties
306 -------------------------------------------------------------------------------------------------*/
307
308
309
310 //
311 // Check if string is entirely in UPPERCase
312 //
313 bool STR_String::IsUpper() const
314 {
315         for (int i=0; i<Len; i++)
316                 if (isLower(pData[i]))
317                         return false;
318
319         return true;
320 }
321
322
323
324 //
325 // Check if string is entirely in lowerCase
326 //
327 bool STR_String::IsLower() const
328 {
329         for (int i=0; i<Len; i++)
330                 if (isUpper(pData[i]))
331                         return false;
332
333         return true;
334 }
335
336
337
338 /*-------------------------------------------------------------------------------------------------
339         Search/Replace
340 -------------------------------------------------------------------------------------------------*/
341
342
343
344 //
345 // Find the first orccurence of <c> in the string
346 //
347 int STR_String::Find(char c, int pos) const
348 {
349         assertd(pos >= 0);
350         assertd(Len==0 || pos<Len);
351         assertd(pData != NULL);
352         char *find_pos = strchr(pData+pos, c);
353         return (find_pos) ? (find_pos-pData) : -1;
354 }
355
356
357
358 //
359 // Find the first occurence of <str> in the string
360 //
361 int     STR_String::Find(const char *str, int pos) const
362 {
363         assertd(pos >= 0);
364         assertd(Len==0 || pos<Len);
365         assertd(pData != NULL);
366         char *find_pos = strstr(pData+pos, str);
367         return (find_pos) ? (find_pos-pData) : -1;
368 }
369
370
371
372 //
373 // Find the first occurence of <str> in the string
374 //
375 int     STR_String::Find(rcSTR_String str, int pos) const
376 {
377         assertd(pos >= 0);
378         assertd(Len==0 || pos<Len);
379         assertd(pData != NULL);
380         char *find_pos = strstr(pData+pos, str.ReadPtr());
381         return (find_pos) ? (find_pos-pData) : -1;
382 }
383
384
385
386 //
387 // Find the last occurence of <c> in the string
388 //
389 int STR_String::RFind(char c) const
390 {
391         assertd(pData != NULL);
392         char *pos = strrchr(pData, c);
393         return (pos) ? (pos-pData) : -1;
394 }
395
396
397
398 //
399 // Find the first occurence of any character in character set <set> in the string
400 //
401 int STR_String::FindOneOf(const char *set, int pos) const
402 {
403         assertd(pos >= 0);
404         assertd(Len==0 || pos<Len);
405         assertd(pData != NULL);
406         char *find_pos = strpbrk(pData+pos, set);
407         return (find_pos) ? (find_pos-pData) : -1;
408 }
409
410
411
412 //
413 // Replace a character in this string with another string
414 //
415 void STR_String::Replace(int pos, rcSTR_String str)
416 {
417         //bounds(pos, 0, Length()-1);
418
419         if (str.Length() < 1)
420         {
421                 // Remove one character from the string
422                 memcpy(pData+pos, pData+pos+1, Len-pos);
423         }
424         else
425         {
426                 // Insert zero or more characters into the string
427                 AllocBuffer(Len + str.Length() - 1, true);
428                 if (str.Length() != 1) memcpy(pData+pos+str.Length(), pData+pos+1, Length()-pos);
429                 memcpy(pData+pos, str.ReadPtr(), str.Length());
430         }
431
432         Len += str.Length()-1;
433 }
434
435
436
437 //
438 // Replace a substring of this string with another string
439 //
440 void STR_String::Replace(int pos, int num, rcSTR_String str)
441 {
442         //bounds(pos, 0, Length()-1);
443         //bounds(pos+num, 0, Length());
444         assertd(num >= 1);
445
446         if (str.Length() < num)
447         {
448                 // Remove some data from the string by replacement
449                 memcpy(pData+pos+str.Length(), pData+pos+num, Len-pos-num+1);
450                 memcpy(pData+pos, str.ReadPtr(), str.Length());
451         }
452         else
453         {
454                 // Insert zero or more characters into the string
455                 AllocBuffer(Len + str.Length() - num, true);
456                 if (str.Length() != num) memcpy(pData+pos+str.Length(), pData+pos+num, Length()-pos-num+1);
457                 memcpy(pData+pos, str.ReadPtr(), str.Length());
458         }
459
460         Len += str.Length()-num;
461 }
462
463
464
465 /*-------------------------------------------------------------------------------------------------
466         Comparison
467 -------------------------------------------------------------------------------------------------*/
468
469
470
471 //
472 // Compare two strings and return the result, <0 if *this<rhs, >0 if *this>rhs or 0 if *this==rhs
473 //
474 int     STR_String::Compare(rcSTR_String rhs) const
475 {
476         return strcmp(pData, rhs.pData);
477 }
478
479
480
481 //
482 // Compare two strings without respecting case and return the result, <0 if *this<rhs, >0 if *this>rhs or 0 if *this==rhs
483 //
484 int STR_String::CompareNoCase(rcSTR_String rhs) const
485 {
486 #ifdef WIN32
487         return stricmp(pData, rhs.pData);
488 #else
489         return strcasecmp(pData, rhs.pData);
490 #endif
491 }
492
493
494
495 /*-------------------------------------------------------------------------------------------------
496         Formatting
497 -------------------------------------------------------------------------------------------------*/
498
499
500
501 //
502 // Capitalize string, "heLLo" -> "HELLO"
503 //
504 STR_String&     STR_String::Upper()
505 {
506         assertd(pData != NULL);
507 #ifdef WIN32
508         _strupr(pData);
509 #else
510         for (int i=0;i<Len;i++)
511                 pData[i] = (pData[i] >= 'a' && pData[i] <= 'z')?pData[i]+'A'-'a':pData[i];
512 #endif
513         return *this;
514 }
515
516
517
518 //
519 // Lower string, "heLLo" -> "hello"
520 //
521 STR_String&     STR_String::Lower()
522 {
523         assertd(pData != NULL);
524 #ifdef WIN32
525         _strlwr(pData);
526 #else
527         for (int i=0;i<Len;i++)
528                 pData[i] = (pData[i] >= 'A' && pData[i] <= 'Z')?pData[i]+'a'-'A':pData[i];
529 #endif
530         return *this;
531 }
532
533
534
535 //
536 // Capitalize string, "heLLo" -> "Hello"
537 //
538 STR_String&     STR_String::Capitalize()
539 {
540         assertd(pData != NULL);
541 #ifdef WIN32
542         if (Len>0) pData[0] = toupper(pData[0]);
543         if (Len>1) _strlwr(pData+1);
544 #else
545         if (Len > 0)
546                 pData[0] = (pData[0] >= 'A' && pData[0] <= 'A')?pData[0]+'a'-'A':pData[0];
547         for (int i=1;i<Len;i++)
548                 pData[i] = (pData[i] >= 'a' && pData[i] <= 'z')?pData[i]+'A'-'a':pData[i];
549 #endif
550         return *this;
551 }
552
553
554
555 //
556 // Trim whitespace from the left side of the string
557 //
558 STR_String&     STR_String::TrimLeft()
559 {
560         int skip;
561         assertd(pData != NULL);
562         for (skip=0; isSpace(pData[skip]); skip++, Len--);
563         memmove(pData, pData+skip, Len+1);
564         return *this;
565 }
566
567
568
569 //
570 // Trim whitespaces from the right side of the string
571 //
572 STR_String&     STR_String::TrimRight()
573 {
574         assertd(pData != NULL);
575         while (Len && isSpace(pData[Len-1])) Len--;
576         pData[Len]=0;
577         return *this;
578 }
579
580
581
582 //
583 // Trim spaces from both sides of the character set
584 //
585 STR_String&     STR_String::Trim()
586 {
587         TrimRight();
588         TrimLeft();
589         return *this;
590 }
591
592
593
594 //
595 // Trim characters from the character set <set> from the left side of the string
596 //
597 STR_String&     STR_String::TrimLeft(char *set)
598 {
599         int skip;
600         assertd(pData != NULL);
601         for (skip=0; Len && strchr(set, pData[skip]); skip++, Len--);
602         memmove(pData, pData+skip, Len+1);
603         return *this;
604 }
605
606
607
608 //
609 // Trim characters from the character set <set> from the right side of the string
610 //
611 STR_String&     STR_String::TrimRight(char *set)
612 {
613         assertd(pData != NULL);
614         while (Len && strchr(set, pData[Len-1])) Len--;
615         pData[Len]=0;
616         return *this;
617 }
618
619
620
621 //
622 // Trim characters from the character set <set> from both sides of the character set
623 //
624 STR_String&     STR_String::Trim(char *set)
625 {
626         TrimRight(set);
627         TrimLeft(set);
628         return *this;
629 }
630
631
632
633 //
634 // Trim quotes from both sides of the string
635 //
636 STR_String&     STR_String::TrimQuotes()
637 {
638         // Trim quotes if they are on both sides of the string
639         assertd(pData != NULL);
640         if ((Len >= 2) && (pData[0] == '\"') && (pData[Len-1] == '\"'))
641         {
642                 memmove(pData, pData+1, Len-2+1);
643                 Len-=2;
644         }
645         return *this;
646 }
647
648
649
650 /*-------------------------------------------------------------------------------------------------
651         Assignment/Concatenation
652 -------------------------------------------------------------------------------------------------*/
653
654
655
656 //
657 // Set the string's conents to a copy of <src> with length <len>
658 //
659 rcSTR_String STR_String::Copy(const char *src, int len)
660 {
661         assertd(len>=0);
662         assertd(src);
663         assertd(pData != NULL);
664
665         AllocBuffer(len, false);
666         Len = len;
667         memcpy(pData, src, len);
668         pData[Len] = 0;
669
670         return *this;
671 }
672
673
674
675 //
676 // Concate a number of bytes to the current string
677 //
678 rcSTR_String STR_String::Concat(const char *data, int len)
679 {
680         assertd(Len>=0);
681         assertd(len>=0);
682         assertd(data);
683         assertd(pData != NULL);
684
685         AllocBuffer(Len+len, true);
686         memcpy(pData+Len, data, len);
687         Len+=len;
688         pData[Len] = 0;
689
690         return *this;
691 }
692
693
694
695
696
697 vector<STR_String>      STR_String::Explode(char c) const
698 {
699         STR_String                              lcv     = *this;
700         vector<STR_String>              uc;
701
702         while (lcv.Length())
703         {
704                 int pos = lcv.Find(c);
705                 if (pos < 0)
706                 {
707                         uc.push_back(lcv);
708                         lcv.Clear();
709                 } else
710                 {
711                         uc.push_back(lcv.Left(pos));
712                         lcv = lcv.Mid(pos+1);
713                 }
714         }
715
716         //uc. -= STR_String("");
717
718         return uc;
719 }
720
721
722 /*
723
724 int             STR_String::Serialize(pCStream stream)
725 {
726         if (stream->GetAccess() == CStream::Access_Read)
727         {
728                 int ln;
729                 stream->Read(&ln, sizeof(ln));
730                 AllocBuffer(ln, false);
731                 stream->Read(pData, ln); 
732                 pData[ln]       = '\0';
733                 Len                     = ln;
734         } else
735         {
736                 stream->Write(&Len, sizeof(Len));
737                 stream->Write(pData, Len);
738         }
739
740         return Len + sizeof(Len);
741 }
742 */
743