Rename a pipe method, add docs
[carla.git] / source / utils / CarlaString.hpp
blob1959d98301ce87dd74fe83cef81b006066e4c028
1 /*
2 * Carla String
3 * Copyright (C) 2013-2023 Filipe Coelho <falktx@falktx.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
18 #ifndef CARLA_STRING_HPP_INCLUDED
19 #define CARLA_STRING_HPP_INCLUDED
21 #include "CarlaMathUtils.hpp"
22 #include "CarlaScopeUtils.hpp"
24 #include <algorithm>
26 // -----------------------------------------------------------------------
27 // CarlaString class
29 class CARLA_API CarlaString
31 public:
32 // -------------------------------------------------------------------
33 // constructors (no explicit conversions allowed)
36 * Empty string.
38 explicit CarlaString() noexcept
39 : fBuffer(_null()),
40 fBufferLen(0),
41 fBufferAlloc(false) {}
44 * Simple character.
46 explicit CarlaString(const char c) noexcept
47 : fBuffer(_null()),
48 fBufferLen(0),
49 fBufferAlloc(false)
51 char ch[2];
52 ch[0] = c;
53 ch[1] = '\0';
55 _dup(ch);
59 * Simple char string.
61 explicit CarlaString(char* const strBuf, const bool reallocData = true) noexcept
62 : fBuffer(_null()),
63 fBufferLen(0),
64 fBufferAlloc(false)
66 if (reallocData || strBuf == nullptr)
68 _dup(strBuf);
70 else
72 fBuffer = strBuf;
73 fBufferLen = std::strlen(strBuf);
74 fBufferAlloc = true;
79 * Simple const char string.
81 explicit CarlaString(const char* const strBuf) noexcept
82 : fBuffer(_null()),
83 fBufferLen(0),
84 fBufferAlloc(false)
86 _dup(strBuf);
90 * Integer.
92 explicit CarlaString(const int value) noexcept
93 : fBuffer(_null()),
94 fBufferLen(0),
95 fBufferAlloc(false)
97 char strBuf[0xff+1];
98 std::snprintf(strBuf, 0xff, "%d", value);
99 strBuf[0xff] = '\0';
101 _dup(strBuf);
105 * Unsigned integer, possibly in hexadecimal.
107 explicit CarlaString(const unsigned int value, const bool hexadecimal = false) noexcept
108 : fBuffer(_null()),
109 fBufferLen(0),
110 fBufferAlloc(false)
112 char strBuf[0xff+1];
113 std::snprintf(strBuf, 0xff, hexadecimal ? "0x%x" : "%u", value);
114 strBuf[0xff] = '\0';
116 _dup(strBuf);
120 * Long integer.
122 explicit CarlaString(const long value) noexcept
123 : fBuffer(_null()),
124 fBufferLen(0),
125 fBufferAlloc(false)
127 char strBuf[0xff+1];
128 std::snprintf(strBuf, 0xff, "%ld", value);
129 strBuf[0xff] = '\0';
131 _dup(strBuf);
135 * Long unsigned integer, possibly hexadecimal.
137 explicit CarlaString(const unsigned long value, const bool hexadecimal = false) noexcept
138 : fBuffer(_null()),
139 fBufferLen(0),
140 fBufferAlloc(false)
142 char strBuf[0xff+1];
143 std::snprintf(strBuf, 0xff, hexadecimal ? "0x%lx" : "%lu", value);
144 strBuf[0xff] = '\0';
146 _dup(strBuf);
150 * Long long integer.
152 explicit CarlaString(const long long value) noexcept
153 : fBuffer(_null()),
154 fBufferLen(0),
155 fBufferAlloc(false)
157 char strBuf[0xff+1];
158 std::snprintf(strBuf, 0xff, "%lld", value);
159 strBuf[0xff] = '\0';
161 _dup(strBuf);
165 * Long long unsigned integer, possibly hexadecimal.
167 explicit CarlaString(const unsigned long long value, const bool hexadecimal = false) noexcept
168 : fBuffer(_null()),
169 fBufferLen(0),
170 fBufferAlloc(false)
172 char strBuf[0xff+1];
173 std::snprintf(strBuf, 0xff, hexadecimal ? "0x%llx" : "%llu", value);
174 strBuf[0xff] = '\0';
176 _dup(strBuf);
180 * Single-precision floating point number.
182 explicit CarlaString(const float value) noexcept
183 : fBuffer(_null()),
184 fBufferLen(0),
185 fBufferAlloc(false)
187 char strBuf[0xff+1];
190 const CarlaScopedLocale csl;
191 std::snprintf(strBuf, 0xff, "%.12g", static_cast<double>(value));
194 strBuf[0xff] = '\0';
196 _dup(strBuf);
200 * Double-precision floating point number.
202 explicit CarlaString(const double value) noexcept
203 : fBuffer(_null()),
204 fBufferLen(0),
205 fBufferAlloc(false)
207 char strBuf[0xff+1];
210 const CarlaScopedLocale csl;
211 std::snprintf(strBuf, 0xff, "%.24g", value);
214 strBuf[0xff] = '\0';
216 _dup(strBuf);
219 // -------------------------------------------------------------------
220 // non-explicit constructor
223 * Create string from another string.
225 CarlaString(const CarlaString& str) noexcept
226 : fBuffer(_null()),
227 fBufferLen(0),
228 fBufferAlloc(false)
230 _dup(str.fBuffer);
233 // -------------------------------------------------------------------
234 // destructor
237 * Destructor.
239 ~CarlaString() noexcept
241 CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr,);
243 if (fBufferAlloc)
244 std::free(fBuffer);
246 fBuffer = nullptr;
247 fBufferLen = 0;
248 fBufferAlloc = false;
251 // -------------------------------------------------------------------
252 // public methods
255 * Get length of the string.
257 std::size_t length() const noexcept
259 return fBufferLen;
263 * Check if the string is empty.
265 bool isEmpty() const noexcept
267 return (fBufferLen == 0);
271 * Check if the string is not empty.
273 bool isNotEmpty() const noexcept
275 return (fBufferLen != 0);
279 * Check if the string contains a specific character, case-sensitive.
281 bool contains(const char c) const noexcept
283 for (std::size_t i=0; i<fBufferLen; ++i)
285 if (fBuffer[i] == c)
286 return true;
289 return false;
293 * Check if the string contains another string, optionally ignoring case.
295 bool contains(const char* const strBuf, const bool ignoreCase = false) const noexcept
297 CARLA_SAFE_ASSERT_RETURN(strBuf != nullptr, false);
299 if (ignoreCase)
301 #ifdef __USE_GNU
302 return (strcasestr(fBuffer, strBuf) != nullptr);
303 #else
304 CarlaString tmp1(fBuffer), tmp2(strBuf);
306 // memory allocation failed or empty string(s)
307 if (tmp1.fBuffer == _null() || tmp2.fBuffer == _null())
308 return false;
310 tmp1.toLower();
311 tmp2.toLower();
312 return (std::strstr(tmp1, tmp2) != nullptr);
313 #endif
316 return (std::strstr(fBuffer, strBuf) != nullptr);
320 * Check if character at 'pos' is a digit.
322 bool isDigit(const std::size_t pos) const noexcept
324 CARLA_SAFE_ASSERT_RETURN(pos < fBufferLen, false);
326 return (fBuffer[pos] >= '0' && fBuffer[pos] <= '9');
330 * Check if the string starts with the character 'c'.
332 bool startsWith(const char c) const noexcept
334 CARLA_SAFE_ASSERT_RETURN(c != '\0', false);
336 return (fBufferLen > 0 && fBuffer[0] == c);
340 * Check if the string starts with the string 'prefix'.
342 bool startsWith(const char* const prefix) const noexcept
344 CARLA_SAFE_ASSERT_RETURN(prefix != nullptr, false);
346 const std::size_t prefixLen(std::strlen(prefix));
348 if (fBufferLen < prefixLen)
349 return false;
351 return (std::strncmp(fBuffer, prefix, prefixLen) == 0);
355 * Check if the string ends with the character 'c'.
357 bool endsWith(const char c) const noexcept
359 CARLA_SAFE_ASSERT_RETURN(c != '\0', false);
361 return (fBufferLen > 0 && fBuffer[fBufferLen-1] == c);
365 * Check if the string ends with the string 'suffix'.
367 bool endsWith(const char* const suffix) const noexcept
369 CARLA_SAFE_ASSERT_RETURN(suffix != nullptr, false);
371 const std::size_t suffixLen(std::strlen(suffix));
373 if (fBufferLen < suffixLen)
374 return false;
376 return (std::strncmp(fBuffer + (fBufferLen-suffixLen), suffix, suffixLen) == 0);
380 * Find the first occurrence of character 'c' in the string.
381 * Returns "length()" if the character is not found.
383 std::size_t find(const char c, bool* const found = nullptr) const noexcept
385 if (fBufferLen == 0 || c == '\0')
387 if (found != nullptr)
388 *found = false;
389 return fBufferLen;
392 for (std::size_t i=0; i < fBufferLen; ++i)
394 if (fBuffer[i] == c)
396 if (found != nullptr)
397 *found = true;
398 return i;
402 if (found != nullptr)
403 *found = false;
404 return fBufferLen;
408 * Find the first occurrence of string 'strBuf' in the string.
409 * Returns "length()" if the string is not found.
411 std::size_t find(const char* const strBuf, bool* const found = nullptr) const noexcept
413 if (fBufferLen == 0 || strBuf == nullptr || strBuf[0] == '\0')
415 if (found != nullptr)
416 *found = false;
417 return fBufferLen;
420 if (char* const subStrBuf = std::strstr(fBuffer, strBuf))
422 const ssize_t ret = subStrBuf - fBuffer;
424 if (ret < 0)
426 // should never happen!
427 carla_safe_assert_int("ret >= 0", __FILE__, __LINE__, int(ret));
429 if (found != nullptr)
430 *found = false;
431 return fBufferLen;
434 if (found != nullptr)
435 *found = true;
436 return static_cast<std::size_t>(ret);
439 if (found != nullptr)
440 *found = false;
441 return fBufferLen;
445 * Find the last occurrence of character 'c' in the string.
446 * Returns "length()" if the character is not found.
448 std::size_t rfind(const char c, bool* const found = nullptr) const noexcept
450 if (fBufferLen == 0 || c == '\0')
452 if (found != nullptr)
453 *found = false;
454 return fBufferLen;
457 for (std::size_t i=fBufferLen; i > 0; --i)
459 if (fBuffer[i-1] == c)
461 if (found != nullptr)
462 *found = true;
463 return i-1;
467 if (found != nullptr)
468 *found = false;
469 return fBufferLen;
473 * Find the last occurrence of string 'strBuf' in the string.
474 * Returns "length()" if the string is not found.
476 std::size_t rfind(const char* const strBuf, bool* const found = nullptr) const noexcept
478 if (found != nullptr)
479 *found = false;
481 if (fBufferLen == 0 || strBuf == nullptr || strBuf[0] == '\0')
482 return fBufferLen;
484 const std::size_t strBufLen(std::strlen(strBuf));
486 std::size_t ret = fBufferLen;
487 const char* tmpBuf = fBuffer;
489 for (std::size_t i=0; i < fBufferLen; ++i)
491 if (std::strstr(tmpBuf+1, strBuf) == nullptr && std::strncmp(tmpBuf, strBuf, strBufLen) == 0)
493 if (found != nullptr)
494 *found = true;
495 break;
498 --ret;
499 ++tmpBuf;
502 return fBufferLen-ret;
506 * Clear the string.
508 void clear() noexcept
510 truncate(0);
514 * Replace all occurrences of character 'before' with character 'after'.
516 CarlaString& replace(const char before, const char after) noexcept
518 CARLA_SAFE_ASSERT_RETURN(before != '\0' && after != '\0', *this);
520 for (std::size_t i=0; i < fBufferLen; ++i)
522 if (fBuffer[i] == before)
523 fBuffer[i] = after;
526 return *this;
530 * Truncate the string to size 'n'.
532 CarlaString& truncate(const std::size_t n) noexcept
534 if (n >= fBufferLen)
535 return *this;
537 fBuffer[n] = '\0';
538 fBufferLen = n;
540 return *this;
544 * Convert all non-basic characters to '_'.
546 CarlaString& toBasic() noexcept
548 for (std::size_t i=0; i < fBufferLen; ++i)
550 if (fBuffer[i] >= '0' && fBuffer[i] <= '9')
551 continue;
552 if (fBuffer[i] >= 'A' && fBuffer[i] <= 'Z')
553 continue;
554 if (fBuffer[i] >= 'a' && fBuffer[i] <= 'z')
555 continue;
556 if (fBuffer[i] == '_')
557 continue;
559 fBuffer[i] = '_';
562 return *this;
566 * Convert all ascii characters to lowercase.
568 CarlaString& toLower() noexcept
570 static const char kCharDiff('a' - 'A');
572 for (std::size_t i=0; i < fBufferLen; ++i)
574 if (fBuffer[i] >= 'A' && fBuffer[i] <= 'Z')
575 fBuffer[i] = static_cast<char>(fBuffer[i] + kCharDiff);
578 return *this;
582 * Convert all ascii characters to uppercase.
584 CarlaString& toUpper() noexcept
586 static const char kCharDiff('a' - 'A');
588 for (std::size_t i=0; i < fBufferLen; ++i)
590 if (fBuffer[i] >= 'a' && fBuffer[i] <= 'z')
591 fBuffer[i] = static_cast<char>(fBuffer[i] - kCharDiff);
594 return *this;
598 * Direct access to the string buffer (read-only).
600 const char* buffer() const noexcept
602 return fBuffer;
606 * Return a duplicate string buffer.
607 * May throw.
609 const char* dup() const
611 return carla_strdup(fBuffer);
615 * Return a duplicate string buffer or null.
617 const char* dupSafe() const noexcept
619 return carla_strdup_safe(fBuffer);
623 * Release the buffer pointer while clearing this string.
624 * This allows to keep a pointer to the buffer after this object is deleted.
626 char* releaseBufferPointer() noexcept
628 char* ret = fBufferLen > 0 ? fBuffer : nullptr;
629 fBuffer = _null();
630 fBufferLen = 0;
631 fBufferAlloc = false;
632 return ret;
635 // -------------------------------------------------------------------
636 // base64 stuff, based on http://www.adp-gmbh.ch/cpp/common/base64.html
637 // Copyright (C) 2004-2008 René Nyffenegger
639 static CarlaString asBase64(const void* const data, const std::size_t dataSize)
641 static const char* const kBase64Chars =
642 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
643 "abcdefghijklmnopqrstuvwxyz"
644 "0123456789+/";
646 static constexpr const std::size_t kTmpBufSize = 65536U;
648 const uchar* bytesToEncode((const uchar*)data);
650 uint i=0, j=0;
651 uint charArray3[3], charArray4[4];
653 char strBuf[kTmpBufSize+1];
654 strBuf[kTmpBufSize] = '\0';
655 std::size_t strBufIndex = 0;
657 CarlaString ret;
659 for (std::size_t s=0; s<dataSize; ++s)
661 charArray3[i++] = *(bytesToEncode++);
663 if (i == 3)
665 charArray4[0] = (charArray3[0] & 0xfc) >> 2;
666 charArray4[1] = ((charArray3[0] & 0x03) << 4) + ((charArray3[1] & 0xf0) >> 4);
667 charArray4[2] = ((charArray3[1] & 0x0f) << 2) + ((charArray3[2] & 0xc0) >> 6);
668 charArray4[3] = charArray3[2] & 0x3f;
670 for (i=0; i<4; ++i)
671 strBuf[strBufIndex++] = kBase64Chars[charArray4[i]];
673 if (strBufIndex >= kTmpBufSize-7)
675 strBuf[strBufIndex] = '\0';
676 strBufIndex = 0;
677 ret += strBuf;
680 i = 0;
684 if (i != 0)
686 for (j=i; j<3; ++j)
687 charArray3[j] = '\0';
689 charArray4[0] = (charArray3[0] & 0xfc) >> 2;
690 charArray4[1] = ((charArray3[0] & 0x03) << 4) + ((charArray3[1] & 0xf0) >> 4);
691 charArray4[2] = ((charArray3[1] & 0x0f) << 2) + ((charArray3[2] & 0xc0) >> 6);
692 charArray4[3] = charArray3[2] & 0x3f;
694 for (j=0; j<4 && i<3 && j<i+1; ++j)
695 strBuf[strBufIndex++] = kBase64Chars[charArray4[j]];
697 for (; i++ < 3;)
698 strBuf[strBufIndex++] = '=';
701 if (strBufIndex != 0)
703 strBuf[strBufIndex] = '\0';
704 ret += strBuf;
707 return ret;
710 // -------------------------------------------------------------------
711 // public operators
713 operator const char*() const noexcept
715 return fBuffer;
718 char operator[](const std::size_t pos) const noexcept
720 if (pos < fBufferLen)
721 return fBuffer[pos];
723 carla_safe_assert("pos < fBufferLen", __FILE__, __LINE__);
725 static char fallback;
726 fallback = '\0';
727 return fallback;
730 char& operator[](const std::size_t pos) noexcept
732 if (pos < fBufferLen)
733 return fBuffer[pos];
735 carla_safe_assert("pos < fBufferLen", __FILE__, __LINE__);
737 static char fallback;
738 fallback = '\0';
739 return fallback;
742 bool operator==(const char* const strBuf) const noexcept
744 return (strBuf != nullptr && std::strcmp(fBuffer, strBuf) == 0);
747 bool operator==(const CarlaString& str) const noexcept
749 return operator==(str.fBuffer);
752 bool operator!=(const char* const strBuf) const noexcept
754 return !operator==(strBuf);
757 bool operator!=(const CarlaString& str) const noexcept
759 return !operator==(str.fBuffer);
762 CarlaString& operator=(const char* const strBuf) noexcept
764 _dup(strBuf);
766 return *this;
769 CarlaString& operator=(const CarlaString& str) noexcept
771 _dup(str.fBuffer);
773 return *this;
776 CarlaString& operator+=(const char* const strBuf) noexcept
778 if (strBuf == nullptr || strBuf[0] == '\0')
779 return *this;
781 const std::size_t strBufLen = std::strlen(strBuf);
783 // for empty strings, we can just take the appended string as our entire data
784 if (isEmpty())
786 _dup(strBuf, strBufLen);
787 return *this;
790 // we have some data ourselves, reallocate to add the new stuff
791 char* const newBuf = (char*)realloc(fBuffer, fBufferLen + strBufLen + 1);
792 CARLA_SAFE_ASSERT_RETURN(newBuf != nullptr, *this);
794 std::memcpy(newBuf + fBufferLen, strBuf, strBufLen + 1);
796 fBuffer = newBuf;
797 fBufferLen += strBufLen;
799 return *this;
802 CarlaString& operator+=(const CarlaString& str) noexcept
804 return operator+=(str.fBuffer);
807 CarlaString operator+(const char* const strBuf) noexcept
809 if (strBuf == nullptr || strBuf[0] == '\0')
810 return *this;
811 if (isEmpty())
812 return CarlaString(strBuf);
814 const std::size_t strBufLen = std::strlen(strBuf);
815 const std::size_t newBufSize = fBufferLen + strBufLen;
816 char* const newBuf = (char*)std::malloc(newBufSize + 1);
817 CARLA_SAFE_ASSERT_RETURN(newBuf != nullptr, CarlaString());
819 std::memcpy(newBuf, fBuffer, fBufferLen);
820 std::memcpy(newBuf + fBufferLen, strBuf, strBufLen + 1);
822 return CarlaString(newBuf, false);
825 CarlaString operator+(const CarlaString& str) noexcept
827 return operator+(str.fBuffer);
830 // needed for std::map compatibility
831 bool operator<(const CarlaString& str) const noexcept
833 return std::strcmp(fBuffer, str.fBuffer) < 0;
836 // -------------------------------------------------------------------
838 private:
839 char* fBuffer; // the actual string buffer
840 std::size_t fBufferLen; // string length
841 bool fBufferAlloc; // wherever the buffer is allocated, not using _null()
844 * Static null string.
845 * Prevents allocation for new and/or empty strings.
847 static char* _null() noexcept
849 static char sNull = '\0';
850 return &sNull;
854 * Helper function.
855 * Called whenever the string needs to be allocated.
857 * Notes:
858 * - Allocates string only if 'strBuf' is not null and new string contents are different
859 * - If 'strBuf' is null, 'size' must be 0
861 void _dup(const char* const strBuf, const std::size_t size = 0) noexcept
863 if (strBuf != nullptr)
865 // don't recreate string if contents match
866 if (std::strcmp(fBuffer, strBuf) == 0)
867 return;
869 if (fBufferAlloc)
870 std::free(fBuffer);
872 fBufferLen = (size > 0) ? size : std::strlen(strBuf);
873 fBuffer = (char*)std::malloc(fBufferLen+1);
875 if (fBuffer == nullptr)
877 fBuffer = _null();
878 fBufferLen = 0;
879 fBufferAlloc = false;
880 return;
883 fBufferAlloc = true;
885 std::strcpy(fBuffer, strBuf);
886 fBuffer[fBufferLen] = '\0';
888 else
890 CARLA_SAFE_ASSERT_UINT(size == 0, static_cast<uint>(size));
892 // don't recreate null string
893 if (! fBufferAlloc)
894 return;
896 CARLA_SAFE_ASSERT(fBuffer != nullptr);
897 std::free(fBuffer);
899 fBuffer = _null();
900 fBufferLen = 0;
901 fBufferAlloc = false;
905 CARLA_PREVENT_HEAP_ALLOCATION
908 // -----------------------------------------------------------------------
910 static inline
911 CarlaString operator+(const CarlaString& strBefore, const char* const strBufAfter) noexcept
913 if (strBufAfter == nullptr || strBufAfter[0] == '\0')
914 return strBefore;
915 if (strBefore.isEmpty())
916 return CarlaString(strBufAfter);
918 const std::size_t strBeforeLen = strBefore.length();
919 const std::size_t strBufAfterLen = std::strlen(strBufAfter);
920 const std::size_t newBufSize = strBeforeLen + strBufAfterLen;
921 char* const newBuf = (char*)std::malloc(newBufSize + 1);
922 CARLA_SAFE_ASSERT_RETURN(newBuf != nullptr, CarlaString());
924 std::memcpy(newBuf, strBefore.buffer(), strBeforeLen);
925 std::memcpy(newBuf + strBeforeLen, strBufAfter, strBufAfterLen + 1);
927 return CarlaString(newBuf, false);
930 static inline
931 CarlaString operator+(const char* const strBufBefore, const CarlaString& strAfter) noexcept
933 if (strAfter.isEmpty())
934 return CarlaString(strBufBefore);
935 if (strBufBefore == nullptr || strBufBefore[0] == '\0')
936 return strAfter;
938 const std::size_t strBufBeforeLen = std::strlen(strBufBefore);
939 const std::size_t strAfterLen = strAfter.length();
940 const std::size_t newBufSize = strBufBeforeLen + strAfterLen;
941 char* const newBuf = (char*)std::malloc(newBufSize + 1);
942 CARLA_SAFE_ASSERT_RETURN(newBuf != nullptr, CarlaString());
944 std::memcpy(newBuf, strBufBefore, strBufBeforeLen);
945 std::memcpy(newBuf + strBufBeforeLen, strAfter.buffer(), strAfterLen + 1);
947 return CarlaString(newBuf, false);
950 // -----------------------------------------------------------------------
952 #endif // CARLA_STRING_HPP_INCLUDED