1 //************************************************************************** 2 //** 3 //** ## ## ## ## ## #### #### ### ### 4 //** ## ## ## ## ## ## ## ## ## ## #### #### 5 //** ## ## ## ## ## ## ## ## ## ## ## ## ## ## 6 //** ## ## ######## ## ## ## ## ## ## ## ### ## 7 //** ### ## ## ### ## ## ## ## ## ## 8 //** # ## ## # #### #### ## ## 9 //** 10 //** $Id: str.h 4362 2010-12-31 13:29:30Z dj_jl $ 11 //** 12 //** Copyright (C) 1999-2010 Jānis Legzdiņš 13 //** 14 //** This program is free software; you can redistribute it and/or 15 //** modify it under the terms of the GNU General Public License 16 //** as published by the Free Software Foundation; either version 2 17 //** of the License, or (at your option) any later version. 18 //** 19 //** This program is distributed in the hope that it will be useful, 20 //** but WITHOUT ANY WARRANTY; without even the implied warranty of 21 //** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 //** GNU General Public License for more details. 23 //** 24 //************************************************************************** 25 // 26 // Dynamic string class. 27 // 28 //************************************************************************** 29 30 #define TEXT_COLOUR_ESCAPE '\034' 31 32 class VStr 33 { 34 private: 35 char* Str; 36 37 void Resize(int NewLen); 38 39 public: 40 // Constructors. VStr()41 VStr() 42 : Str(NULL) 43 {} VStr(ENoInit)44 VStr(ENoInit) 45 {} VStr(const char * InStr)46 VStr(const char* InStr) 47 : Str(NULL) 48 { 49 if (*InStr) 50 { 51 Resize(int(Length(InStr))); 52 Cpy(Str, InStr); 53 } 54 } VStr(const VStr & InStr)55 VStr(const VStr& InStr) 56 : Str(NULL) 57 { 58 if (InStr.Str) 59 { 60 Resize(int(InStr.Length())); 61 Cpy(Str, InStr.Str); 62 } 63 } 64 VStr(const VStr& InStr, int Start, int Len); VStr(char InChr)65 explicit VStr(char InChr) 66 : Str(NULL) 67 { 68 Resize(1); 69 Str[0] = InChr; 70 } VStr(bool InBool)71 explicit VStr(bool InBool) 72 : Str(NULL) 73 { 74 if (InBool) 75 { 76 Resize(4); 77 Cpy(Str, "true"); 78 } 79 else 80 { 81 Resize(5); 82 Cpy(Str, "false"); 83 } 84 } VStr(int InInt)85 explicit VStr(int InInt) 86 : Str(NULL) 87 { 88 char Buf[64]; 89 90 sprintf(Buf, "%d", InInt); 91 Resize(int(Length(Buf))); 92 Cpy(Str, Buf); 93 } VStr(unsigned InInt)94 explicit VStr(unsigned InInt) 95 : Str(NULL) 96 { 97 char Buf[64]; 98 99 sprintf(Buf, "%u", InInt); 100 Resize(int(Length(Buf))); 101 Cpy(Str, Buf); 102 } VStr(float InFloat)103 explicit VStr(float InFloat) 104 : Str(NULL) 105 { 106 char Buf[64]; 107 108 sprintf(Buf, "%f", InFloat); 109 Resize(int(Length(Buf))); 110 Cpy(Str, Buf); 111 } VStr(const VName & InName)112 explicit VStr(const VName& InName) 113 : Str(NULL) 114 { 115 Resize(int(Length(*InName))); 116 Cpy(Str, *InName); 117 } 118 119 // Destructor. ~VStr()120 ~VStr() 121 { 122 Clean(); 123 } 124 125 // Clears the string. Clean()126 void Clean() 127 { 128 Resize(0); 129 } 130 // Return length of the string. Length()131 size_t Length() const 132 { 133 return Str ? ((int*)Str)[-1] : 0; 134 } 135 // Return number of characters in a UTF-8 string. Utf8Length()136 size_t Utf8Length() const 137 { 138 return Str ? Utf8Length(Str) : 0; 139 } 140 // Return C string. 141 const char* operator*() const 142 { 143 return Str ? Str : ""; 144 } 145 // Check if string is empty. IsEmpty()146 bool IsEmpty() const 147 { 148 return !Str; 149 } IsNotEmpty()150 bool IsNotEmpty() const 151 { 152 return !!Str; 153 } 154 155 // Character ancestors. 156 char operator[](int Idx) const 157 { 158 return Str[Idx]; 159 } 160 char& operator[](int Idx) 161 { 162 return Str[Idx]; 163 } 164 165 // Assignement operators. 166 VStr& operator=(const char* InStr) 167 { 168 Resize(int(Length(InStr))); 169 if (*InStr) 170 Cpy(Str, InStr); 171 return *this; 172 } 173 VStr& operator=(const VStr& InStr) 174 { 175 Resize(int(InStr.Length())); 176 if (InStr.Str) 177 Cpy(Str, InStr.Str); 178 return *this; 179 } 180 181 // Concatenation operators. 182 VStr& operator+=(const char* InStr) 183 { 184 if (*InStr) 185 { 186 int l = int(Length()); 187 Resize(int(l + Length(InStr))); 188 Cpy(Str + l, InStr); 189 } 190 return *this; 191 } 192 VStr& operator+=(const VStr& InStr) 193 { 194 if (InStr.Length()) 195 { 196 int l = int(Length()); 197 Resize(int(l + InStr.Length())); 198 Cpy(Str + l, *InStr); 199 } 200 return *this; 201 } 202 VStr& operator+=(char InChr) 203 { 204 int l = int(Length()); 205 Resize(int(l + 1)); 206 Str[l] = InChr; 207 return *this; 208 } 209 VStr& operator+=(bool InBool) 210 { 211 return operator+=(InBool ? "true" : "false"); 212 } 213 VStr& operator+=(int InInt) 214 { 215 char Buf[64]; 216 217 sprintf(Buf, "%d", InInt); 218 return operator+=(Buf); 219 } 220 VStr& operator+=(unsigned InInt) 221 { 222 char Buf[64]; 223 224 sprintf(Buf, "%u", InInt); 225 return operator+=(Buf); 226 } 227 VStr& operator+=(float InFloat) 228 { 229 char Buf[64]; 230 231 sprintf(Buf, "%f", InFloat); 232 return operator+=(Buf); 233 } 234 VStr& operator+=(const VName& InName) 235 { 236 return operator+=(*InName); 237 } 238 friend VStr operator+(const VStr& S1, const char* S2) 239 { 240 VStr Ret(S1); 241 Ret += S2; 242 return Ret; 243 } 244 friend VStr operator+(const VStr& S1, const VStr& S2) 245 { 246 VStr Ret(S1); 247 Ret += S2; 248 return Ret; 249 } 250 friend VStr operator+(const VStr& S1, char S2) 251 { 252 VStr Ret(S1); 253 Ret += S2; 254 return Ret; 255 } 256 friend VStr operator+(const VStr& S1, bool InBool) 257 { 258 VStr Ret(S1); 259 Ret += InBool; 260 return Ret; 261 } 262 friend VStr operator+(const VStr& S1, int InInt) 263 { 264 VStr Ret(S1); 265 Ret += InInt; 266 return Ret; 267 } 268 friend VStr operator+(const VStr& S1, unsigned InInt) 269 { 270 VStr Ret(S1); 271 Ret += InInt; 272 return Ret; 273 } 274 friend VStr operator+(const VStr& S1, float InFloat) 275 { 276 VStr Ret(S1); 277 Ret += InFloat; 278 return Ret; 279 } 280 friend VStr operator+(const VStr& S1, const VName& InName) 281 { 282 VStr Ret(S1); 283 Ret += InName; 284 return Ret; 285 } 286 287 // Comparison operators. 288 friend bool operator==(const VStr& S1, const char* S2) 289 { 290 return !Cmp(*S1, S2); 291 } 292 friend bool operator==(const VStr& S1, const VStr& S2) 293 { 294 return !Cmp(*S1, *S2); 295 } 296 friend bool operator!=(const VStr& S1, const char* S2) 297 { 298 return !!Cmp(*S1, S2); 299 } 300 friend bool operator!=(const VStr& S1, const VStr& S2) 301 { 302 return !!Cmp(*S1, *S2); 303 } 304 305 // Comparison functions. Cmp(const char * S2)306 int Cmp(const char* S2) const 307 { 308 return Cmp(**this, S2); 309 } Cmp(const VStr & S2)310 int Cmp(const VStr& S2) const 311 { 312 return Cmp(**this, *S2); 313 } ICmp(const char * S2)314 int ICmp(const char* S2) const 315 { 316 return ICmp(**this, S2); 317 } ICmp(const VStr & S2)318 int ICmp(const VStr& S2) const 319 { 320 return ICmp(**this, *S2); 321 } 322 323 bool StartsWith(const char*) const; 324 bool StartsWith(const VStr&) const; 325 bool EndsWith(const char*) const; 326 bool EndsWith(const VStr&) const; 327 328 VStr ToLower() const; 329 VStr ToUpper() const; 330 331 int IndexOf(char) const; 332 int IndexOf(const char*) const; 333 int IndexOf(const VStr&) const; 334 int LastIndexOf(char) const; 335 int LastIndexOf(const char*) const; 336 int LastIndexOf(const VStr&) const; 337 338 VStr Replace(const char*, const char*) const; 339 VStr Replace(const VStr&, const VStr&) const; 340 341 VStr Utf8Substring(int, int) const; 342 343 void Split(char, TArray<VStr>&) const; 344 void Split(const char*, TArray<VStr>&) const; 345 346 bool IsValidUtf8() const; 347 VStr Latin1ToUtf8() const; 348 349 // Serialisation operator. 350 friend VStream& operator<<(VStream& Strm, VStr& S) 351 { 352 if (Strm.IsLoading()) 353 { 354 vint32 Len; 355 Strm << STRM_INDEX(Len); 356 if (Len < 0) 357 Len = 0; 358 S.Resize(Len); 359 if (Len) 360 Strm.Serialise(S.Str, Len + 1); 361 } 362 else 363 { 364 vint32 Len = vint32(S.Length()); 365 Strm << STRM_INDEX(Len); 366 if (Len) 367 Strm.Serialise(S.Str, Len + 1); 368 } 369 return Strm; 370 } 371 372 VStr EvalEscapeSequences() const; 373 374 VStr RemoveColours() const; 375 376 VStr ExtractFilePath() const; 377 VStr ExtractFileName() const; 378 VStr ExtractFileBase() const; 379 VStr ExtractFileExtension() const; 380 VStr StripExtension() const; 381 VStr DefaultPath(const VStr& basepath) const; 382 VStr DefaultExtension(const VStr& extension) const; 383 VStr FixFileSlashes() const; 384 385 static size_t Length(const char*); 386 static size_t Utf8Length(const char*); 387 static size_t ByteLengthForUtf8(const char*, size_t); 388 static int GetChar(const char*&); 389 static VStr FromChar(int); 390 static int Cmp(const char*, const char*); 391 static int NCmp(const char*, const char*, size_t); 392 static int ICmp(const char*, const char*); 393 static int NICmp(const char*, const char*, size_t); 394 static void Cpy(char*, const char*); 395 static void NCpy(char*, const char*, size_t); 396 static char ToUpper(char); 397 static char ToLower(char); 398 }; 399 400 char *va(const char *text, ...) __attribute__ ((format(printf, 1, 2))); 401