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