Blender V2.61 - r43446

STR_String.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00040 #include <stdio.h>
00041 #include <stdarg.h>
00042 #include <stdlib.h> 
00043 #include <ctype.h>
00044 #include <string.h>
00045 #if defined(__sun__) || defined( __sun ) || defined (__sparc) || defined (__sparc__) || defined (_AIX)
00046 #  include <strings.h>
00047 #endif
00048 #include "STR_String.h"
00049 
00050 /*-------------------------------------------------------------------------------------------------
00051     Construction / destruction
00052 -------------------------------------------------------------------------------------------------*/
00053 
00054 
00055 
00056 //
00057 // Construct an empty string
00058 //
00059 STR_String::STR_String() :
00060     pData(new char [32]), 
00061     Len(0),
00062     Max(32)
00063 {
00064     pData[0] = 0;
00065 }
00066 
00067 
00068 
00069 //
00070 // Construct a string of one character
00071 //
00072 STR_String::STR_String(char c) :
00073     pData(new char [9]),
00074     Len(1),
00075     Max(9)
00076 {
00077     pData[0] = c;
00078     pData[1] = 0;
00079 }
00080 
00081 
00082 
00083 //
00084 // Construct a string of multiple repeating characters
00085 //
00086 STR_String::STR_String(char c, int len) :
00087     pData(new char [len+8]),
00088     Len(len),
00089     Max(len+8)
00090 {
00091     assertd(pData != NULL);
00092     memset(pData, c, len);
00093     pData[len] = 0;
00094 }
00095 
00096 
00097 
00098 //
00099 // Construct a string from a pointer-to-ASCIIZ-string
00100 //
00101 // MAART: Changed to test for null strings
00102 STR_String::STR_String(const char *str)
00103 {
00104     if (str) {
00105         Len = ::strlen(str);
00106         Max = Len + 8;
00107         pData = new char [Max];
00108         assertd(pData != NULL);
00109         ::memcpy(pData, str, Len);
00110         pData[Len] = 0;
00111     }
00112     else {
00113         pData = 0;
00114         Len = 0;
00115         Max = 8;
00116     }
00117 }
00118 
00119 
00120 
00121 //
00122 // Construct a string from a pointer-to-ASCII-string and a length
00123 //
00124 STR_String::STR_String(const char *str, int len) :
00125     pData(new char [len+8]),
00126     Len(len),
00127     Max(len+8)
00128 {
00129     assertd(pData != NULL);
00130     memcpy(pData, str, len);
00131     pData[len] = 0;
00132 }
00133 
00134 
00135 
00136 //
00137 // Construct a string from another string
00138 //
00139 STR_String::STR_String(rcSTR_String str) :
00140     pData(new char [str.Length()+8]),
00141     Len(str.Length()),
00142     Max(str.Length()+8)
00143 {
00144     assertd(pData != NULL);
00145     assertd(str.pData != NULL);
00146     memcpy(pData, str.pData, str.Length());
00147     pData[str.Length()] = 0;
00148 }
00149 
00150 
00151 
00152 //
00153 // Construct a string from the first number of characters in another string
00154 //
00155 STR_String::STR_String(rcSTR_String str, int len) :
00156     pData(new char [len+8]),
00157     Len(len),
00158     Max(len+8)
00159 {
00160     assertd(pData != NULL);
00161     assertd(str.pData != NULL);
00162     memcpy(pData, str.pData, str.Length());
00163     pData[str.Length()] = 0;
00164 }
00165 
00166 
00167 
00168 //
00169 // Create a string by concatenating two sources
00170 //
00171 STR_String::STR_String(const char *src1, int len1, const char *src2, int len2) :
00172     pData(new char [len1+len2+8]),
00173     Len(len1+len2),
00174     Max(len1+len2+8)
00175 {
00176     assertd(pData != NULL);
00177     memcpy(pData, src1, len1);
00178     memcpy(pData+len1, src2, len2);
00179     pData[len1+len2] = 0;
00180 }
00181 
00182 
00183 
00184 //
00185 // Create a string with an integer value
00186 //
00187 STR_String::STR_String(int val) :
00188     pData(new char [32]),
00189     Max(32)
00190 {
00191     assertd(pData != NULL);
00192     Len=sprintf(pData, "%d", val);
00193 }
00194     
00195 
00196 
00197 
00198 //
00199 // Create a string with a dword value
00200 //
00201 STR_String::STR_String(dword val) :
00202     pData(new char [32]),
00203     Max(32)
00204 {
00205     assertd(pData != NULL);
00206     Len=sprintf(pData, "%lu", val);
00207 }
00208 
00209 
00210 
00211 //
00212 // Create a string with a floating point value
00213 //
00214 STR_String::STR_String(float val) :
00215     pData(new char [32]),
00216     Max(32)
00217 {
00218     assertd(pData != NULL);
00219     Len=sprintf(pData, "%g", val);
00220 }
00221 
00222 
00223 
00224 //
00225 // Create a string with a double value
00226 //
00227 STR_String::STR_String(double val) :
00228     pData(new char [32]),
00229     Max(32)
00230 {
00231     assertd(pData != NULL);
00232     Len=sprintf(pData, "%g", val);
00233 }
00234 
00235 
00236 
00237 /*-------------------------------------------------------------------------------------------------
00238     Buffer management
00239 -------------------------------------------------------------------------------------------------*/
00240 
00241 
00242 
00243 //
00244 // Make sure that the allocated buffer is at least <len> in size
00245 //
00246 void STR_String::AllocBuffer(int len, bool keep_contents)
00247 {
00248     // Check if we have enough space
00249     if (len+1 <= Max) return;
00250 
00251     // Reallocate string
00252     char *new_data = new char [len+8];
00253     if (keep_contents) memcpy(new_data, pData, Len);
00254     delete[] pData;
00255 
00256     // Accept new data
00257     Max = len+8;
00258     pData = new_data;
00259     assertd(pData != NULL);
00260 }
00261     
00262 
00263 
00264 /*-------------------------------------------------------------------------------------------------
00265     Basic string operations
00266 -------------------------------------------------------------------------------------------------*/
00267 
00268 
00269 
00270 //
00271 // Format string (as does sprintf)
00272 //
00273 STR_String& STR_String::Format(const char *fmt, ...)
00274 {
00275     AllocBuffer(2048, false);
00276 
00277     assertd(pData != NULL);
00278     // Expand arguments and format to string
00279     va_list args;
00280     va_start(args, fmt);
00281     Len = vsprintf(pData, fmt, args);
00282     assertd(Len <= 2048);
00283     va_end(args);
00284 
00285     return *this;
00286 }
00287 
00288 
00289 
00290 //
00291 // Format string (as does sprintf)
00292 //
00293 STR_String& STR_String::FormatAdd(const char *fmt, ...)
00294 {
00295     AllocBuffer(2048, false);
00296 
00297     assertd(pData != NULL);
00298     // Expand arguments and format to string
00299     va_list args;
00300     va_start(args, fmt);
00301     Len += vsprintf(pData+Len, fmt, args);
00302     assertd(Len <= 2048);
00303     va_end(args);
00304 
00305     return *this;
00306 }
00307 
00308 
00309 
00310 /*-------------------------------------------------------------------------------------------------
00311     Properties
00312 -------------------------------------------------------------------------------------------------*/
00313 
00314 
00315 
00316 //
00317 // Check if string is entirely in UPPERCase
00318 //
00319 bool STR_String::IsUpper() const
00320 {
00321     for (int i=0; i<Len; i++)
00322         if (isLower(pData[i]))
00323             return false;
00324 
00325     return true;
00326 }
00327 
00328 
00329 
00330 //
00331 // Check if string is entirely in lowerCase
00332 //
00333 bool STR_String::IsLower() const
00334 {
00335     for (int i=0; i<Len; i++)
00336         if (isUpper(pData[i]))
00337             return false;
00338 
00339     return true;
00340 }
00341 
00342 
00343 
00344 /*-------------------------------------------------------------------------------------------------
00345     Search/Replace
00346 -------------------------------------------------------------------------------------------------*/
00347 
00348 
00349 
00350 //
00351 // Find the first orccurence of <c> in the string
00352 //
00353 int STR_String::Find(char c, int pos) const
00354 {
00355     assertd(pos >= 0);
00356     assertd(Len==0 || pos<Len);
00357     assertd(pData != NULL);
00358     char *find_pos = strchr(pData+pos, c);
00359     return (find_pos) ? (find_pos-pData) : -1;
00360 }
00361 
00362 
00363 
00364 //
00365 // Find the first occurrence of <str> in the string
00366 //
00367 int STR_String::Find(const char *str, int pos) const
00368 {
00369     assertd(pos >= 0);
00370     assertd(Len==0 || pos<Len);
00371     assertd(pData != NULL);
00372     char *find_pos = strstr(pData+pos, str);
00373     return (find_pos) ? (find_pos-pData) : -1;
00374 }
00375 
00376 
00377 
00378 //
00379 // Find the first occurrence of <str> in the string
00380 //
00381 int STR_String::Find(rcSTR_String str, int pos) const
00382 {
00383     assertd(pos >= 0);
00384     assertd(Len==0 || pos<Len);
00385     assertd(pData != NULL);
00386     char *find_pos = strstr(pData+pos, str.ReadPtr());
00387     return (find_pos) ? (find_pos-pData) : -1;
00388 }
00389 
00390 
00391 
00392 //
00393 // Find the last occurrence of <c> in the string
00394 //
00395 int STR_String::RFind(char c) const
00396 {
00397     assertd(pData != NULL);
00398     char *pos = strrchr(pData, c);
00399     return (pos) ? (pos-pData) : -1;
00400 }
00401 
00402 
00403 
00404 //
00405 // Find the first occurrence of any character in character set <set> in the string
00406 //
00407 int STR_String::FindOneOf(const char *set, int pos) const
00408 {
00409     assertd(pos >= 0);
00410     assertd(Len==0 || pos<Len);
00411     assertd(pData != NULL);
00412     char *find_pos = strpbrk(pData+pos, set);
00413     return (find_pos) ? (find_pos-pData) : -1;
00414 }
00415 
00416 
00417 
00418 //
00419 // Replace a character in this string with another string
00420 //
00421 void STR_String::Replace(int pos, rcSTR_String str)
00422 {
00423     //bounds(pos, 0, Length()-1);
00424 
00425     if (str.Length() < 1)
00426     {
00427         // Remove one character from the string
00428         memcpy(pData+pos, pData+pos+1, Len-pos);
00429     }
00430     else
00431     {
00432         // Insert zero or more characters into the string
00433         AllocBuffer(Len + str.Length() - 1, true);
00434         if (str.Length() != 1) memcpy(pData+pos+str.Length(), pData+pos+1, Length()-pos);
00435         memcpy(pData+pos, str.ReadPtr(), str.Length());
00436     }
00437 
00438     Len += str.Length()-1;
00439 }
00440 
00441 
00442 
00443 //
00444 // Replace a substring of this string with another string
00445 //
00446 void STR_String::Replace(int pos, int num, rcSTR_String str)
00447 {
00448     //bounds(pos, 0, Length()-1);
00449     //bounds(pos+num, 0, Length());
00450     assertd(num >= 1);
00451 
00452     if (str.Length() < num)
00453     {
00454         // Remove some data from the string by replacement
00455         memcpy(pData+pos+str.Length(), pData+pos+num, Len-pos-num+1);
00456         memcpy(pData+pos, str.ReadPtr(), str.Length());
00457     }
00458     else
00459     {
00460         // Insert zero or more characters into the string
00461         AllocBuffer(Len + str.Length() - num, true);
00462         if (str.Length() != num) memcpy(pData+pos+str.Length(), pData+pos+num, Length()-pos-num+1);
00463         memcpy(pData+pos, str.ReadPtr(), str.Length());
00464     }
00465 
00466     Len += str.Length()-num;
00467 }
00468 
00469 
00470 
00471 /*-------------------------------------------------------------------------------------------------
00472     Comparison
00473 -------------------------------------------------------------------------------------------------*/
00474 
00475 
00476 
00477 //
00478 // Compare two strings and return the result, <0 if *this<rhs, >0 if *this>rhs or 0 if *this==rhs
00479 //
00480 int STR_String::Compare(rcSTR_String rhs) const
00481 {
00482     return strcmp(pData, rhs.pData);
00483 }
00484 
00485 
00486 
00487 //
00488 // Compare two strings without respecting case and return the result, <0 if *this<rhs, >0 if *this>rhs or 0 if *this==rhs
00489 //
00490 int STR_String::CompareNoCase(rcSTR_String rhs) const
00491 {
00492 #ifdef WIN32
00493     return stricmp(pData, rhs.pData);
00494 #else
00495     return strcasecmp(pData, rhs.pData);
00496 #endif
00497 }
00498 
00499 
00500 
00501 /*-------------------------------------------------------------------------------------------------
00502     Formatting
00503 -------------------------------------------------------------------------------------------------*/
00504 
00505 
00506 
00507 //
00508 // Capitalize string, "heLLo" -> "HELLO"
00509 //
00510 STR_String& STR_String::Upper()
00511 {
00512     assertd(pData != NULL);
00513 #ifdef WIN32
00514     _strupr(pData);
00515 #else
00516     for (int i=0;i<Len;i++)
00517         pData[i] = (pData[i] >= 'a' && pData[i] <= 'z')?pData[i]+'A'-'a':pData[i];
00518 #endif
00519     return *this;
00520 }
00521 
00522 
00523 
00524 //
00525 // Lower string, "heLLo" -> "hello"
00526 //
00527 STR_String& STR_String::Lower()
00528 {
00529     assertd(pData != NULL);
00530 #ifdef WIN32
00531     _strlwr(pData);
00532 #else
00533     for (int i=0;i<Len;i++)
00534         pData[i] = (pData[i] >= 'A' && pData[i] <= 'Z')?pData[i]+'a'-'A':pData[i];
00535 #endif
00536     return *this;
00537 }
00538 
00539 
00540 
00541 //
00542 // Capitalize string, "heLLo" -> "Hello"
00543 //
00544 STR_String& STR_String::Capitalize()
00545 {
00546     assertd(pData != NULL);
00547 #ifdef WIN32
00548     if (Len>0) pData[0] = toupper(pData[0]);
00549     if (Len>1) _strlwr(pData+1);
00550 #else
00551     if (Len > 0)
00552         pData[0] = (pData[0] >= 'A' && pData[0] <= 'A')?pData[0]+'a'-'A':pData[0];
00553     for (int i=1;i<Len;i++)
00554         pData[i] = (pData[i] >= 'a' && pData[i] <= 'z')?pData[i]+'A'-'a':pData[i];
00555 #endif
00556     return *this;
00557 }
00558 
00559 
00560 
00561 //
00562 // Trim whitespace from the left side of the string
00563 //
00564 STR_String& STR_String::TrimLeft()
00565 {
00566     int skip;
00567     assertd(pData != NULL);
00568     for (skip=0; isSpace(pData[skip]); skip++, Len--)
00569         {};
00570     memmove(pData, pData+skip, Len+1);
00571     return *this;
00572 }
00573 
00574 
00575 
00576 //
00577 // Trim whitespaces from the right side of the string
00578 //
00579 STR_String& STR_String::TrimRight()
00580 {
00581     assertd(pData != NULL);
00582     while (Len && isSpace(pData[Len-1])) Len--;
00583     pData[Len]=0;
00584     return *this;
00585 }
00586 
00587 
00588 
00589 //
00590 // Trim spaces from both sides of the character set
00591 //
00592 STR_String& STR_String::Trim()
00593 {
00594     TrimRight();
00595     TrimLeft();
00596     return *this;
00597 }
00598 
00599 
00600 
00601 //
00602 // Trim characters from the character set <set> from the left side of the string
00603 //
00604 STR_String& STR_String::TrimLeft(char *set)
00605 {
00606     int skip;
00607     assertd(pData != NULL);
00608     for (skip=0; Len && strchr(set, pData[skip]); skip++, Len--)
00609         {};
00610     memmove(pData, pData+skip, Len+1);
00611     return *this;
00612 }
00613 
00614 
00615 
00616 //
00617 // Trim characters from the character set <set> from the right side of the string
00618 //
00619 STR_String& STR_String::TrimRight(char *set)
00620 {
00621     assertd(pData != NULL);
00622     while (Len && strchr(set, pData[Len-1])) Len--;
00623     pData[Len]=0;
00624     return *this;
00625 }
00626 
00627 
00628 
00629 //
00630 // Trim characters from the character set <set> from both sides of the character set
00631 //
00632 STR_String& STR_String::Trim(char *set)
00633 {
00634     TrimRight(set);
00635     TrimLeft(set);
00636     return *this;
00637 }
00638 
00639 
00640 
00641 //
00642 // Trim quotes from both sides of the string
00643 //
00644 STR_String& STR_String::TrimQuotes()
00645 {
00646     // Trim quotes if they are on both sides of the string
00647     assertd(pData != NULL);
00648     if ((Len >= 2) && (pData[0] == '\"') && (pData[Len-1] == '\"'))
00649     {
00650         memmove(pData, pData+1, Len-2+1);
00651         Len-=2;
00652     }
00653     return *this;
00654 }
00655 
00656 
00657 
00658 /*-------------------------------------------------------------------------------------------------
00659     Assignment/Concatenation
00660 -------------------------------------------------------------------------------------------------*/
00661 
00662 
00663 
00664 //
00665 // Set the string's conents to a copy of <src> with length <len>
00666 //
00667 rcSTR_String STR_String::Copy(const char *src, int len)
00668 {
00669     assertd(len>=0);
00670     assertd(src);
00671     assertd(pData != NULL);
00672 
00673     AllocBuffer(len, false);
00674     Len = len;
00675     memcpy(pData, src, len);
00676     pData[Len] = 0;
00677 
00678     return *this;
00679 }
00680 
00681 
00682 
00683 //
00684 // Concate a number of bytes to the current string
00685 //
00686 rcSTR_String STR_String::Concat(const char *data, int len)
00687 {
00688     assertd(Len>=0);
00689     assertd(len>=0);
00690     assertd(data);
00691     assertd(pData != NULL);
00692 
00693     AllocBuffer(Len+len, true);
00694     memcpy(pData+Len, data, len);
00695     Len+=len;
00696     pData[Len] = 0;
00697 
00698     return *this;
00699 }
00700 
00701 
00702 
00703 
00704 
00705 vector<STR_String>  STR_String::Explode(char c) const
00706 {
00707     STR_String              lcv = *this;
00708     vector<STR_String>      uc;
00709 
00710     while (lcv.Length())
00711     {
00712         int pos = lcv.Find(c);
00713         if (pos < 0)
00714         {
00715             uc.push_back(lcv);
00716             lcv.Clear();
00717         } else
00718         {
00719             uc.push_back(lcv.Left(pos));
00720             lcv = lcv.Mid(pos+1);
00721         }
00722     }
00723 
00724     //uc. -= STR_String("");
00725 
00726     return uc;
00727 }
00728 
00729 
00730 /*
00731 
00732 int     STR_String::Serialize(pCStream stream)
00733 {
00734     if (stream->GetAccess() == CStream::Access_Read)
00735     {
00736         int ln;
00737         stream->Read(&ln, sizeof(ln));
00738         AllocBuffer(ln, false);
00739         stream->Read(pData, ln); 
00740         pData[ln]   = '\0';
00741         Len         = ln;
00742     } else
00743     {
00744         stream->Write(&Len, sizeof(Len));
00745         stream->Write(pData, Len);
00746     }
00747 
00748     return Len + sizeof(Len);
00749 }
00750 */
00751