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