00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef __UT_String_h__
00022 #define __UT_String_h__
00023
00024 #include "UT_API.h"
00025 #include <iostream.h>
00026 #include <string.h>
00027 #include <malloc.h>
00028 #include <ctype.h>
00029 #include <string>
00030 #include "UT_Assert.h"
00031 #include "UT_Algorithm.h"
00032
00033 #ifdef WIN32
00034 #define strcasecmp stricmp
00035 #define strncasecmp strnicmp
00036 #endif
00037
00038 class UT_WorkBuffer;
00039 class UT_String;
00040 class UT_StringCshIO;
00041 class UT_WorkArgs;
00042 class UT_IStream;
00043
00044
00045
00046
00047 UT_API extern void UTvarLookup(const char *name, UT_String &result);
00048 UT_API extern void UTexprLookup(const char *name, UT_String &result);
00049
00050 inline bool UTisstring(const char *s) { return s && *s; }
00051
00052 class UT_API UT_String {
00053 public:
00054 enum UT_AlwaysDeepType { ALWAYS_DEEP };
00055
00056
00057
00058
00059
00060
00061 UT_String(const char *str = 0, int deepCopy = 0, int len = -1);
00062
00063
00064 UT_String(UT_AlwaysDeepType, const char *str = 0)
00065 : myIsReference(false),
00066 myIsAlwaysDeep(true)
00067 { myData = str ? strdup(str) : 0; }
00068
00069
00070
00071
00072 UT_String(const UT_String &str);
00073
00074 ~UT_String();
00075
00076
00077 void setAlwaysDeep(bool deep)
00078 {
00079 myIsAlwaysDeep = deep;
00080 if (deep && myIsReference)
00081 {
00082 if (myData != NULL)
00083 harden();
00084 else
00085 {
00086
00087
00088
00089 myIsReference = false;
00090 }
00091 }
00092 }
00093 bool isAlwaysDeep() const
00094 {
00095 return myIsAlwaysDeep;
00096 }
00097
00098
00099 void swap( UT_String &other );
00100 void harden();
00101 void harden(const char *s, int len = -1);
00102 void hardenIfNeeded();
00103 void hardenIfNeeded(const char *s);
00104
00105
00106 bool isHard() const { return !myIsReference; }
00107
00108
00109
00110
00111
00112 char * steal(void)
00113 {
00114 if (!myIsAlwaysDeep)
00115 {
00116 if (myIsReference)
00117 myData = strdup(myData ? myData : "");
00118 myIsReference = true;
00119 return myData;
00120 }
00121 else
00122 {
00123
00124
00125 return strdup(myData ? myData : "");
00126 }
00127 }
00128
00129
00130
00131
00132
00133 void adopt(char *s)
00134 {
00135 if (!myIsReference)
00136 {
00137 if (s != myData)
00138 free(myData);
00139 }
00140 myData = s;
00141 myIsReference = false;
00142 }
00143 void adopt(UT_String &str)
00144 {
00145 adopt(str.steal());
00146 }
00147
00148
00149
00150
00151 void saveBinary(ostream &os) const { save(os, 1); }
00152 void saveAscii(ostream &os) const { save(os, 0); }
00153
00154
00155 bool load(UT_IStream &is);
00156 void save(ostream &os, int binary) const;
00157
00158
00159 void clear()
00160 { *this = (const char *)NULL; }
00161
00162
00163 void prepend(const char *prefix);
00164 void prepend(char ch);
00165
00166
00167 void append(char ch);
00168
00169 UT_String &operator=(const UT_String &str);
00170 UT_String &operator=(const char *str);
00171 UT_String &operator+=(const char *str)
00172 {
00173 if (!isstring())
00174 {
00175
00176
00177
00178 harden(str);
00179 }
00180 else
00181 {
00182 bool same = (str == myData);
00183 harden();
00184 if (str)
00185 {
00186 int mylen = (int)strlen(myData);
00187 myData = (char *)realloc(myData,
00188 mylen+strlen(str)+1);
00189 if (!same)
00190 {
00191 strcpy(&myData[mylen], str);
00192 }
00193 else
00194 {
00195 memcpy(myData + mylen, myData, mylen);
00196 myData[mylen * 2] = '\0';
00197 }
00198 }
00199 }
00200 return *this;
00201 }
00202
00203 UT_String &operator+=(const UT_String &str)
00204 {
00205 *this += (const char *)str.myData;
00206 return *this;
00207 }
00208 unsigned operator==(const char *str) const
00209 {
00210 if (!myData || !str)
00211 return (!myData && !str) ? 1 : 0;
00212 return (strcmp(str, myData) == 0) ? 1 : 0;
00213 }
00214 unsigned operator==(const UT_String &str) const
00215 {
00216 if (!myData || !str.myData)
00217 return (!myData && !str.myData) ? 1 : 0;
00218 return (strcmp(str.myData, myData) == 0) ? 1 : 0;
00219 }
00220 unsigned operator!=(const char *str) const
00221 {
00222 unsigned rval;
00223 if (!myData || !str)
00224 {
00225 rval = (!myData && !str) ? 0U : 1U;
00226 }
00227 else rval = (strcmp(str, myData) != 0) ? 1U : 0U;
00228 return rval;
00229 }
00230 unsigned operator!=(const UT_String &str) const
00231 {
00232 return *this != (const char *)str.myData;
00233 }
00234 unsigned operator<(const char *str) const
00235 {
00236 unsigned rval;
00237 if (!myData)
00238 {
00239 if (str)
00240 rval = 1;
00241 else
00242 rval = 0;
00243 }
00244 else
00245 {
00246 if (!str)
00247 rval = 0;
00248 else
00249 rval = (strcmp(myData, str) < 0) ? 1U : 0U;
00250 }
00251 return rval;
00252 }
00253 unsigned operator<(const UT_String &str) const
00254 {
00255 return *this < (const char *)str.myData;
00256 }
00257
00258 unsigned operator<=(const char *str) const
00259 {
00260 unsigned rval;
00261 if (!myData)
00262 rval = 1;
00263 else
00264 {
00265 if (!str)
00266 rval = 0;
00267 else
00268 rval = (strcmp(myData, str) > 0) ? 0U : 1U;
00269 }
00270 return rval;
00271 }
00272 unsigned operator<=(const UT_String &str) const
00273 {
00274 return *this <= (const char *)str.myData;
00275 }
00276 unsigned operator>(const char *str) const
00277 {
00278 unsigned rval;
00279 if (!myData)
00280 rval = 0;
00281 else
00282 {
00283 if (!str)
00284 rval = 1;
00285 else
00286 rval = (strcmp(myData, str) > 0) ? 1U : 0U;
00287 }
00288 return rval;
00289 }
00290 unsigned operator>(const UT_String &str) const
00291 {
00292 return *this > (const char *)str.myData;
00293 }
00294 unsigned operator>=(const char *str) const
00295 {
00296 unsigned rval;
00297 if (!myData)
00298 {
00299 if (str)
00300 rval = 0;
00301 else
00302 rval = 1;
00303 }
00304 else
00305 {
00306 if (!str)
00307 rval = 1;
00308 else
00309 rval = (strcmp(myData, str) < 0) ? 0U : 1U;
00310 }
00311 return rval;
00312 }
00313 unsigned operator>=(const UT_String &str) const
00314 {
00315 return *this >= (const char *)str.myData;
00316 }
00317
00318 #ifdef METROWERKS_BUILD
00319 operator char *() const
00320 { return myData; }
00321 #else
00322 operator const char *() const
00323 { return (const char *)myData; }
00324 operator char *()
00325 { return myData; }
00326 #endif
00327 const char *buffer() const
00328 { return myData; }
00329 const char *nonNullBuffer() const
00330 { return myData ? myData : ""; }
00331 char operator()(unsigned i) const
00332 {
00333 UT_ASSERT_P( isstring() );
00334 UT_ASSERT_SLOW(i <= strlen(myData));
00335 return myData[i];
00336 }
00337 char &operator()(unsigned i)
00338 {
00339 harden();
00340 return myData[i];
00341 }
00342 int toInt() const;
00343 fpreal toFloat() const;
00344
00345
00346
00347
00348 std::string toStdString() const;
00349
00350
00351
00352
00353
00354 unsigned length(void) const
00355 { return (myData) ? (unsigned)strlen(myData) : 0; }
00356 int64 getMemoryUsage() const
00357 {
00358 return
00359 sizeof(*this)
00360 + (!myIsReference ? (length() + 1)*sizeof(char) : 0);
00361 }
00362
00363 char *findChar(int c) const
00364 { return (myData) ? strchr(myData, c) : 0; }
00365
00366
00367
00368
00369
00370 char *findChar(const char *str) const
00371 { return (myData) ? strpbrk(myData, str) : NULL; }
00372 char *findChar(const UT_String &str) const
00373 { return findChar((const char *) str); }
00374 char *lastChar(int c) const
00375 { return myData ? strrchr(myData, c):0; }
00376
00377 int countChar(int c) const;
00378 char *findNonSpace() const;
00379 const char *findWord(const char *word) const;
00380 bool findString(const char *str, bool fullword,
00381 bool usewildcards) const;
00382 int changeWord(const char *from, const char *to, int all=1);
00383 int changeString(const char *from, const char *to, bool fullword);
00384 int changeQuotedWord(const char *from, const char *to,
00385 int quote = '`', int all = 1);
00386
00387 int findLongestCommonSuffix( const char *with );
00388
00389
00390
00391
00392
00393
00394 int substr(UT_String &buf, int index, int len=0) const;
00395
00396
00397
00398 unsigned isFloat(int skip_spaces = 0, int loose = 0) const;
00399 unsigned isInteger(int skip_spaces = 0) const;
00400
00401 void toUpper()
00402 {
00403 char *ptr;
00404 harden();
00405 for (ptr=myData; *ptr; ptr++)
00406 *ptr = (char)toupper(*ptr);
00407 }
00408 void toLower()
00409 {
00410 char *ptr;
00411 harden();
00412 for (ptr=myData; *ptr; ptr++)
00413 *ptr = (char)tolower(*ptr);
00414 }
00415
00416
00417
00418
00419
00420 const char *fileName() const
00421 {
00422 const char *fname;
00423
00424 if (!myData) return 0;
00425
00426 fname = strrchr(myData, '/');
00427 if (!fname)
00428 fname = myData;
00429 else
00430 fname++;
00431 return fname;
00432 }
00433 const char *fileExtension( ) const
00434 {
00435 const char * slash;
00436 const char * dot;
00437
00438 if( !isstring() )
00439 return 0;
00440
00441 dot = lastChar( '.' );
00442 slash = lastChar( '/' );
00443
00444 return (slash < dot) ? dot : 0;
00445 }
00446
00447
00448
00449 UT_String pathUpToExtension() const;
00450
00451
00452
00453
00454
00455
00456 void splitPath(UT_String &dir_name, UT_String &file_name) const;
00457
00458
00459
00460
00461
00462
00463
00464 int parseNumberedFilename(UT_String &prefix,
00465 UT_String &frame,
00466 UT_String &suff,
00467 bool negative = true,
00468 bool fractional = false) const;
00469
00470 int isstring() const
00471 { return (myData && *myData); }
00472
00473
00474
00475
00476 int trimSpace(bool leaveSingleSpaceBetweenWords = false);
00477
00478
00479
00480 int trimBoundingSpace();
00481
00482
00483
00484
00485 int strip(const char *chars);
00486
00487
00488
00489 void protectString();
00490
00491
00492
00493 bool isQuotedString(char delimiter='\'') const;
00494
00495
00496
00497
00498
00499 UT_String makeQuotedString(char delimiter='\'') const;
00500
00501
00502
00503
00504 UT_String makeSmartQuotedString(char default_delimiter='\'') const;
00505
00506 void expandControlSequences();
00507
00508 bool hasWhiteSpace() const;
00509
00510 void removeTrailingSpace();
00511
00512 void removeTrailingDigits();
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524 int cshParse(char *argv[], int maxArgs,
00525 void (*vlookup)(const char *, UT_String&)=UTvarLookup,
00526 void (*elookup)(const char *, UT_String&)=UTexprLookup,
00527 int *error = 0,
00528 UT_StringCshIO *io=0);
00529
00530 int cshParse(UT_WorkArgs &argv,
00531 void (*vlookup)(const char *, UT_String&)=UTvarLookup,
00532 void (*elookup)(const char *, UT_String&)=UTexprLookup,
00533 int *error = 0,
00534 UT_StringCshIO *io=0);
00535
00536
00537
00538
00539
00540
00541
00542 int dosParse(UT_WorkArgs &argv);
00543 int dosParse(char *argv[], int maxArgs);
00544
00545
00546
00547
00548
00549
00550 int parse(char *argv[], int maxArgs)
00551 {
00552 harden();
00553 return parseInPlace(argv, maxArgs);
00554 }
00555
00556
00557 int parseInPlace(char *argv[], int maxArgs);
00558 int parse(UT_WorkArgs &argv)
00559 {
00560 harden();
00561 return parseInPlace(argv);
00562 }
00563 int parseInPlace(UT_WorkArgs &argv);
00564
00565 int tokenize(char *argv[], int maxArgs, char separator)
00566 {
00567 harden();
00568 return tokenizeInPlace(argv, maxArgs, separator);
00569 }
00570 int tokenizeInPlace(char *argv[], int maxArgs, char separator);
00571 int tokenize(UT_WorkArgs &argv, char separator)
00572 {
00573 harden();
00574 return tokenizeInPlace(argv, separator);
00575 }
00576 int tokenizeInPlace(UT_WorkArgs &argv, char separator);
00577 int tokenize(char *argv[], int maxArgs,
00578 const char *separators = " \t\n")
00579 {
00580 harden();
00581 return tokenizeInPlace(argv, maxArgs, separators);
00582 }
00583 int tokenizeInPlace(char *argv[], int maxArgs,
00584 const char *separators = " \t\n");
00585 int tokenize(UT_WorkArgs &argv, const char *separators = " \t\n")
00586 {
00587 harden();
00588 return tokenizeInPlace(argv, separators);
00589 }
00590 int tokenizeInPlace(UT_WorkArgs &argv,
00591 const char *separators = " \t\n");
00592
00593
00594 void expandVariables();
00595
00596
00597 inline unsigned hash() const
00598 {
00599 return hash(myData);
00600 }
00601
00602 static inline unsigned hash(const char *str, unsigned code = 0)
00603 {
00604 char c;
00605
00606
00607
00608
00609
00610
00611
00612
00613 if (str)
00614 {
00615 for (; c = *str; str++)
00616 {
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626 code = 37 * code + c;
00627 }
00628 }
00629 return code;
00630 }
00631
00632
00633
00634
00635
00636
00637 unsigned match(const char *pattern, int caseSensitive=1) const;
00638
00639
00640
00641
00642 unsigned multiMatch(const char *pattern,
00643 int caseSensitive, char separator) const;
00644 unsigned multiMatch(const char *pattern, int caseSensitive = 1,
00645 const char *separators = ", ",
00646 bool *explicitlyExcluded = 0,
00647 int *matchIndex = 0) const;
00648
00649
00650
00651 unsigned multiMatchRecord(const char *pattern, int maxpatterns,
00652 char *singles, int &nsingles,
00653 char **words, int &nwords,
00654 int case_sensitive = 1,
00655 const char *separators = ", ") const;
00656
00657
00658
00659
00660
00661
00662
00663 bool matchPattern(const UT_WorkArgs &pattern_args,
00664 bool assume_match=false);
00665
00666 static int multiMatchCheck(const char *pattern);
00667 static int wildcardMatchCheck(const char *pattern);
00668
00669
00670 unsigned contains(const char *pattern, int caseSensitive=1) const;
00671
00672 bool startsWith(const char *prefix) const;
00673
00674 bool endsWith(const char *suffix) const;
00675 bool endsWith(const char *suffix, bool case_sensitive) const;
00676
00677
00678
00679
00680
00681
00682
00683
00684 int traversePattern(int max, void *data,
00685 int (*func)(int num, int sec, void *data),
00686 unsigned int (*secfunc)(int num,void *data)=0,
00687 int offset=0) const;
00688
00689
00690 const char *fcontain(const char *pattern) const
00691 { return (myData) ? strstr(myData, pattern) : 0; }
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702 bool patternRename(const char *match_pattern, const char *replace);
00703
00704
00705
00706
00707
00708
00709 UT_String *base(void) const;
00710 const char *suffix(void) const;
00711
00712
00713
00714
00715 void incrementNumberedName();
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728 static ostream &setFormat(ostream &os, const char *fmt);
00729 ostream &setFormat(ostream &os);
00730
00731 int replacePrefix(const char *oldpref,
00732 const char *newpref);
00733 int replaceSuffix(const char *oldsuffix,
00734 const char *newsuffix);
00735
00736
00737
00738
00739
00740
00741 int expandArrays(char *names[], int max);
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751 int format(int cols);
00752
00753
00754
00755 int substitute( const char *find, const char *replacement,
00756 bool all = true );
00757
00758
00759
00760 int replace( int pos, int len, const char *str );
00761
00762
00763 int insert(int pos, const char *str)
00764 { return replace(pos, 0, str); }
00765
00766
00767
00768
00769 static int compareNumberedString(const char *s1, const char *s2,
00770 bool case_sensitive=true);
00771 static int qsortCmpNumberedString(const void *v1, const void *v2);
00772 static int qsortCmpNumberedString(char *const*v1, char *const*v2);
00773
00774
00775
00776 static int compareNumberedFilename(const char *s1, const char *s2,
00777 bool case_sensitive=false);
00778 static int qsortCmpNumberedFilename(const void *v1, const void *v2);
00779 static int qsortCmpNumberedFilename(char *const*v1, char *const*v2);
00780
00781
00782
00783
00784 static int itoa(char *str, int i);
00785 static int utoa(char *str, unsigned i);
00786
00787
00788 void itoa(int i);
00789 void utoa(int i);
00790
00791
00792
00793
00794 void itoa_pretty(int64 val);
00795
00796
00797
00798
00799 int sprintf(const char *fmt, ...) SYS_PRINTF_CHECK_ATTRIBUTE(2, 3);
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810 int forceValidVariableName(const char *safechars = NULL);
00811
00812
00813
00814 bool forceAlphaNumeric();
00815
00816
00817
00818
00819
00820 void getRelativePath(const char *src_fullpath,
00821 const char *dest_fullpath);
00822
00823
00824
00825
00826
00827
00828
00829
00830 static int findLongestCommonPathPrefix(const char *fullpath1, int len1,
00831 const char *fullpath2, int len2);
00832
00833
00834
00835 bool isAbsolutePath(bool file_path=false) const;
00836
00837
00838
00839
00840
00841 bool collapseAbsolutePath(bool file_path=false);
00842
00843
00844
00845
00846
00847 bool truncateMiddle(int max_length);
00848
00849 static const UT_String &getEmptyString();
00850
00851
00852
00853
00854
00855 void extractModifiers(UT_String &modifiers);
00856
00857
00858
00859
00860
00861 bool applyModifiers(const UT_String &modifiers);
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871 bool applyNextModifier(const char *mod, bool all);
00872
00873 static bool isValidModifier(const char c, bool have_subst);
00874
00875
00876
00877
00878 static int findModifiers(const char *src);
00879
00880
00881
00882
00883
00884 UT_String removeRange ();
00885
00886 private:
00887 void freeData();
00888 char *myData;
00889 bool myIsReference:1,
00890 myIsAlwaysDeep:1;
00891
00892
00893
00894
00895 friend UT_API ostream &operator<<(ostream &os, const UT_String &d);
00896 };
00897
00898 class UT_API UT_StringCshIO {
00899 public:
00900 UT_String myOut;
00901 UT_String myErr;
00902 UT_String myIn;
00903 short myDoubleOut;
00904 short myDoubleIn;
00905 };
00906
00907 UT_API ostream & do_setformat(ostream &os, const char fmt[]);
00908
00909 UT_SWAPPER_CLASS(UT_String);
00910
00911 #endif