Blender V2.61 - r43446
|
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