VST3: fetch midi mappings all at once, use it for note/sound-off
[carla.git] / source / utils / CarlaString.hpp
blobd2602380b535cf3a35f3eea06252d9a29ca1faf1
1 /*
2 * Carla String
3 * Copyright (C) 2013-2024 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 = '\0';
726 return fallback;
729 char& operator[](const std::size_t pos) noexcept
731 if (pos < fBufferLen)
732 return fBuffer[pos];
734 carla_safe_assert("pos < fBufferLen", __FILE__, __LINE__);
736 static char fallback = '\0';
737 return fallback;
740 bool operator==(const char* const strBuf) const noexcept
742 return (strBuf != nullptr && std::strcmp(fBuffer, strBuf) == 0);
745 bool operator==(const CarlaString& str) const noexcept
747 return operator==(str.fBuffer);
750 bool operator!=(const char* const strBuf) const noexcept
752 return !operator==(strBuf);
755 bool operator!=(const CarlaString& str) const noexcept
757 return !operator==(str.fBuffer);
760 CarlaString& operator=(const char* const strBuf) noexcept
762 _dup(strBuf);
764 return *this;
767 CarlaString& operator=(const CarlaString& str) noexcept
769 _dup(str.fBuffer);
771 return *this;
774 CarlaString& operator+=(const char* const strBuf) noexcept
776 if (strBuf == nullptr || strBuf[0] == '\0')
777 return *this;
779 const std::size_t strBufLen = std::strlen(strBuf);
781 // for empty strings, we can just take the appended string as our entire data
782 if (isEmpty())
784 _dup(strBuf, strBufLen);
785 return *this;
788 // we have some data ourselves, reallocate to add the new stuff
789 char* const newBuf = (char*)realloc(fBuffer, fBufferLen + strBufLen + 1);
790 CARLA_SAFE_ASSERT_RETURN(newBuf != nullptr, *this);
792 std::memcpy(newBuf + fBufferLen, strBuf, strBufLen + 1);
794 fBuffer = newBuf;
795 fBufferLen += strBufLen;
797 return *this;
800 CarlaString& operator+=(const CarlaString& str) noexcept
802 return operator+=(str.fBuffer);
805 CarlaString operator+(const char* const strBuf) noexcept
807 if (strBuf == nullptr || strBuf[0] == '\0')
808 return *this;
809 if (isEmpty())
810 return CarlaString(strBuf);
812 const std::size_t strBufLen = std::strlen(strBuf);
813 const std::size_t newBufSize = fBufferLen + strBufLen;
814 char* const newBuf = (char*)std::malloc(newBufSize + 1);
815 CARLA_SAFE_ASSERT_RETURN(newBuf != nullptr, CarlaString());
817 std::memcpy(newBuf, fBuffer, fBufferLen);
818 std::memcpy(newBuf + fBufferLen, strBuf, strBufLen + 1);
820 return CarlaString(newBuf, false);
823 CarlaString operator+(const CarlaString& str) noexcept
825 return operator+(str.fBuffer);
828 // needed for std::map compatibility
829 bool operator<(const CarlaString& str) const noexcept
831 return std::strcmp(fBuffer, str.fBuffer) < 0;
834 // -------------------------------------------------------------------
836 private:
837 char* fBuffer; // the actual string buffer
838 std::size_t fBufferLen; // string length
839 bool fBufferAlloc; // wherever the buffer is allocated, not using _null()
842 * Static null string.
843 * Prevents allocation for new and/or empty strings.
845 static char* _null() noexcept
847 static char sNull = '\0';
848 return &sNull;
852 * Helper function.
853 * Called whenever the string needs to be allocated.
855 * Notes:
856 * - Allocates string only if 'strBuf' is not null and new string contents are different
857 * - If 'strBuf' is null, 'size' must be 0
859 void _dup(const char* const strBuf, const std::size_t size = 0) noexcept
861 if (strBuf != nullptr)
863 // don't recreate string if contents match
864 if (std::strcmp(fBuffer, strBuf) == 0)
865 return;
867 if (fBufferAlloc)
868 std::free(fBuffer);
870 fBufferLen = (size > 0) ? size : std::strlen(strBuf);
871 fBuffer = (char*)std::malloc(fBufferLen+1);
873 if (fBuffer == nullptr)
875 fBuffer = _null();
876 fBufferLen = 0;
877 fBufferAlloc = false;
878 return;
881 fBufferAlloc = true;
883 std::strcpy(fBuffer, strBuf);
884 fBuffer[fBufferLen] = '\0';
886 else
888 CARLA_SAFE_ASSERT_UINT(size == 0, static_cast<uint>(size));
890 // don't recreate null string
891 if (! fBufferAlloc)
892 return;
894 CARLA_SAFE_ASSERT(fBuffer != nullptr);
895 std::free(fBuffer);
897 fBuffer = _null();
898 fBufferLen = 0;
899 fBufferAlloc = false;
903 CARLA_PREVENT_HEAP_ALLOCATION
906 // -----------------------------------------------------------------------
908 static inline
909 CarlaString operator+(const CarlaString& strBefore, const char* const strBufAfter) noexcept
911 if (strBufAfter == nullptr || strBufAfter[0] == '\0')
912 return strBefore;
913 if (strBefore.isEmpty())
914 return CarlaString(strBufAfter);
916 const std::size_t strBeforeLen = strBefore.length();
917 const std::size_t strBufAfterLen = std::strlen(strBufAfter);
918 const std::size_t newBufSize = strBeforeLen + strBufAfterLen;
919 char* const newBuf = (char*)std::malloc(newBufSize + 1);
920 CARLA_SAFE_ASSERT_RETURN(newBuf != nullptr, CarlaString());
922 std::memcpy(newBuf, strBefore.buffer(), strBeforeLen);
923 std::memcpy(newBuf + strBeforeLen, strBufAfter, strBufAfterLen + 1);
925 return CarlaString(newBuf, false);
928 static inline
929 CarlaString operator+(const char* const strBufBefore, const CarlaString& strAfter) noexcept
931 if (strAfter.isEmpty())
932 return CarlaString(strBufBefore);
933 if (strBufBefore == nullptr || strBufBefore[0] == '\0')
934 return strAfter;
936 const std::size_t strBufBeforeLen = std::strlen(strBufBefore);
937 const std::size_t strAfterLen = strAfter.length();
938 const std::size_t newBufSize = strBufBeforeLen + strAfterLen;
939 char* const newBuf = (char*)std::malloc(newBufSize + 1);
940 CARLA_SAFE_ASSERT_RETURN(newBuf != nullptr, CarlaString());
942 std::memcpy(newBuf, strBufBefore, strBufBeforeLen);
943 std::memcpy(newBuf + strBufBeforeLen, strAfter.buffer(), strAfterLen + 1);
945 return CarlaString(newBuf, false);
948 // -----------------------------------------------------------------------
950 #endif // CARLA_STRING_HPP_INCLUDED