17 #ifndef DISTRHO_STRING_HPP_INCLUDED 
   18 #define DISTRHO_STRING_HPP_INCLUDED 
   20 #include "../DistrhoUtils.hpp" 
   21 #include "../extra/ScopedSafeLocale.hpp" 
   25 #if __cplusplus >= 201703L 
   26 # include <string_view> 
   46           fBufferAlloc(
false) {}
 
   51     explicit String(
const char c) noexcept
 
   66     explicit String(
char* 
const strBuf, 
const bool reallocData = 
true) noexcept
 
   71         if (reallocData || strBuf == 
nullptr)
 
   78             fBufferLen   = std::strlen(strBuf);
 
   86     explicit String(
const char* 
const strBuf) noexcept
 
   94    #if __cplusplus >= 201703L 
   98     explicit constexpr 
String(
const std::string_view& strView) noexcept
 
   99         : fBuffer(
const_cast<char*
>(strView.data())),
 
  100           fBufferLen(strView.size()),
 
  101           fBufferAlloc(
false) {}
 
  107     explicit String(
const int value) noexcept
 
  113         std::snprintf(strBuf, 0xff, 
"%d", value);
 
  122     explicit String(
const unsigned int value, 
const bool hexadecimal = 
false) noexcept
 
  128         std::snprintf(strBuf, 0xff, hexadecimal ? 
"0x%x" : 
"%u", value);
 
  137     explicit String(
const long value) noexcept
 
  143         std::snprintf(strBuf, 0xff, 
"%ld", value);
 
  152     explicit String(
const unsigned long value, 
const bool hexadecimal = 
false) noexcept
 
  158         std::snprintf(strBuf, 0xff, hexadecimal ? 
"0x%lx" : 
"%lu", value);
 
  167     explicit String(
const long long value) noexcept
 
  173         std::snprintf(strBuf, 0xff, 
"%lld", value);
 
  182     explicit String(
const unsigned long long value, 
const bool hexadecimal = 
false) noexcept
 
  188         std::snprintf(strBuf, 0xff, hexadecimal ? 
"0x%llx" : 
"%llu", value);
 
  197     explicit String(
const float value) noexcept
 
  206             std::snprintf(strBuf, 0xff, 
"%.12g", 
static_cast<double>(value));
 
  217     explicit String(
const double value) noexcept
 
  226             std::snprintf(strBuf, 0xff, 
"%.24g", value);
 
  256         DISTRHO_SAFE_ASSERT_RETURN(fBuffer != 
nullptr,);
 
  263         fBufferAlloc = 
false;
 
  272     std::size_t length() 
const noexcept
 
  280     bool isEmpty() 
const noexcept
 
  282         return (fBufferLen == 0);
 
  288     bool isNotEmpty() 
const noexcept
 
  290         return (fBufferLen != 0);
 
  296     bool contains(
const char c) 
const noexcept
 
  298         for (std::size_t i=0; i<fBufferLen; ++i)
 
  310     bool contains(
const char* 
const strBuf, 
const bool ignoreCase = 
false) 
const noexcept
 
  312         DISTRHO_SAFE_ASSERT_RETURN(strBuf != 
nullptr, 
false);
 
  317             return (strcasestr(fBuffer, strBuf) != 
nullptr);
 
  319             String tmp1(fBuffer), tmp2(strBuf);
 
  322             if (tmp1.fBuffer == _null() || tmp2.fBuffer == _null())
 
  327             return (std::strstr(tmp1, tmp2) != 
nullptr);
 
  331         return (std::strstr(fBuffer, strBuf) != 
nullptr);
 
  337     bool isDigit(
const std::size_t pos) 
const noexcept
 
  339         DISTRHO_SAFE_ASSERT_RETURN(pos < fBufferLen, 
false);
 
  341         return (fBuffer[pos] >= 
'0' && fBuffer[pos] <= 
'9');
 
  347     bool startsWith(
const char c) 
const noexcept
 
  349         DISTRHO_SAFE_ASSERT_RETURN(c != 
'\0', 
false);
 
  351         return (fBufferLen > 0 && fBuffer[0] == c);
 
  357     bool startsWith(
const char* 
const prefix) 
const noexcept
 
  359         DISTRHO_SAFE_ASSERT_RETURN(prefix != 
nullptr, 
false);
 
  361         const std::size_t prefixLen(std::strlen(prefix));
 
  363         if (fBufferLen < prefixLen)
 
  366         return (std::strncmp(fBuffer, prefix, prefixLen) == 0);
 
  372     bool endsWith(
const char c) 
const noexcept
 
  374         DISTRHO_SAFE_ASSERT_RETURN(c != 
'\0', 
false);
 
  376         return (fBufferLen > 0 && fBuffer[fBufferLen-1] == c);
 
  382     bool endsWith(
const char* 
const suffix) 
const noexcept
 
  384         DISTRHO_SAFE_ASSERT_RETURN(suffix != 
nullptr, 
false);
 
  386         const std::size_t suffixLen(std::strlen(suffix));
 
  388         if (fBufferLen < suffixLen)
 
  391         return (std::strncmp(fBuffer + (fBufferLen-suffixLen), suffix, suffixLen) == 0);
 
  398     std::size_t find(
const char c, 
bool* 
const found = 
nullptr) 
const noexcept
 
  400         if (fBufferLen == 0 || c == 
'\0')
 
  402             if (found != 
nullptr)
 
  407         for (std::size_t i=0; i < fBufferLen; ++i)
 
  411                 if (found != 
nullptr)
 
  417         if (found != 
nullptr)
 
  426     std::size_t find(
const char* 
const strBuf, 
bool* 
const found = 
nullptr) 
const noexcept
 
  428         if (fBufferLen == 0 || strBuf == 
nullptr || strBuf[0] == 
'\0')
 
  430             if (found != 
nullptr)
 
  435         if (
char* 
const subStrBuf = std::strstr(fBuffer, strBuf))
 
  437             const ssize_t ret(subStrBuf - fBuffer);
 
  444                 if (found != 
nullptr)
 
  449             if (found != 
nullptr)
 
  451             return static_cast<std::size_t
>(ret);
 
  454         if (found != 
nullptr)
 
  463     std::size_t rfind(
const char c, 
bool* 
const found = 
nullptr) 
const noexcept
 
  465         if (fBufferLen == 0 || c == 
'\0')
 
  467             if (found != 
nullptr)
 
  472         for (std::size_t i=fBufferLen; i > 0; --i)
 
  474             if (fBuffer[i-1] == c)
 
  476                 if (found != 
nullptr)
 
  482         if (found != 
nullptr)
 
  491     std::size_t rfind(
const char* 
const strBuf, 
bool* 
const found = 
nullptr) 
const noexcept
 
  493         if (found != 
nullptr)
 
  496         if (fBufferLen == 0 || strBuf == 
nullptr || strBuf[0] == 
'\0')
 
  499         const std::size_t strBufLen(std::strlen(strBuf));
 
  501         std::size_t ret = fBufferLen;
 
  502         const char* tmpBuf = fBuffer;
 
  504         for (std::size_t i=0; i < fBufferLen; ++i)
 
  506             if (std::strstr(tmpBuf+1, strBuf) == 
nullptr && std::strncmp(tmpBuf, strBuf, strBufLen) == 0)
 
  508                 if (found != 
nullptr)
 
  517         return fBufferLen-ret;
 
  523     void clear() noexcept
 
  531     String& replace(
const char before, 
const char after) noexcept
 
  533         DISTRHO_SAFE_ASSERT_RETURN(before != 
'\0' , *
this);
 
  535         for (std::size_t i=0; i < fBufferLen; ++i)
 
  537             if (fBuffer[i] == before)
 
  547     String& remove(
const char c) noexcept
 
  549         DISTRHO_SAFE_ASSERT_RETURN(c != 
'\0', *
this);
 
  554         for (std::size_t i=0; i < fBufferLen; ++i)
 
  559                 std::memmove(fBuffer+i, fBuffer+i+1, fBufferLen-i);
 
  563         fBuffer[fBufferLen] = 
'\0';
 
  570     String& truncate(
const std::size_t n) noexcept
 
  584     String& toBasic() noexcept
 
  586         for (std::size_t i=0; i < fBufferLen; ++i)
 
  588             if (fBuffer[i] >= 
'0' && fBuffer[i] <= 
'9')
 
  590             if (fBuffer[i] >= 
'A' && fBuffer[i] <= 
'Z')
 
  592             if (fBuffer[i] >= 
'a' && fBuffer[i] <= 
'z')
 
  594             if (fBuffer[i] == 
'_')
 
  606     String& toLower() noexcept
 
  608         static const char kCharDiff(
'a' - 
'A');
 
  610         for (std::size_t i=0; i < fBufferLen; ++i)
 
  612             if (fBuffer[i] >= 
'A' && fBuffer[i] <= 
'Z')
 
  613                 fBuffer[i] = 
static_cast<char>(fBuffer[i] + kCharDiff);
 
  622     String& toUpper() noexcept
 
  624         static const char kCharDiff(
'a' - 
'A');
 
  626         for (std::size_t i=0; i < fBufferLen; ++i)
 
  628             if (fBuffer[i] >= 
'a' && fBuffer[i] <= 
'z')
 
  629                 fBuffer[i] = 
static_cast<char>(fBuffer[i] - kCharDiff);
 
  639     String asBasic() 
const noexcept
 
  649     String asLower() 
const noexcept
 
  659     String asUpper() 
const noexcept
 
  668     const char* buffer() 
const noexcept
 
  678     char* getAndReleaseBuffer() noexcept
 
  680         char* ret = fBufferLen > 0 ? fBuffer : 
nullptr;
 
  683         fBufferAlloc = 
false;
 
  691     static String asBase64(
const void* 
const data, 
const std::size_t dataSize)
 
  693         static const char* 
const kBase64Chars =
 
  694             "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 
  695             "abcdefghijklmnopqrstuvwxyz" 
  699         const std::size_t kTmpBufSize = std::min(
d_nextPowerOf2(
static_cast<uint32_t
>(dataSize/3)), 65536U);
 
  701         constexpr std::size_t kTmpBufSize = 65536U;
 
  704         const uchar* bytesToEncode((
const uchar*)data);
 
  707         uint charArray3[3], charArray4[4];
 
  709         char strBuf[kTmpBufSize + 1];
 
  710         strBuf[kTmpBufSize] = 
'\0';
 
  711         std::size_t strBufIndex = 0;
 
  715         for (std::size_t s=0; s<dataSize; ++s)
 
  717             charArray3[i++] = *(bytesToEncode++);
 
  721                 charArray4[0] =  (charArray3[0] & 0xfc) >> 2;
 
  722                 charArray4[1] = ((charArray3[0] & 0x03) << 4) + ((charArray3[1] & 0xf0) >> 4);
 
  723                 charArray4[2] = ((charArray3[1] & 0x0f) << 2) + ((charArray3[2] & 0xc0) >> 6);
 
  724                 charArray4[3] =   charArray3[2] & 0x3f;
 
  727                     strBuf[strBufIndex++] = kBase64Chars[charArray4[i]];
 
  729                 if (strBufIndex >= kTmpBufSize-7)
 
  731                     strBuf[strBufIndex] = 
'\0';
 
  743               charArray3[j] = 
'\0';
 
  745             charArray4[0] =  (charArray3[0] & 0xfc) >> 2;
 
  746             charArray4[1] = ((charArray3[0] & 0x03) << 4) + ((charArray3[1] & 0xf0) >> 4);
 
  747             charArray4[2] = ((charArray3[1] & 0x0f) << 2) + ((charArray3[2] & 0xc0) >> 6);
 
  748             charArray4[3] =   charArray3[2] & 0x3f;
 
  750             for (j=0; j<4 && i<3 && j<i+1; ++j)
 
  751                 strBuf[strBufIndex++] = kBase64Chars[charArray4[j]];
 
  754                 strBuf[strBufIndex++] = 
'=';
 
  757         if (strBufIndex != 0)
 
  759             strBuf[strBufIndex] = 
'\0';
 
  769     operator const char*() 
const noexcept
 
  774     char operator[](
const std::size_t pos) 
const noexcept
 
  776         if (pos < fBufferLen)
 
  781         static char fallback;
 
  786     char& operator[](
const std::size_t pos) noexcept
 
  788         if (pos < fBufferLen)
 
  793         static char fallback;
 
  798     bool operator==(
const char* 
const strBuf) 
const noexcept
 
  800         return (strBuf != 
nullptr && std::strcmp(fBuffer, strBuf) == 0);
 
  803     bool operator==(
const String& str) 
const noexcept
 
  805         return operator==(str.fBuffer);
 
  808     bool operator!=(
const char* 
const strBuf) 
const noexcept
 
  810         return !operator==(strBuf);
 
  813     bool operator!=(
const String& str) 
const noexcept
 
  815         return !operator==(str.fBuffer);
 
  818     String& operator=(
const char* 
const strBuf) noexcept
 
  832     String& operator+=(
const char* 
const strBuf) noexcept
 
  834         if (strBuf == 
nullptr || strBuf[0] == 
'\0')
 
  837         const std::size_t strBufLen = std::strlen(strBuf);
 
  842             _dup(strBuf, strBufLen);
 
  847         char* 
const newBuf = (
char*)realloc(fBuffer, fBufferLen + strBufLen + 1);
 
  848         DISTRHO_SAFE_ASSERT_RETURN(newBuf != 
nullptr, *
this);
 
  850         std::memcpy(newBuf + fBufferLen, strBuf, strBufLen + 1);
 
  853         fBufferLen += strBufLen;
 
  860         return operator+=(str.fBuffer);
 
  863     String operator+(
const char* 
const strBuf) noexcept
 
  865         if (strBuf == 
nullptr || strBuf[0] == 
'\0')
 
  870         const std::size_t strBufLen = std::strlen(strBuf);
 
  871         const std::size_t newBufSize = fBufferLen + strBufLen;
 
  872         char* 
const newBuf = (
char*)malloc(newBufSize + 1);
 
  873         DISTRHO_SAFE_ASSERT_RETURN(newBuf != 
nullptr, 
String());
 
  875         std::memcpy(newBuf, fBuffer, fBufferLen);
 
  876         std::memcpy(newBuf + fBufferLen, strBuf, strBufLen + 1);
 
  878         return String(newBuf, 
false);
 
  883         return operator+(str.fBuffer);
 
  887     bool operator<(
const String& str) 
const noexcept
 
  889         return std::strcmp(fBuffer, str.fBuffer) < 0;
 
  896     std::size_t fBufferLen;   
 
  903     static char* _null() noexcept
 
  905         static char sNull = 
'\0';
 
  917     void _dup(
const char* 
const strBuf, 
const std::size_t size = 0) noexcept
 
  919         if (strBuf != 
nullptr)
 
  922             if (std::strcmp(fBuffer, strBuf) == 0)
 
  928             fBufferLen = (size > 0) ? size : std::strlen(strBuf);
 
  929             fBuffer    = (
char*)std::malloc(fBufferLen+1);
 
  931             if (fBuffer == 
nullptr)
 
  935                 fBufferAlloc = 
false;
 
  941             std::strcpy(fBuffer, strBuf);
 
  942             fBuffer[fBufferLen] = 
'\0';
 
  946             DISTRHO_SAFE_ASSERT_UINT(size == 0, 
static_cast<uint
>(size));
 
  952             DISTRHO_SAFE_ASSERT(fBuffer != 
nullptr);
 
  957             fBufferAlloc = 
false;
 
  961     DISTRHO_PREVENT_HEAP_ALLOCATION
 
  967 String operator+(
const String& strBefore, 
const char* 
const strBufAfter) noexcept
 
  969     if (strBufAfter == 
nullptr || strBufAfter[0] == 
'\0')
 
  971     if (strBefore.isEmpty())
 
  972         return String(strBufAfter);
 
  974     const std::size_t strBeforeLen = strBefore.length();
 
  975     const std::size_t strBufAfterLen = std::strlen(strBufAfter);
 
  976     const std::size_t newBufSize = strBeforeLen + strBufAfterLen;
 
  977     char* 
const newBuf = (
char*)malloc(newBufSize + 1);
 
  978     DISTRHO_SAFE_ASSERT_RETURN(newBuf != 
nullptr, 
String());
 
  980     std::memcpy(newBuf, strBefore.buffer(), strBeforeLen);
 
  981     std::memcpy(newBuf + strBeforeLen, strBufAfter, strBufAfterLen + 1);
 
  983     return String(newBuf, 
false);
 
  987 String operator+(
const char* 
const strBufBefore, 
const String& strAfter) noexcept
 
  989     if (strAfter.isEmpty())
 
  990         return String(strBufBefore);
 
  991     if (strBufBefore == 
nullptr || strBufBefore[0] == 
'\0')
 
  994     const std::size_t strBufBeforeLen = std::strlen(strBufBefore);
 
  995     const std::size_t strAfterLen = strAfter.length();
 
  996     const std::size_t newBufSize = strBufBeforeLen + strAfterLen;
 
  997     char* 
const newBuf = (
char*)malloc(newBufSize + 1);
 
  998     DISTRHO_SAFE_ASSERT_RETURN(newBuf != 
nullptr, 
String());
 
 1000     std::memcpy(newBuf, strBufBefore, strBufBeforeLen);
 
 1001     std::memcpy(newBuf + strBufBeforeLen, strAfter.buffer(), strAfterLen + 1);
 
 1003     return String(newBuf, 
false);
 
Definition: ScopedSafeLocale.hpp:57
 
Definition: String.hpp:35
 
static uint32_t d_nextPowerOf2(uint32_t size) noexcept
Definition: DistrhoUtils.hpp:308
 
#define END_NAMESPACE_DISTRHO
Definition: DistrhoInfo.hpp:949
 
#define START_NAMESPACE_DISTRHO
Definition: DistrhoInfo.hpp:943
 
static void d_safe_assert(const char *const assertion, const char *const file, const int line) noexcept
Definition: DistrhoUtils.hpp:187
 
static void d_safe_assert_int(const char *const assertion, const char *const file, const int line, const int value) noexcept
Definition: DistrhoUtils.hpp:196