Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CarlaString.hpp 12KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. /*
  2. * Carla String
  3. * Copyright (C) 2013 Filipe Coelho <falktx@falktx.com>
  4. *
  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.
  9. *
  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.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #ifndef CARLA_STRING_HPP_INCLUDED
  18. #define CARLA_STRING_HPP_INCLUDED
  19. #include "CarlaJuceUtils.hpp"
  20. // -----------------------------------------------------------------------
  21. // CarlaString class
  22. class CarlaString
  23. {
  24. public:
  25. // -------------------------------------------------------------------
  26. // constructors (no explicit conversions allowed)
  27. explicit CarlaString()
  28. {
  29. _init();
  30. _dup(nullptr);
  31. }
  32. explicit CarlaString(char* const strBuf)
  33. {
  34. _init();
  35. _dup(strBuf);
  36. }
  37. explicit CarlaString(const char* const strBuf)
  38. {
  39. _init();
  40. _dup(strBuf);
  41. }
  42. explicit CarlaString(const int value)
  43. {
  44. char strBuf[0xff+1];
  45. carla_zeroChar(strBuf, 0xff+1);
  46. std::snprintf(strBuf, 0xff, "%d", value);
  47. _init();
  48. _dup(strBuf);
  49. }
  50. explicit CarlaString(const unsigned int value, const bool hexadecimal = false)
  51. {
  52. char strBuf[0xff+1];
  53. carla_zeroChar(strBuf, 0xff+1);
  54. std::snprintf(strBuf, 0xff, hexadecimal ? "0x%x" : "%u", value);
  55. _init();
  56. _dup(strBuf);
  57. }
  58. explicit CarlaString(const long int value)
  59. {
  60. char strBuf[0xff+1];
  61. carla_zeroChar(strBuf, 0xff+1);
  62. std::snprintf(strBuf, 0xff, "%ld", value);
  63. _init();
  64. _dup(strBuf);
  65. }
  66. explicit CarlaString(const unsigned long int value, const bool hexadecimal = false)
  67. {
  68. char strBuf[0xff+1];
  69. carla_zeroChar(strBuf, 0xff+1);
  70. std::snprintf(strBuf, 0xff, hexadecimal ? "0x%lx" : "%lu", value);
  71. _init();
  72. _dup(strBuf);
  73. }
  74. explicit CarlaString(const float value)
  75. {
  76. char strBuf[0xff+1];
  77. carla_zeroChar(strBuf, 0xff+1);
  78. std::snprintf(strBuf, 0xff, "%f", value);
  79. _init();
  80. _dup(strBuf);
  81. }
  82. explicit CarlaString(const double value)
  83. {
  84. char strBuf[0xff+1];
  85. carla_zeroChar(strBuf, 0xff+1);
  86. std::snprintf(strBuf, 0xff, "%g", value);
  87. _init();
  88. _dup(strBuf);
  89. }
  90. // -------------------------------------------------------------------
  91. // non-explicit constructor
  92. CarlaString(const CarlaString& str)
  93. {
  94. _init();
  95. _dup(str.fBuffer);
  96. }
  97. // -------------------------------------------------------------------
  98. // destructor
  99. ~CarlaString()
  100. {
  101. CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr,);
  102. delete[] fBuffer;
  103. fBuffer = nullptr;
  104. }
  105. // -------------------------------------------------------------------
  106. // public methods
  107. size_t length() const noexcept
  108. {
  109. return fBufferLen;
  110. }
  111. bool isEmpty() const noexcept
  112. {
  113. return (fBufferLen == 0);
  114. }
  115. bool isNotEmpty() const noexcept
  116. {
  117. return (fBufferLen != 0);
  118. }
  119. #ifdef __USE_GNU
  120. bool contains(const char* const strBuf, const bool ignoreCase = false) const
  121. {
  122. CARLA_SAFE_ASSERT_RETURN(strBuf != nullptr, false);
  123. if (ignoreCase)
  124. return (strcasestr(fBuffer, strBuf) != nullptr);
  125. else
  126. return (std::strstr(fBuffer, strBuf) != nullptr);
  127. }
  128. bool contains(const CarlaString& str, const bool ignoreCase = false) const
  129. {
  130. return contains(str.fBuffer, ignoreCase);
  131. }
  132. #else
  133. bool contains(const char* const strBuf) const
  134. {
  135. CARLA_SAFE_ASSERT_RETURN(strBuf != nullptr, false);
  136. return (std::strstr(fBuffer, strBuf) != nullptr);
  137. }
  138. bool contains(const CarlaString& str) const
  139. {
  140. return contains(str.fBuffer);
  141. }
  142. #endif
  143. bool isDigit(const size_t pos) const noexcept
  144. {
  145. CARLA_SAFE_ASSERT_RETURN(pos < fBufferLen, false);
  146. return (fBuffer[pos] >= '0' && fBuffer[pos] <= '9');
  147. }
  148. bool startsWith(const char c) const
  149. {
  150. CARLA_SAFE_ASSERT_RETURN(c != '\0', false);
  151. return (fBufferLen > 0 && fBuffer[0] == c);
  152. }
  153. bool startsWith(const char* const prefix) const
  154. {
  155. CARLA_SAFE_ASSERT_RETURN(prefix != nullptr, false);
  156. const size_t prefixLen(std::strlen(prefix));
  157. if (fBufferLen < prefixLen)
  158. return false;
  159. return (std::strncmp(fBuffer + (fBufferLen-prefixLen), prefix, prefixLen) == 0);
  160. }
  161. bool endsWith(const char c) const
  162. {
  163. CARLA_SAFE_ASSERT_RETURN(c != '\0', false);
  164. return (fBufferLen > 0 && fBuffer[fBufferLen] == c);
  165. }
  166. bool endsWith(const char* const suffix) const
  167. {
  168. CARLA_SAFE_ASSERT_RETURN(suffix != nullptr, false);
  169. const size_t suffixLen(std::strlen(suffix));
  170. if (fBufferLen < suffixLen)
  171. return false;
  172. return (std::strncmp(fBuffer + (fBufferLen-suffixLen), suffix, suffixLen) == 0);
  173. }
  174. void clear() noexcept
  175. {
  176. truncate(0);
  177. }
  178. size_t find(const char c) const noexcept
  179. {
  180. for (size_t i=0; i < fBufferLen; ++i)
  181. {
  182. if (fBuffer[i] == c)
  183. return i;
  184. }
  185. return 0;
  186. }
  187. size_t rfind(const char c) const noexcept
  188. {
  189. for (size_t i=fBufferLen; i > 0; --i)
  190. {
  191. if (fBuffer[i-1] == c)
  192. return i-1;
  193. }
  194. return 0;
  195. }
  196. size_t rfind(const char* const strBuf) const
  197. {
  198. CARLA_SAFE_ASSERT_RETURN(strBuf != nullptr && strBuf[0] != '\0', fBufferLen);
  199. size_t ret = fBufferLen+1;
  200. const char* tmpBuf = fBuffer;
  201. for (size_t i=0; i < fBufferLen; ++i)
  202. {
  203. if (std::strstr(tmpBuf, strBuf) == nullptr)
  204. break;
  205. --ret;
  206. ++tmpBuf;
  207. }
  208. return (ret > fBufferLen) ? fBufferLen : fBufferLen-ret;
  209. }
  210. void replace(const char before, const char after)
  211. {
  212. CARLA_SAFE_ASSERT_RETURN(before != '\0' && after != '\0',);
  213. for (size_t i=0; i < fBufferLen; ++i)
  214. {
  215. if (fBuffer[i] == before)
  216. fBuffer[i] = after;
  217. else if (fBuffer[i] == '\0')
  218. break;
  219. }
  220. }
  221. void truncate(const size_t n) noexcept
  222. {
  223. if (n >= fBufferLen)
  224. return;
  225. for (size_t i=n; i < fBufferLen; ++i)
  226. fBuffer[i] = '\0';
  227. fBufferLen = n;
  228. }
  229. void toBasic() noexcept
  230. {
  231. for (size_t i=0; i < fBufferLen; ++i)
  232. {
  233. if (fBuffer[i] >= '0' && fBuffer[i] <= '9')
  234. continue;
  235. if (fBuffer[i] >= 'A' && fBuffer[i] <= 'Z')
  236. continue;
  237. if (fBuffer[i] >= 'a' && fBuffer[i] <= 'z')
  238. continue;
  239. if (fBuffer[i] == '_')
  240. continue;
  241. fBuffer[i] = '_';
  242. }
  243. }
  244. void toLower() noexcept
  245. {
  246. #ifndef BUILD_ANSI_TEST
  247. // Using '+=' temporarily converts char into int
  248. static const char kCharDiff('a' - 'A');
  249. for (size_t i=0; i < fBufferLen; ++i)
  250. {
  251. if (fBuffer[i] >= 'A' && fBuffer[i] <= 'Z')
  252. fBuffer[i] += kCharDiff;
  253. }
  254. #endif
  255. }
  256. void toUpper() noexcept
  257. {
  258. #ifndef BUILD_ANSI_TEST
  259. // Using '-=' temporarily converts char into int
  260. static const char kCharDiff('a' - 'A');
  261. for (size_t i=0; i < fBufferLen; ++i)
  262. {
  263. if (fBuffer[i] >= 'a' && fBuffer[i] <= 'z')
  264. fBuffer[i] -= kCharDiff;
  265. }
  266. #endif
  267. }
  268. // -------------------------------------------------------------------
  269. // public operators
  270. operator const char*() const noexcept
  271. {
  272. return fBuffer;
  273. }
  274. char& operator[](const size_t pos) const noexcept
  275. {
  276. return fBuffer[pos];
  277. }
  278. bool operator==(const char* const strBuf) const
  279. {
  280. return (strBuf != nullptr && std::strcmp(fBuffer, strBuf) == 0);
  281. }
  282. bool operator==(const CarlaString& str) const
  283. {
  284. return operator==(str.fBuffer);
  285. }
  286. bool operator!=(const char* const strBuf) const
  287. {
  288. return !operator==(strBuf);
  289. }
  290. bool operator!=(const CarlaString& str) const
  291. {
  292. return !operator==(str.fBuffer);
  293. }
  294. CarlaString& operator=(const char* const strBuf)
  295. {
  296. _dup(strBuf);
  297. return *this;
  298. }
  299. CarlaString& operator=(const CarlaString& str)
  300. {
  301. return operator=(str.fBuffer);
  302. }
  303. CarlaString& operator+=(const char* const strBuf)
  304. {
  305. const size_t newBufSize = fBufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
  306. char newBuf[newBufSize];
  307. std::strcpy(newBuf, fBuffer);
  308. std::strcat(newBuf, strBuf);
  309. _dup(newBuf, newBufSize-1);
  310. return *this;
  311. }
  312. CarlaString& operator+=(const CarlaString& str)
  313. {
  314. return operator+=(str.fBuffer);
  315. }
  316. CarlaString operator+(const char* const strBuf)
  317. {
  318. const size_t newBufSize = fBufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
  319. char newBuf[newBufSize];
  320. std::strcpy(newBuf, fBuffer);
  321. std::strcat(newBuf, strBuf);
  322. return CarlaString(newBuf);
  323. }
  324. CarlaString operator+(const CarlaString& str)
  325. {
  326. return operator+(str.fBuffer);
  327. }
  328. // -------------------------------------------------------------------
  329. private:
  330. char* fBuffer;
  331. size_t fBufferLen;
  332. bool fFirstInit;
  333. void _init() noexcept
  334. {
  335. fBuffer = nullptr;
  336. fBufferLen = 0;
  337. fFirstInit = true;
  338. }
  339. // allocate string strBuf if not null
  340. // size > 0 only if strBuf is valid
  341. void _dup(const char* const strBuf, const size_t size = 0)
  342. {
  343. if (strBuf != nullptr)
  344. {
  345. // don't recreate string if contents match
  346. if (fFirstInit || std::strcmp(fBuffer, strBuf) != 0)
  347. {
  348. if (! fFirstInit)
  349. {
  350. CARLA_ASSERT(fBuffer != nullptr);
  351. delete[] fBuffer;
  352. }
  353. fBufferLen = (size > 0) ? size : std::strlen(strBuf);
  354. fBuffer = new char[fBufferLen+1];
  355. std::strcpy(fBuffer, strBuf);
  356. fBuffer[fBufferLen] = '\0';
  357. fFirstInit = false;
  358. }
  359. }
  360. else
  361. {
  362. CARLA_ASSERT(size == 0);
  363. // don't recreate null string
  364. if (fFirstInit || fBufferLen != 0)
  365. {
  366. if (! fFirstInit)
  367. {
  368. CARLA_ASSERT(fBuffer != nullptr);
  369. delete[] fBuffer;
  370. }
  371. fBufferLen = 0;
  372. fBuffer = new char[1];
  373. fBuffer[0] = '\0';
  374. fFirstInit = false;
  375. }
  376. }
  377. }
  378. CARLA_PREVENT_HEAP_ALLOCATION
  379. CARLA_LEAK_DETECTOR(CarlaString)
  380. };
  381. // -----------------------------------------------------------------------
  382. static inline
  383. CarlaString operator+(const CarlaString& strBefore, const char* const strBufAfter)
  384. {
  385. const char* const strBufBefore = (const char*)strBefore;
  386. const size_t newBufSize = strBefore.length() + ((strBufAfter != nullptr) ? std::strlen(strBufAfter) : 0) + 1;
  387. char newBuf[newBufSize];
  388. std::strcpy(newBuf, strBufBefore);
  389. std::strcat(newBuf, strBufAfter);
  390. return CarlaString(newBuf);
  391. }
  392. static inline
  393. CarlaString operator+(const char* const strBufBefore, const CarlaString& strAfter)
  394. {
  395. const char* const strBufAfter = (const char*)strAfter;
  396. const size_t newBufSize = ((strBufBefore != nullptr) ? std::strlen(strBufBefore) : 0) + strAfter.length() + 1;
  397. char newBuf[newBufSize];
  398. std::strcpy(newBuf, strBufBefore);
  399. std::strcat(newBuf, strBufAfter);
  400. return CarlaString(newBuf);
  401. }
  402. // -----------------------------------------------------------------------
  403. #endif // CARLA_STRING_HPP_INCLUDED