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