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"
26 // -----------------------------------------------------------------------
29 class CARLA_API CarlaString
32 // -------------------------------------------------------------------
33 // constructors (no explicit conversions allowed)
38 explicit CarlaString() noexcept
41 fBufferAlloc(false) {}
46 explicit CarlaString(const char c
) noexcept
61 explicit CarlaString(char* const strBuf
, const bool reallocData
= true) noexcept
66 if (reallocData
|| strBuf
== nullptr)
73 fBufferLen
= std::strlen(strBuf
);
79 * Simple const char string.
81 explicit CarlaString(const char* const strBuf
) noexcept
92 explicit CarlaString(const int value
) noexcept
98 std::snprintf(strBuf
, 0xff, "%d", value
);
105 * Unsigned integer, possibly in hexadecimal.
107 explicit CarlaString(const unsigned int value
, const bool hexadecimal
= false) noexcept
113 std::snprintf(strBuf
, 0xff, hexadecimal
? "0x%x" : "%u", value
);
122 explicit CarlaString(const long value
) noexcept
128 std::snprintf(strBuf
, 0xff, "%ld", value
);
135 * Long unsigned integer, possibly hexadecimal.
137 explicit CarlaString(const unsigned long value
, const bool hexadecimal
= false) noexcept
143 std::snprintf(strBuf
, 0xff, hexadecimal
? "0x%lx" : "%lu", value
);
152 explicit CarlaString(const long long value
) noexcept
158 std::snprintf(strBuf
, 0xff, "%lld", value
);
165 * Long long unsigned integer, possibly hexadecimal.
167 explicit CarlaString(const unsigned long long value
, const bool hexadecimal
= false) noexcept
173 std::snprintf(strBuf
, 0xff, hexadecimal
? "0x%llx" : "%llu", value
);
180 * Single-precision floating point number.
182 explicit CarlaString(const float value
) noexcept
190 const CarlaScopedLocale csl
;
191 std::snprintf(strBuf
, 0xff, "%.12g", static_cast<double>(value
));
200 * Double-precision floating point number.
202 explicit CarlaString(const double value
) noexcept
210 const CarlaScopedLocale csl
;
211 std::snprintf(strBuf
, 0xff, "%.24g", value
);
219 // -------------------------------------------------------------------
220 // non-explicit constructor
223 * Create string from another string.
225 CarlaString(const CarlaString
& str
) noexcept
233 // -------------------------------------------------------------------
239 ~CarlaString() noexcept
241 CARLA_SAFE_ASSERT_RETURN(fBuffer
!= nullptr,);
248 fBufferAlloc
= false;
251 // -------------------------------------------------------------------
255 * Get length of the string.
257 std::size_t length() const noexcept
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
)
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);
302 return (strcasestr(fBuffer
, strBuf
) != nullptr);
304 CarlaString
tmp1(fBuffer
), tmp2(strBuf
);
306 // memory allocation failed or empty string(s)
307 if (tmp1
.fBuffer
== _null() || tmp2
.fBuffer
== _null())
312 return (std::strstr(tmp1
, tmp2
) != nullptr);
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
)
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
)
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)
392 for (std::size_t i
=0; i
< fBufferLen
; ++i
)
396 if (found
!= nullptr)
402 if (found
!= nullptr)
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)
420 if (char* const subStrBuf
= std::strstr(fBuffer
, strBuf
))
422 const ssize_t ret
= subStrBuf
- fBuffer
;
426 // should never happen!
427 carla_safe_assert_int("ret >= 0", __FILE__
, __LINE__
, int(ret
));
429 if (found
!= nullptr)
434 if (found
!= nullptr)
436 return static_cast<std::size_t>(ret
);
439 if (found
!= nullptr)
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)
457 for (std::size_t i
=fBufferLen
; i
> 0; --i
)
459 if (fBuffer
[i
-1] == c
)
461 if (found
!= nullptr)
467 if (found
!= nullptr)
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)
481 if (fBufferLen
== 0 || strBuf
== nullptr || strBuf
[0] == '\0')
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)
502 return fBufferLen
-ret
;
508 void clear() noexcept
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
)
530 * Truncate the string to size 'n'.
532 CarlaString
& truncate(const std::size_t n
) noexcept
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')
552 if (fBuffer
[i
] >= 'A' && fBuffer
[i
] <= 'Z')
554 if (fBuffer
[i
] >= 'a' && fBuffer
[i
] <= 'z')
556 if (fBuffer
[i
] == '_')
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
);
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
);
598 * Direct access to the string buffer (read-only).
600 const char* buffer() const noexcept
606 * Return a duplicate string buffer.
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;
631 fBufferAlloc
= false;
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"
646 static constexpr const std::size_t kTmpBufSize
= 65536U;
648 const uchar
* bytesToEncode((const uchar
*)data
);
651 uint charArray3
[3], charArray4
[4];
653 char strBuf
[kTmpBufSize
+1];
654 strBuf
[kTmpBufSize
] = '\0';
655 std::size_t strBufIndex
= 0;
659 for (std::size_t s
=0; s
<dataSize
; ++s
)
661 charArray3
[i
++] = *(bytesToEncode
++);
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;
671 strBuf
[strBufIndex
++] = kBase64Chars
[charArray4
[i
]];
673 if (strBufIndex
>= kTmpBufSize
-7)
675 strBuf
[strBufIndex
] = '\0';
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
]];
698 strBuf
[strBufIndex
++] = '=';
701 if (strBufIndex
!= 0)
703 strBuf
[strBufIndex
] = '\0';
710 // -------------------------------------------------------------------
713 operator const char*() const noexcept
718 char operator[](const std::size_t pos
) const noexcept
720 if (pos
< fBufferLen
)
723 carla_safe_assert("pos < fBufferLen", __FILE__
, __LINE__
);
725 static char fallback
;
730 char& operator[](const std::size_t pos
) noexcept
732 if (pos
< fBufferLen
)
735 carla_safe_assert("pos < fBufferLen", __FILE__
, __LINE__
);
737 static char 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
769 CarlaString
& operator=(const CarlaString
& str
) noexcept
776 CarlaString
& operator+=(const char* const strBuf
) noexcept
778 if (strBuf
== nullptr || strBuf
[0] == '\0')
781 const std::size_t strBufLen
= std::strlen(strBuf
);
783 // for empty strings, we can just take the appended string as our entire data
786 _dup(strBuf
, strBufLen
);
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);
797 fBufferLen
+= strBufLen
;
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')
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 // -------------------------------------------------------------------
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';
855 * Called whenever the string needs to be allocated.
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)
872 fBufferLen
= (size
> 0) ? size
: std::strlen(strBuf
);
873 fBuffer
= (char*)std::malloc(fBufferLen
+1);
875 if (fBuffer
== nullptr)
879 fBufferAlloc
= false;
885 std::strcpy(fBuffer
, strBuf
);
886 fBuffer
[fBufferLen
] = '\0';
890 CARLA_SAFE_ASSERT_UINT(size
== 0, static_cast<uint
>(size
));
892 // don't recreate null string
896 CARLA_SAFE_ASSERT(fBuffer
!= nullptr);
901 fBufferAlloc
= false;
905 CARLA_PREVENT_HEAP_ALLOCATION
908 // -----------------------------------------------------------------------
911 CarlaString
operator+(const CarlaString
& strBefore
, const char* const strBufAfter
) noexcept
913 if (strBufAfter
== nullptr || strBufAfter
[0] == '\0')
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);
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')
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