17 #ifndef DISTRHO_STRING_HPP_INCLUDED 
   18 #define DISTRHO_STRING_HPP_INCLUDED 
   20 #include "d_leakdetector.hpp" 
   22 START_NAMESPACE_DISTRHO
 
   44     explicit d_string(
const char c) noexcept
 
   57     explicit d_string(
char* 
const strBuf) noexcept
 
   66     explicit d_string(
const char* 
const strBuf) noexcept
 
   75     explicit d_string(
const int value) noexcept
 
   78         std::snprintf(strBuf, 0xff, 
"%d", value);
 
   88     explicit d_string(
const unsigned int value, 
const bool hexadecimal = 
false) noexcept
 
   91         std::snprintf(strBuf, 0xff, hexadecimal ? 
"0x%x" : 
"%u", value);
 
  101     explicit d_string(
const long value) noexcept
 
  104         std::snprintf(strBuf, 0xff, 
"%ld", value);
 
  114     explicit d_string(
const unsigned long value, 
const bool hexadecimal = 
false) noexcept
 
  117         std::snprintf(strBuf, 0xff, hexadecimal ? 
"0x%lx" : 
"%lu", value);
 
  127     explicit d_string(
const long long value) noexcept
 
  130         std::snprintf(strBuf, 0xff, 
"%lld", value);
 
  140     explicit d_string(
const unsigned long long value, 
const bool hexadecimal = 
false) noexcept
 
  143         std::snprintf(strBuf, 0xff, hexadecimal ? 
"0x%llx" : 
"%llu", value);
 
  153     explicit d_string(
const float value) noexcept
 
  156         std::snprintf(strBuf, 0xff, 
"%f", value);
 
  166     explicit d_string(
const double value) noexcept
 
  169         std::snprintf(strBuf, 0xff, 
"%g", value);
 
  196         DISTRHO_SAFE_ASSERT_RETURN(fBuffer != 
nullptr,);
 
  198         if (fBuffer == _null())
 
  213     size_t length() 
const noexcept
 
  221     bool isEmpty() 
const noexcept
 
  223         return (fBufferLen == 0);
 
  229     bool isNotEmpty() 
const noexcept
 
  231         return (fBufferLen != 0);
 
  237     bool contains(
const char* 
const strBuf, 
const bool ignoreCase = 
false) 
const noexcept
 
  239         DISTRHO_SAFE_ASSERT_RETURN(strBuf != 
nullptr, 
false);
 
  244             return (strcasestr(fBuffer, strBuf) != 
nullptr);
 
  246             d_string tmp1(fBuffer), tmp2(strBuf);
 
  249             if (tmp1.fBuffer == _null() || tmp2.fBuffer == _null())
 
  254             return (std::strstr(tmp1, tmp2) != 
nullptr);
 
  258         return (std::strstr(fBuffer, strBuf) != 
nullptr);
 
  264     bool isDigit(
const size_t pos) 
const noexcept
 
  266         DISTRHO_SAFE_ASSERT_RETURN(pos < fBufferLen, 
false);
 
  268         return (fBuffer[pos] >= 
'0' && fBuffer[pos] <= 
'9');
 
  274     bool startsWith(
const char c) 
const noexcept
 
  276         DISTRHO_SAFE_ASSERT_RETURN(c != 
'\0', 
false);
 
  278         return (fBufferLen > 0 && fBuffer[0] == c);
 
  284     bool startsWith(
const char* 
const prefix) 
const noexcept
 
  286         DISTRHO_SAFE_ASSERT_RETURN(prefix != 
nullptr, 
false);
 
  288         const size_t prefixLen(std::strlen(prefix));
 
  290         if (fBufferLen < prefixLen)
 
  293         return (std::strncmp(fBuffer, prefix, prefixLen) == 0);
 
  299     bool endsWith(
const char c) 
const noexcept
 
  301         DISTRHO_SAFE_ASSERT_RETURN(c != 
'\0', 
false);
 
  303         return (fBufferLen > 0 && fBuffer[fBufferLen-1] == c);
 
  309     bool endsWith(
const char* 
const suffix) 
const noexcept
 
  311         DISTRHO_SAFE_ASSERT_RETURN(suffix != 
nullptr, 
false);
 
  313         const size_t suffixLen(std::strlen(suffix));
 
  315         if (fBufferLen < suffixLen)
 
  318         return (std::strncmp(fBuffer + (fBufferLen-suffixLen), suffix, suffixLen) == 0);
 
  325     size_t find(
const char c, 
bool* 
const found = 
nullptr) 
const noexcept
 
  327         if (fBufferLen == 0 || c == 
'\0')
 
  329             if (found != 
nullptr)
 
  334         for (
size_t i=0; i < fBufferLen; ++i)
 
  338                 if (found != 
nullptr)
 
  344         if (found != 
nullptr)
 
  353     size_t find(
const char* 
const strBuf, 
bool* 
const found = 
nullptr) 
const noexcept
 
  355         if (fBufferLen == 0 || strBuf == 
nullptr || strBuf[0] == 
'\0')
 
  357             if (found != 
nullptr)
 
  362         if (
char* 
const subStrBuf = std::strstr(fBuffer, strBuf))
 
  364             const ssize_t ret(subStrBuf - fBuffer);
 
  369                 d_safe_assert(
"ret >= 0", __FILE__, __LINE__);
 
  371                 if (found != 
nullptr)
 
  376             if (found != 
nullptr)
 
  378             return static_cast<size_t>(ret);
 
  381         if (found != 
nullptr)
 
  390     size_t rfind(
const char c, 
bool* 
const found = 
nullptr) 
const noexcept
 
  392         if (fBufferLen == 0 || c == 
'\0')
 
  394             if (found != 
nullptr)
 
  399         for (
size_t i=fBufferLen; i > 0; --i)
 
  401             if (fBuffer[i-1] == c)
 
  403                 if (found != 
nullptr)
 
  409         if (found != 
nullptr)
 
  418     size_t rfind(
const char* 
const strBuf, 
bool* 
const found = 
nullptr) 
const noexcept
 
  420         if (found != 
nullptr)
 
  423         if (fBufferLen == 0 || strBuf == 
nullptr || strBuf[0] == 
'\0')
 
  426         const size_t strBufLen(std::strlen(strBuf));
 
  428         size_t ret = fBufferLen;
 
  429         const char* tmpBuf = fBuffer;
 
  431         for (
size_t i=0; i < fBufferLen; ++i)
 
  433             if (std::strstr(tmpBuf+1, strBuf) == 
nullptr && std::strncmp(tmpBuf, strBuf, strBufLen) == 0)
 
  435                 if (found != 
nullptr)
 
  444         return fBufferLen-ret;
 
  450     void clear() noexcept
 
  458     void replace(
const char before, 
const char after) noexcept
 
  460         DISTRHO_SAFE_ASSERT_RETURN(before != 
'\0' && after != 
'\0',);
 
  462         for (
size_t i=0; i < fBufferLen; ++i)
 
  464             if (fBuffer[i] == before)
 
  472     void truncate(
const size_t n) noexcept
 
  477         for (
size_t i=n; i < fBufferLen; ++i)
 
  486     void toBasic() noexcept
 
  488         for (
size_t i=0; i < fBufferLen; ++i)
 
  490             if (fBuffer[i] >= 
'0' && fBuffer[i] <= 
'9')
 
  492             if (fBuffer[i] >= 
'A' && fBuffer[i] <= 
'Z')
 
  494             if (fBuffer[i] >= 
'a' && fBuffer[i] <= 
'z')
 
  496             if (fBuffer[i] == 
'_')
 
  506     void toLower() noexcept
 
  508         static const char kCharDiff(
'a' - 
'A');
 
  510         for (
size_t i=0; i < fBufferLen; ++i)
 
  512             if (fBuffer[i] >= 
'A' && fBuffer[i] <= 
'Z')
 
  513                 fBuffer[i] = 
static_cast<char>(fBuffer[i] + kCharDiff);
 
  520     void toUpper() noexcept
 
  522         static const char kCharDiff(
'a' - 
'A');
 
  524         for (
size_t i=0; i < fBufferLen; ++i)
 
  526             if (fBuffer[i] >= 
'a' && fBuffer[i] <= 
'z')
 
  527                 fBuffer[i] = 
static_cast<char>(fBuffer[i] - kCharDiff);
 
  534     const char* buffer() 
const noexcept
 
  542     operator const char*() 
const noexcept
 
  547     char operator[](
const size_t pos) 
const noexcept
 
  549         if (pos < fBufferLen)
 
  552         d_safe_assert(
"pos < fBufferLen", __FILE__, __LINE__);
 
  554         static char fallback;
 
  559     char& operator[](
const size_t pos) noexcept
 
  561         if (pos < fBufferLen)
 
  564         d_safe_assert(
"pos < fBufferLen", __FILE__, __LINE__);
 
  566         static char fallback;
 
  571     bool operator==(
const char* 
const strBuf) 
const noexcept
 
  573         return (strBuf != 
nullptr && std::strcmp(fBuffer, strBuf) == 0);
 
  576     bool operator==(
const d_string& str) 
const noexcept
 
  578         return operator==(str.fBuffer);
 
  581     bool operator!=(
const char* 
const strBuf) 
const noexcept
 
  583         return !operator==(strBuf);
 
  586     bool operator!=(
const d_string& str) 
const noexcept
 
  588         return !operator==(str.fBuffer);
 
  591     d_string& operator=(
const char* 
const strBuf) noexcept
 
  605     d_string& operator+=(
const char* 
const strBuf) noexcept
 
  607         if (strBuf == 
nullptr)
 
  610         const size_t newBufSize = fBufferLen + std::strlen(strBuf) + 1;
 
  611         char         newBuf[newBufSize];
 
  613         std::strcpy(newBuf, fBuffer);
 
  614         std::strcat(newBuf, strBuf);
 
  616         _dup(newBuf, newBufSize-1);
 
  623         return operator+=(str.fBuffer);
 
  626     d_string operator+(
const char* 
const strBuf) noexcept
 
  628         const size_t newBufSize = fBufferLen + ((strBuf != 
nullptr) ? std::strlen(strBuf) : 0) + 1;
 
  629         char         newBuf[newBufSize];
 
  631         std::strcpy(newBuf, fBuffer);
 
  633         if (strBuf != 
nullptr)
 
  634             std::strcat(newBuf, strBuf);
 
  641         return operator+(str.fBuffer);
 
  654     static char* _null() noexcept
 
  656         static char sNull = 
'\0';
 
  664     void _init() noexcept
 
  678     void _dup(
const char* 
const strBuf, 
const size_t size = 0) noexcept
 
  680         if (strBuf != 
nullptr)
 
  683             if (std::strcmp(fBuffer, strBuf) == 0)
 
  686             if (fBuffer != _null())
 
  689             fBufferLen = (size > 0) ? size : std::strlen(strBuf);
 
  690             fBuffer    = (
char*)std::malloc(fBufferLen+1);
 
  692             if (fBuffer == 
nullptr)
 
  695             std::strcpy(fBuffer, strBuf);
 
  697             fBuffer[fBufferLen] = 
'\0';
 
  701             DISTRHO_SAFE_ASSERT(size == 0);
 
  704             if (fBuffer == _null())
 
  707             DISTRHO_SAFE_ASSERT(fBuffer != 
nullptr);
 
  715     DISTRHO_PREVENT_HEAP_ALLOCATION
 
  721 d_string operator+(
const d_string& strBefore, 
const char* 
const strBufAfter) noexcept
 
  723     const char* 
const strBufBefore = strBefore.buffer();
 
  724     const size_t      newBufSize   = strBefore.length() + ((strBufAfter != 
nullptr) ? std::strlen(strBufAfter) : 0) + 1;
 
  725     char newBuf[newBufSize];
 
  727     std::strcpy(newBuf, strBufBefore);
 
  728     std::strcat(newBuf, strBufAfter);
 
  734 d_string operator+(
const char* 
const strBufBefore, 
const d_string& strAfter) noexcept
 
  736     const char* 
const strBufAfter = strAfter.buffer();
 
  737     const size_t      newBufSize  = ((strBufBefore != 
nullptr) ? std::strlen(strBufBefore) : 0) + strAfter.length() + 1;
 
  738     char newBuf[newBufSize];
 
  740     std::strcpy(newBuf, strBufBefore);
 
  741     std::strcat(newBuf, strBufAfter);
 
  748 END_NAMESPACE_DISTRHO
 
  750 #endif // DISTRHO_STRING_HPP_INCLUDED 
Definition: d_string.hpp:27