|
Blender
V2.59
|
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