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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  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. bool contains(const char* const strBuf, const bool ignoreCase = false) const
  120. {
  121. CARLA_SAFE_ASSERT_RETURN(strBuf != nullptr, false);
  122. if (ignoreCase)
  123. {
  124. #ifdef __USE_GNU
  125. return (strcasestr(fBuffer, strBuf) != nullptr);
  126. #else
  127. CarlaString tmp1(fBuffer), tmp2(strBuf);
  128. tmp1.toLower();
  129. tmp2.toLower();
  130. return (std::strstr((const char*)tmp1, (const char*)tmp2) != nullptr);
  131. #endif
  132. }
  133. return (std::strstr(fBuffer, strBuf) != nullptr);
  134. }
  135. bool contains(const CarlaString& str, const bool ignoreCase = false) const
  136. {
  137. return contains(str.fBuffer, ignoreCase);
  138. }
  139. bool isDigit(const size_t pos) const noexcept
  140. {
  141. CARLA_SAFE_ASSERT_RETURN(pos < fBufferLen, false);
  142. return (fBuffer[pos] >= '0' && fBuffer[pos] <= '9');
  143. }
  144. bool startsWith(const char c) const
  145. {
  146. CARLA_SAFE_ASSERT_RETURN(c != '\0', false);
  147. return (fBufferLen > 0 && fBuffer[0] == c);
  148. }
  149. bool startsWith(const char* const prefix) const
  150. {
  151. CARLA_SAFE_ASSERT_RETURN(prefix != nullptr, false);
  152. const size_t prefixLen(std::strlen(prefix));
  153. if (fBufferLen < prefixLen)
  154. return false;
  155. return (std::strncmp(fBuffer + (fBufferLen-prefixLen), prefix, prefixLen) == 0);
  156. }
  157. bool endsWith(const char c) const
  158. {
  159. CARLA_SAFE_ASSERT_RETURN(c != '\0', false);
  160. return (fBufferLen > 0 && fBuffer[fBufferLen] == c);
  161. }
  162. bool endsWith(const char* const suffix) const
  163. {
  164. CARLA_SAFE_ASSERT_RETURN(suffix != nullptr, false);
  165. const size_t suffixLen(std::strlen(suffix));
  166. if (fBufferLen < suffixLen)
  167. return false;
  168. return (std::strncmp(fBuffer + (fBufferLen-suffixLen), suffix, suffixLen) == 0);
  169. }
  170. void clear() noexcept
  171. {
  172. truncate(0);
  173. }
  174. size_t find(const char c) const noexcept
  175. {
  176. for (size_t i=0; i < fBufferLen; ++i)
  177. {
  178. if (fBuffer[i] == c)
  179. return i;
  180. }
  181. return 0;
  182. }
  183. size_t rfind(const char c) const noexcept
  184. {
  185. for (size_t i=fBufferLen; i > 0; --i)
  186. {
  187. if (fBuffer[i-1] == c)
  188. return i-1;
  189. }
  190. return 0;
  191. }
  192. size_t rfind(const char* const strBuf) const
  193. {
  194. CARLA_SAFE_ASSERT_RETURN(strBuf != nullptr && strBuf[0] != '\0', fBufferLen);
  195. size_t ret = fBufferLen+1;
  196. const char* tmpBuf = fBuffer;
  197. for (size_t i=0; i < fBufferLen; ++i)
  198. {
  199. if (std::strstr(tmpBuf, strBuf) == nullptr)
  200. break;
  201. --ret;
  202. ++tmpBuf;
  203. }
  204. return (ret > fBufferLen) ? fBufferLen : fBufferLen-ret;
  205. }
  206. void replace(const char before, const char after)
  207. {
  208. CARLA_SAFE_ASSERT_RETURN(before != '\0' && after != '\0',);
  209. for (size_t i=0; i < fBufferLen; ++i)
  210. {
  211. if (fBuffer[i] == before)
  212. fBuffer[i] = after;
  213. else if (fBuffer[i] == '\0')
  214. break;
  215. }
  216. }
  217. void truncate(const size_t n) noexcept
  218. {
  219. if (n >= fBufferLen)
  220. return;
  221. for (size_t i=n; i < fBufferLen; ++i)
  222. fBuffer[i] = '\0';
  223. fBufferLen = n;
  224. }
  225. void toBasic() noexcept
  226. {
  227. for (size_t i=0; i < fBufferLen; ++i)
  228. {
  229. if (fBuffer[i] >= '0' && fBuffer[i] <= '9')
  230. continue;
  231. if (fBuffer[i] >= 'A' && fBuffer[i] <= 'Z')
  232. continue;
  233. if (fBuffer[i] >= 'a' && fBuffer[i] <= 'z')
  234. continue;
  235. if (fBuffer[i] == '_')
  236. continue;
  237. fBuffer[i] = '_';
  238. }
  239. }
  240. void toLower() noexcept
  241. {
  242. #ifndef BUILD_ANSI_TEST
  243. // Using '+=' temporarily converts char into int
  244. static const char kCharDiff('a' - 'A');
  245. for (size_t i=0; i < fBufferLen; ++i)
  246. {
  247. if (fBuffer[i] >= 'A' && fBuffer[i] <= 'Z')
  248. fBuffer[i] += kCharDiff;
  249. }
  250. #endif
  251. }
  252. void toUpper() noexcept
  253. {
  254. #ifndef BUILD_ANSI_TEST
  255. // Using '-=' temporarily converts char into int
  256. static const char kCharDiff('a' - 'A');
  257. for (size_t i=0; i < fBufferLen; ++i)
  258. {
  259. if (fBuffer[i] >= 'a' && fBuffer[i] <= 'z')
  260. fBuffer[i] -= kCharDiff;
  261. }
  262. #endif
  263. }
  264. const char* dup() const
  265. {
  266. return carla_strdup(fBuffer);
  267. }
  268. const char* getBuffer() const
  269. {
  270. return fBuffer;
  271. }
  272. // -------------------------------------------------------------------
  273. // public operators
  274. operator const char*() const noexcept
  275. {
  276. return fBuffer;
  277. }
  278. char& operator[](const size_t pos) const noexcept
  279. {
  280. return fBuffer[pos];
  281. }
  282. bool operator==(const char* const strBuf) const
  283. {
  284. return (strBuf != nullptr && std::strcmp(fBuffer, strBuf) == 0);
  285. }
  286. bool operator==(const CarlaString& str) const
  287. {
  288. return operator==(str.fBuffer);
  289. }
  290. bool operator!=(const char* const strBuf) const
  291. {
  292. return !operator==(strBuf);
  293. }
  294. bool operator!=(const CarlaString& str) const
  295. {
  296. return !operator==(str.fBuffer);
  297. }
  298. CarlaString& operator=(const char* const strBuf)
  299. {
  300. _dup(strBuf);
  301. return *this;
  302. }
  303. CarlaString& operator=(const CarlaString& str)
  304. {
  305. return operator=(str.fBuffer);
  306. }
  307. CarlaString& operator+=(const char* const strBuf)
  308. {
  309. if (strBuf == nullptr)
  310. return *this;
  311. const size_t newBufSize = fBufferLen + std::strlen(strBuf) + 1;
  312. char newBuf[newBufSize];
  313. std::strcpy(newBuf, fBuffer);
  314. std::strcat(newBuf, strBuf);
  315. _dup(newBuf, newBufSize-1);
  316. return *this;
  317. }
  318. CarlaString& operator+=(const CarlaString& str)
  319. {
  320. return operator+=(str.fBuffer);
  321. }
  322. CarlaString operator+(const char* const strBuf)
  323. {
  324. const size_t newBufSize = fBufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
  325. char newBuf[newBufSize];
  326. std::strcpy(newBuf, fBuffer);
  327. if (strBuf != nullptr)
  328. std::strcat(newBuf, strBuf);
  329. return CarlaString(newBuf);
  330. }
  331. CarlaString operator+(const CarlaString& str)
  332. {
  333. return operator+(str.fBuffer);
  334. }
  335. // -------------------------------------------------------------------
  336. private:
  337. char* fBuffer;
  338. size_t fBufferLen;
  339. bool fFirstInit;
  340. void _init() noexcept
  341. {
  342. fBuffer = nullptr;
  343. fBufferLen = 0;
  344. fFirstInit = true;
  345. }
  346. // allocate string strBuf if not null
  347. // size > 0 only if strBuf is valid
  348. void _dup(const char* const strBuf, const size_t size = 0)
  349. {
  350. if (strBuf != nullptr)
  351. {
  352. // don't recreate string if contents match
  353. if (fFirstInit || std::strcmp(fBuffer, strBuf) != 0)
  354. {
  355. if (! fFirstInit)
  356. {
  357. CARLA_ASSERT(fBuffer != nullptr);
  358. delete[] fBuffer;
  359. }
  360. fBufferLen = (size > 0) ? size : std::strlen(strBuf);
  361. fBuffer = new char[fBufferLen+1];
  362. std::strcpy(fBuffer, strBuf);
  363. fBuffer[fBufferLen] = '\0';
  364. fFirstInit = false;
  365. }
  366. }
  367. else
  368. {
  369. CARLA_ASSERT(size == 0);
  370. // don't recreate null string
  371. if (fFirstInit || fBufferLen != 0)
  372. {
  373. if (! fFirstInit)
  374. {
  375. CARLA_ASSERT(fBuffer != nullptr);
  376. delete[] fBuffer;
  377. }
  378. fBufferLen = 0;
  379. fBuffer = new char[1];
  380. fBuffer[0] = '\0';
  381. fFirstInit = false;
  382. }
  383. }
  384. }
  385. CARLA_PREVENT_HEAP_ALLOCATION
  386. CARLA_LEAK_DETECTOR(CarlaString)
  387. };
  388. // -----------------------------------------------------------------------
  389. static inline
  390. CarlaString operator+(const CarlaString& strBefore, const char* const strBufAfter)
  391. {
  392. const char* const strBufBefore = (const char*)strBefore;
  393. const size_t newBufSize = strBefore.length() + ((strBufAfter != nullptr) ? std::strlen(strBufAfter) : 0) + 1;
  394. char newBuf[newBufSize];
  395. std::strcpy(newBuf, strBufBefore);
  396. std::strcat(newBuf, strBufAfter);
  397. return CarlaString(newBuf);
  398. }
  399. static inline
  400. CarlaString operator+(const char* const strBufBefore, const CarlaString& strAfter)
  401. {
  402. const char* const strBufAfter = (const char*)strAfter;
  403. const size_t newBufSize = ((strBufBefore != nullptr) ? std::strlen(strBufBefore) : 0) + strAfter.length() + 1;
  404. char newBuf[newBufSize];
  405. std::strcpy(newBuf, strBufBefore);
  406. std::strcat(newBuf, strBufAfter);
  407. return CarlaString(newBuf);
  408. }
  409. // -----------------------------------------------------------------------
  410. #endif // CARLA_STRING_HPP_INCLUDED