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