1 /* 2 * OpenClonk, http://www.openclonk.org 3 * 4 * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/ 5 * Copyright (c) 2009-2016, The OpenClonk Team and contributors 6 * 7 * Distributed under the terms of the ISC license; see accompanying file 8 * "COPYING" for details. 9 * 10 * "Clonk" is a registered trademark of Matthes Bender, used with permission. 11 * See accompanying file "TRADEMARK" for details. 12 * 13 * To redistribute this file separately, substitute the full license texts 14 * for the above references. 15 */ 16 // Standard buffer classes 17 18 #ifndef STDBUF_H 19 #define STDBUF_H 20 21 #include <zlib.h> 22 23 // debug memory management 24 #if defined(_DEBUG) && defined(_MSC_VER) 25 #include <crtdbg.h> 26 #endif 27 28 // Base buffer class. Either references or holds data. 29 class StdBuf 30 { 31 public: 32 33 // *** Construction 34 // Standard constructor 35 StdBuf() = default; 36 37 // Constructor from other buffer (copy construction): 38 // Will take over buffer ownership. Copies data if specified. 39 // Note: Construct with Buf2.getRef() to construct a reference (This will work for a constant Buf2, too) 40 StdBuf(StdBuf & Buf2, bool fCopy = false) pData(nullptr)41 : pData(nullptr) 42 { 43 if (fCopy) 44 Copy(Buf2); 45 else if (!Buf2.isRef()) 46 Take(std::move(Buf2)); 47 else 48 Ref(Buf2); 49 } 50 StdBuf(const StdBuf & Buf2, bool fCopy = true) pData(nullptr)51 : pData(nullptr) 52 { 53 if (fCopy) 54 Copy(Buf2); 55 else 56 Ref(Buf2); 57 } StdBuf(StdBuf && Buf2)58 StdBuf(StdBuf && Buf2) noexcept 59 : pData(nullptr) 60 { 61 if (!Buf2.isRef()) 62 Take(std::move(Buf2)); 63 else 64 Ref(Buf2); 65 } 66 67 // Set by constant data. Copies data if desired. 68 StdBuf(const void *pData, size_t iSize, bool fCopy = false) pData(pData)69 : pData(pData), iSize(iSize) 70 { 71 if (fCopy) Copy(); 72 } 73 ~StdBuf()74 ~StdBuf() 75 { 76 Clear(); 77 } 78 79 protected: 80 81 // Reference? Otherwise, this object holds the data. 82 bool fRef = true; 83 // Data 84 union 85 { 86 const void *pData = nullptr; 87 void *pMData; 88 #if defined(_DEBUG) 89 char *szString; // for debugger preview 90 #endif 91 }; 92 unsigned int iSize = 0; 93 94 public: 95 96 // *** Getters 97 isNull()98 bool isNull() const { return ! getData(); } getData()99 const void *getData() const { return fRef ? pData : pMData; } getMData()100 void *getMData() { assert(!fRef); return pMData; } getSize()101 size_t getSize() const { return iSize; } isRef()102 bool isRef() const { return fRef; } 103 getPtr(size_t i)104 const void *getPtr(size_t i) const { return reinterpret_cast<const char*>(getData()) + i; } getMPtr(size_t i)105 void *getMPtr(size_t i) { return reinterpret_cast<char*>(getMData()) + i; } 106 getPart(size_t iStart,size_t inSize)107 StdBuf getPart(size_t iStart, size_t inSize) const 108 { 109 assert(iStart + inSize <= iSize); 110 return StdBuf(getPtr(iStart), inSize); 111 } 112 113 // *** Setters 114 115 // * Direct setters 116 117 // Reference given data Ref(const void * pnData,size_t inSize)118 void Ref(const void *pnData, size_t inSize) 119 { 120 Clear(); 121 fRef = true; pData = pnData; iSize = inSize; 122 } 123 // Take over data (hold it) Take(void * pnData,size_t inSize)124 void Take(void *pnData, size_t inSize) 125 { 126 Clear(); 127 if (pnData) 128 { 129 fRef = false; pMData = pnData; iSize = inSize; 130 } 131 } 132 // Transfer puffer ownership to the caller GrabPointer()133 void *GrabPointer() 134 { 135 if (isNull()) return nullptr; 136 // Do not give out a buffer which someone else will free 137 if (fRef) Copy(); 138 void *pMData = getMData(); 139 pData = pMData; fRef = true; 140 return pMData; 141 } 142 143 // * Buffer data operations 144 145 // Create new buffer with given size New(size_t inSize)146 void New(size_t inSize) 147 { 148 Clear(); 149 pMData = malloc(iSize = inSize); 150 fRef = false; 151 } 152 // Write data into the buffer 153 void Write(const void *pnData, size_t inSize, size_t iAt = 0) 154 { 155 assert(iAt + inSize <= iSize); 156 if (pnData && inSize) std::memcpy(getMPtr(iAt), pnData, inSize); 157 } 158 // Move data around inside the buffer (checks overlap) 159 void Move(size_t iFrom, size_t inSize, size_t iTo = 0) 160 { 161 assert(iFrom + inSize <= iSize); assert(iTo + inSize <= iSize); 162 std::memmove(getMPtr(iTo), getPtr(iFrom), inSize); 163 } 164 // Compare to memory 165 int Compare(const void *pCData, size_t iCSize, size_t iAt = 0) const 166 { 167 assert(iAt + iCSize <= getSize()); 168 return std::memcmp(getPtr(iAt), pCData, iCSize); 169 } 170 // Grow the buffer Grow(size_t iGrow)171 void Grow(size_t iGrow) 172 { 173 // Grow dereferences 174 if (fRef) { Copy(iSize + iGrow); return; } 175 if (!iGrow) return; 176 // Realloc 177 pMData = realloc(pMData, iSize += iGrow); 178 } 179 // Shrink the buffer Shrink(size_t iShrink)180 void Shrink(size_t iShrink) 181 { 182 assert(iSize >= iShrink); 183 // Shrink dereferences 184 if (fRef) { Copy(iSize - iShrink); return; } 185 if (!iShrink) return; 186 // Realloc 187 pMData = realloc(pMData, iSize -= iShrink); 188 } 189 // Clear buffer Clear()190 void Clear() 191 { 192 if (!fRef) free(pMData); 193 pMData = nullptr; fRef = true; iSize = 0; 194 } 195 // Free buffer that had been grabbed DeletePointer(void * data)196 static void DeletePointer(void *data) 197 { 198 free(data); 199 } 200 201 // * Composed actions 202 203 // Set buffer size (dereferences) SetSize(size_t inSize)204 void SetSize(size_t inSize) 205 { 206 if (inSize > iSize) 207 Grow(inSize - iSize); 208 else 209 Shrink(iSize - inSize); 210 } 211 212 // Write buffer contents into the buffer 213 void Write(const StdBuf &Buf2, size_t iAt = 0) 214 { 215 Write(Buf2.getData(), Buf2.getSize(), iAt); 216 } 217 218 // Compare (a part of) this buffer's contents to another's 219 int Compare(const StdBuf &Buf2, size_t iAt = 0) const 220 { 221 return Compare(Buf2.getData(), Buf2.getSize(), iAt); 222 } 223 224 // Create a copy of the data (dereferences, obviously) Copy(size_t inSize)225 void Copy(size_t inSize) 226 { 227 if (isNull() && !inSize) return; 228 const void *pOldData = getData(); 229 size_t iOldSize = iSize; 230 New(inSize); 231 Write(pOldData, std::min(iOldSize, inSize)); 232 } Copy()233 void Copy() 234 { 235 Copy(iSize); 236 } 237 // Copy data from address Copy(const void * pnData,size_t inSize)238 void Copy(const void *pnData, size_t inSize) 239 { 240 Ref(pnData, inSize); Copy(); 241 } 242 // Copy from another buffer Copy(const StdBuf & Buf2)243 void Copy(const StdBuf &Buf2) 244 { 245 Copy(Buf2.getData(), Buf2.getSize()); 246 } 247 // Create a copy and return it Duplicate()248 StdBuf Duplicate() const 249 { 250 StdBuf Buf; Buf.Copy(*this); return Buf; 251 } 252 253 // Append data from address Append(const void * pnData,size_t inSize)254 void Append(const void *pnData, size_t inSize) 255 { 256 Grow(inSize); 257 Write(pnData, inSize, iSize - inSize); 258 } 259 // Append data from another buffer Append(const StdBuf & Buf2)260 void Append(const StdBuf &Buf2) 261 { 262 Append(Buf2.getData(), Buf2.getSize()); 263 } 264 265 // Reference another buffer's contents Ref(const StdBuf & Buf2)266 void Ref(const StdBuf &Buf2) 267 { 268 Ref(Buf2.getData(), Buf2.getSize()); 269 } 270 // Create a reference to this buffer's contents getRef()271 StdBuf getRef() const 272 { 273 return StdBuf(getData(), getSize()); 274 } 275 // take over another buffer's contents Take(StdBuf & Buf2)276 void Take(StdBuf & Buf2) 277 { 278 Take(Buf2.GrabPointer(), Buf2.getSize()); 279 } Take(StdBuf && Buf2)280 void Take(StdBuf &&Buf2) 281 { 282 Take(Buf2.GrabPointer(), Buf2.getSize()); 283 } 284 285 // * File support 286 bool LoadFromFile(const char *szFile); 287 bool SaveToFile(const char *szFile) const; 288 289 // *** Operators 290 291 // Null check 292 bool operator ! () const { return isNull(); } 293 294 // Appending 295 StdBuf operator += (const StdBuf &Buf2) 296 { 297 Append(Buf2); 298 return *this; 299 } 300 StdBuf operator + (const StdBuf &Buf2) const 301 { 302 StdBuf Buf(getRef()); 303 Buf.Append(Buf2); 304 return Buf; 305 } 306 307 // Compare 308 bool operator == (const StdBuf &Buf2) const 309 { 310 return getSize() == Buf2.getSize() && !Compare(Buf2); 311 } 312 bool operator != (const StdBuf &Buf2) const { return ! operator == (Buf2); } 313 314 // Set (as constructor: take if possible) 315 StdBuf &operator = (StdBuf &&Buf2) 316 { 317 if (Buf2.isRef()) Ref(Buf2); else Take(std::move(Buf2)); 318 return *this; 319 } 320 321 // build a simple hash GetHash()322 int GetHash() const 323 { 324 if (isNull()) return 0; 325 return crc32(0, reinterpret_cast<const Bytef *>(getData()), getSize()); 326 } 327 328 // *** Compiling 329 330 void CompileFunc(class StdCompiler *pComp, int iType = 0); 331 332 }; 333 334 // Cast Hide Helpers - MSVC doesn't allow this as member template 335 template <class elem_t> 336 const elem_t *getBufPtr(const StdBuf &Buf, size_t iPos = 0) 337 { 338 // assert(iPos + sizeof(elem_t) <= Buf.getSize()); 339 const void *pPos = reinterpret_cast<const char *>(Buf.getData()) + iPos; 340 return reinterpret_cast<const elem_t *>(pPos); 341 } 342 template <class elem_t> 343 elem_t *getMBufPtr(StdBuf &Buf, size_t iPos = 0) 344 { 345 // assert(iPos + sizeof(elem_t) <= Buf.getSize()); 346 void *pPos = reinterpret_cast<char *>(Buf.getMData()) + iPos; 347 return reinterpret_cast<elem_t *>(pPos); 348 } 349 350 // Copy-Buffer - Just copies data in the copy constructor. 351 class StdCopyBuf : public StdBuf 352 { 353 public: 354 355 StdCopyBuf() = default; 356 357 // Set by buffer. Copies data by default. 358 StdCopyBuf(const StdBuf &Buf2, bool fCopy = true) 359 : StdBuf(Buf2.getRef(), fCopy) 360 { } 361 362 // Set by buffer. Copies data by default. 363 StdCopyBuf(const StdCopyBuf &Buf2, bool fCopy = true) 364 : StdBuf(Buf2.getRef(), fCopy) 365 { } StdCopyBuf(StdBuf & Buf2)366 StdCopyBuf(StdBuf & Buf2) noexcept 367 : StdBuf(std::move(Buf2)) 368 { } StdCopyBuf(StdCopyBuf && Buf2)369 StdCopyBuf(StdCopyBuf &&Buf2) noexcept 370 : StdBuf(std::move(Buf2)) 371 { } 372 373 // Set by constant data. Copies data by default. 374 StdCopyBuf(const void *pData, size_t iSize, bool fCopy = true) StdBuf(pData,iSize,fCopy)375 : StdBuf(pData, iSize, fCopy) 376 { } 377 378 StdCopyBuf &operator = (const StdBuf &Buf2) { Copy(Buf2); return *this; } 379 StdCopyBuf &operator = (const StdCopyBuf &Buf2) { Copy(Buf2); return *this; } 380 381 }; 382 383 // Stringbuffer (operates on null-terminated character buffers) 384 class StdStrBuf : protected StdBuf 385 { 386 public: 387 388 // *** Construction 389 390 StdStrBuf() = default; 391 392 // See StdBuf::StdBuf. Will take data if possible. 393 // The static_cast is necessary to pass a rvalue reference to 394 // the StdBuf constructor. Without it, the const lvalue 395 // StdBuf constructor will be used, which will ref the contents 396 // instead of moving them. 397 StdStrBuf(StdStrBuf & Buf2, bool fCopy = false) 398 // : StdBuf(static_cast<StdStrBuf &>(Buf2), fCopy) StdBuf(Buf2,fCopy)399 : StdBuf(Buf2, fCopy) 400 { } 401 402 // This constructor is important, because the compiler will create one 403 // otherwise, despite having two other constructors to choose from 404 StdStrBuf(const StdStrBuf & Buf2, bool fCopy = true) StdBuf(Buf2,fCopy)405 : StdBuf(Buf2, fCopy) 406 { } StdStrBuf(StdStrBuf && Buf2)407 StdStrBuf(StdStrBuf && Buf2) noexcept 408 : StdBuf(std::move(Buf2)) 409 { } 410 411 // Set by constant data. References data by default, copies if specified. 412 explicit StdStrBuf(const char *pData, bool fCopy = false) 413 : StdBuf(pData, pData ? strlen(pData) + 1 : 0, fCopy) 414 { } 415 416 #ifdef _WIN32 417 explicit StdStrBuf(const wchar_t * utf16); 418 struct wchar_t_holder { 419 wchar_t * p; wchar_t_holderwchar_t_holder420 wchar_t_holder(wchar_t * p): p(p) { } 421 wchar_t_holder(const wchar_t_holder &); ~wchar_t_holderwchar_t_holder422 ~wchar_t_holder() { delete[] p; } 423 operator wchar_t * () { return p; } 424 }; 425 wchar_t_holder GetWideChar() const; 426 StdBuf GetWideCharBuf(); 427 #endif 428 429 // As previous constructor, but set length manually. StdStrBuf(const char * pData,long int iLength)430 StdStrBuf(const char *pData, long int iLength) 431 : StdBuf(pData, pData ? iLength + 1 : 0, false) 432 { } 433 StdStrBuf(const char *pData, size_t iLength, bool fCopy = false) 434 : StdBuf(pData, pData ? iLength + 1 : 0, fCopy) 435 { } 436 437 public: 438 439 // *** Getters 440 isNull()441 bool isNull() const { return StdBuf::isNull(); } getData()442 const char *getData() const { return getBufPtr<char>(*this); } getMData()443 char *getMData() { return getMBufPtr<char>(*this); } getSize()444 size_t getSize() const { return StdBuf::getSize(); } getLength()445 size_t getLength() const { return getSize() ? getSize() - 1 : 0; } isRef()446 bool isRef() const { return StdBuf::isRef(); } 447 getPtr(size_t i)448 const char *getPtr(size_t i) const { return getBufPtr<char>(*this, i); } getMPtr(size_t i)449 char *getMPtr(size_t i) { return getMBufPtr<char>(*this, i); } 450 451 // For convenience. Note that writing can't be allowed. 452 char operator [] (size_t i) const { return *getPtr(i); } 453 454 // Analogous to StdBuf Ref(const char * pnData)455 void Ref(const char *pnData) { StdBuf::Ref(pnData, pnData ? std::strlen(pnData) + 1 : 0); } Ref(const char * pnData,size_t iLength)456 void Ref(const char *pnData, size_t iLength) { assert((!pnData && !iLength) || std::strlen(pnData) == iLength); StdBuf::Ref(pnData, iLength + 1); } Take(char * pnData)457 void Take(char *pnData) { StdBuf::Take(pnData, pnData ? std::strlen(pnData) + 1 : 0); } Take(char * pnData,size_t iLength)458 void Take(char *pnData, size_t iLength) { assert((!pnData && !iLength) || std::strlen(pnData) == iLength); StdBuf::Take(pnData, iLength + 1); } GrabPointer()459 char *GrabPointer() { return reinterpret_cast<char *>(StdBuf::GrabPointer()); } 460 Ref(const StdStrBuf & Buf2)461 void Ref(const StdStrBuf &Buf2) { StdBuf::Ref(Buf2.getData(), Buf2.getSize()); } getRef()462 StdStrBuf getRef() const { return StdStrBuf(getData(), getLength()); } Take(StdStrBuf & Buf2)463 void Take(StdStrBuf & Buf2) { StdBuf::Take(Buf2); } Take(StdStrBuf && Buf2)464 void Take(StdStrBuf &&Buf2) { StdBuf::Take(std::move(Buf2)); } 465 Clear()466 void Clear() { StdBuf::Clear(); } Copy()467 void Copy() { StdBuf::Copy(); } Copy(const char * pnData)468 void Copy(const char *pnData) { StdBuf::Copy(pnData, pnData ? std::strlen(pnData) + 1 : 0); } Copy(const StdStrBuf & Buf2)469 void Copy(const StdStrBuf &Buf2) { StdBuf::Copy(Buf2); } Duplicate()470 StdStrBuf Duplicate() const { StdStrBuf Buf; Buf.Copy(*this); return Buf; } 471 void Move(size_t iFrom, size_t inSize, size_t iTo = 0) { StdBuf::Move(iFrom, inSize, iTo); } 472 473 // Byte-wise compare (will compare this string from iAt to the full string in Buf2) 474 int Compare(const StdStrBuf &Buf2, size_t iAt = 0) const 475 { 476 assert(iAt <= getLength()); 477 const int result = StdBuf::Compare(Buf2.getData(), std::min(getLength() - iAt, Buf2.getLength()), iAt); 478 if (result) return result; 479 480 if (getLength() < Buf2.getLength() + iAt) return -1; 481 else if (getLength() > Buf2.getLength() + iAt) return 1; 482 return 0; 483 } 484 int Compare_(const char *pCData, size_t iAt = 0) const 485 { 486 StdStrBuf str(pCData); // GCC needs this, for some obscure reason 487 return Compare(str, iAt); 488 } BeginsWith(const char * beginning)489 bool BeginsWith(const char *beginning) const 490 { 491 // Return whether string starts with beginning 492 return strncmp((const char 493 *)pData, beginning, strlen(beginning)) == 0; 494 } 495 496 // Grows the string to contain the specified number more/less characters. 497 // Note: Will set the terminator, but won't initialize - use Append* instead. Grow(size_t iGrow)498 void Grow(size_t iGrow) 499 { 500 StdBuf::Grow(getSize() ? iGrow : iGrow + 1); 501 *getMPtr(getLength()) = '\0'; 502 } Shrink(size_t iShrink)503 void Shrink(size_t iShrink) 504 { 505 assert(iShrink <= getLength()); 506 StdBuf::Shrink(iShrink); 507 *getMPtr(getLength()) = '\0'; 508 } SetLength(size_t iLength)509 void SetLength(size_t iLength) 510 { 511 if (iLength == getLength() && !isNull()) return; 512 if (iLength >= getLength()) 513 Grow(iLength - getLength()); 514 else 515 Shrink(getLength() - iLength); 516 } 517 518 // Append string Append(const char * pnData,size_t iChars)519 void Append(const char *pnData, size_t iChars) 520 { 521 Grow(iChars); 522 Write(pnData, iChars, iSize - iChars - 1); 523 } Append(const char * pnData)524 void Append(const char *pnData) 525 { 526 Append(pnData, std::strlen(pnData)); 527 } Append(const StdStrBuf & Buf2)528 void Append(const StdStrBuf &Buf2) 529 { 530 Append(Buf2.getData(), Buf2.getLength()); 531 } 532 533 // Copy string Copy(const char * pnData,size_t iChars)534 void Copy(const char *pnData, size_t iChars) 535 { 536 Clear(); 537 Append(pnData, iChars); 538 } 539 540 // * File support 541 bool LoadFromFile(const char *szFile); 542 bool SaveToFile(const char *szFile) const; 543 544 // * Operators 545 546 bool operator ! () const { return isNull(); } 547 548 StdStrBuf &operator += (const StdStrBuf &Buf2) { Append(Buf2); return *this; } 549 StdStrBuf &operator += (const char *szString) { Append(szString); return *this; } 550 StdStrBuf operator + (const StdStrBuf &Buf2) const { StdStrBuf Buf = getRef(); Buf.Append(Buf2); return Buf; } 551 StdStrBuf operator + (const char *szString) const { StdStrBuf Buf = getRef(); Buf.Append(szString); return Buf; } 552 StdStrBuf operator + (char c) const { StdStrBuf Buf = getRef(); Buf.AppendChar(c); return Buf; } 553 554 bool operator == (const StdStrBuf &Buf2) const 555 { 556 return getLength() == Buf2.getLength() && !Compare(Buf2); 557 } 558 bool operator != (const StdStrBuf &Buf2) const { return !operator == (Buf2); } 559 560 bool operator == (const char *szString) const { return StdStrBuf(szString) == *this; } 561 bool operator != (const char *szString) const { return ! operator == (szString); } 562 563 // Note this references the data. 564 StdStrBuf &operator = (const StdStrBuf &Buf2) { Ref(Buf2); return *this; } 565 StdStrBuf &operator = (const char *szString) { Ref(szString); return *this; } 566 567 // conversion to "bool" 568 operator const void *() const { return getData(); } 569 570 // less-than operation for map 571 inline bool operator <(const StdStrBuf &v2) const 572 { 573 size_t iLen = getLength(), iLen2 = v2.getLength(); 574 if (iLen == iLen2) 575 return iLen ? (std::strcmp(getData(), v2.getData())<0) : false; 576 else 577 return iLen < iLen2; 578 } 579 580 // * String specific 581 AppendChars(char cChar,size_t iCnt)582 void AppendChars(char cChar, size_t iCnt) 583 { 584 Grow(iCnt); 585 for (size_t i = getLength() - iCnt; i < getLength(); i++) 586 *getMPtr(i) = cChar; 587 } AppendChar(char cChar)588 void AppendChar(char cChar) 589 { 590 AppendChars(cChar, 1); 591 } 592 void AppendCharacter(uint32_t unicodechar); 593 void AppendBackslash(); InsertChar(char cChar,size_t insert_before)594 void InsertChar(char cChar, size_t insert_before) 595 { 596 assert(insert_before <= getLength()); 597 Grow(1); 598 for (size_t i = getLength()-1; i > insert_before; --i) 599 *getMPtr(i) = *getPtr(i-1); 600 *getMPtr(insert_before) = cChar; 601 } 602 603 // Append data until given character (or string end) occurs. AppendUntil(const char * szString,char cUntil)604 void AppendUntil(const char *szString, char cUntil) 605 { 606 const char *pPos = std::strchr(szString, cUntil); 607 if (pPos) 608 Append(szString, pPos - szString); 609 else 610 Append(szString); 611 } 612 // See above CopyUntil(const char * szString,char cUntil)613 void CopyUntil(const char *szString, char cUntil) 614 { 615 Clear(); 616 AppendUntil(szString, cUntil); 617 } 618 // cut end after given char into another string. Return whether char was found at all SplitAtChar(char cSplit,StdStrBuf * psSplit)619 bool SplitAtChar(char cSplit, StdStrBuf *psSplit) 620 { 621 if (!getData()) return false; 622 const char *pPos = std::strchr(getData(), cSplit); 623 if (!pPos) return false; 624 size_t iPos = pPos - getData(); 625 if (psSplit) psSplit->Take(copyPart(iPos + 1, getLength() - iPos - 1)); 626 Shrink(getLength() - iPos); 627 return true; 628 } 629 630 void Format(const char *szFmt, ...) GNUC_FORMAT_ATTRIBUTE_O; 631 void FormatV(const char *szFmt, va_list args); 632 void AppendFormat(const char *szFmt, ...) GNUC_FORMAT_ATTRIBUTE_O; 633 void AppendFormatV(const char *szFmt, va_list args); 634 copyPart(size_t iStart,size_t inSize)635 StdStrBuf copyPart(size_t iStart, size_t inSize) const 636 { 637 assert(iStart + inSize <= iSize); 638 if (!inSize) return StdStrBuf(); 639 StdStrBuf sResult; 640 sResult.Copy(getPtr(iStart), inSize); 641 return sResult; 642 } 643 644 // replace all occurences of one string with another. Return number of replacements. 645 int Replace(const char *szOld, const char *szNew, size_t iStartSearch=0); 646 int ReplaceChar(char cOld, char cNew); 647 648 // replace the trailing part of a string with something else 649 void ReplaceEnd(size_t iPos, const char *szNewEnd); 650 651 // get an indexed section from the string like Section1;Section2;Section3 652 bool GetSection(size_t idx, StdStrBuf *psOutSection, char cSeparator=';') const; 653 654 // Checks whether the content is valid UTF-8, and if not, convert it from windows-1252 to UTF-8 and return true. 655 bool EnsureUnicode(); 656 657 // convert to lower case 658 void ToLowerCase(); 659 660 // check if a string consists only of the given chars 661 bool ValidateChars(const char *szInitialChars, const char *szMidChars); 662 663 // build a simple hash GetHash()664 int GetHash() const 665 { 666 return StdBuf::GetHash(); 667 } 668 EscapeString()669 void EscapeString() 670 { 671 Replace(R"(\)", R"(\\)"); 672 Replace(R"(")", R"(\")"); 673 } 674 675 bool TrimSpaces(); // kill spaces at beginning and end. Return if changed. 676 677 // * Compiling 678 679 void CompileFunc(class StdCompiler *pComp, int iRawType = 0); 680 681 }; 682 683 // Copy-Stringbuffer - Just copies data in the copy constructor. 684 class StdCopyStrBuf : public StdStrBuf 685 { 686 public: 687 688 StdCopyStrBuf() = default; 689 690 explicit StdCopyStrBuf(const StdStrBuf &Buf2, bool fCopy = true) 691 : StdStrBuf(Buf2.getRef(), fCopy) 692 { } 693 694 StdCopyStrBuf(const StdCopyStrBuf &Buf2, bool fCopy = true) 695 : StdStrBuf(Buf2.getRef(), fCopy) 696 { } 697 StdCopyStrBuf(StdStrBuf && Buf2) noexcept 698 : StdStrBuf(std::move(Buf2)) 699 { } 700 StdCopyStrBuf(StdCopyStrBuf && Buf2) noexcept 701 : StdStrBuf(std::move(Buf2)) 702 { } 703 704 // Set by constant data. Copies data if desired. 705 explicit StdCopyStrBuf(const char *pData, bool fCopy = true) 706 : StdStrBuf(pData, fCopy) 707 { } 708 709 #ifdef _WIN32 710 explicit StdCopyStrBuf(const wchar_t * utf16): StdStrBuf(utf16) {} 711 #endif 712 713 StdCopyStrBuf(const std::string &s) noexcept 714 : StdStrBuf(s.c_str(), s.size(), true) 715 { } 716 717 StdCopyStrBuf &operator = (const StdStrBuf &Buf2) { Copy(Buf2); return *this; } 718 StdCopyStrBuf &operator = (const StdCopyStrBuf &Buf2) { Copy(Buf2); return *this; } 719 StdCopyStrBuf &operator = (const char *szString) { Copy(szString); return *this; } 720 StdCopyStrBuf &operator = (const std::string &s) { Copy(s.c_str(), s.size()); return *this; } 721 722 operator std::string() const 723 { 724 return std::string(getData(), getLength()); 725 } 726 }; 727 728 // Wrappers 729 extern StdStrBuf FormatString(const char *szFmt, ...) GNUC_FORMAT_ATTRIBUTE; 730 extern StdStrBuf FormatStringV(const char *szFmt, va_list args); 731 732 #ifdef _WIN32 733 // Converts a wide char string to UTF-8 std::string 734 std::string WStrToString(wchar_t *s); 735 #endif 736 737 #endif 738