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.

446 lines
9.9KB

  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 GPL.txt file
  16. */
  17. #ifndef __CARLA_STRING_HPP__
  18. #define __CARLA_STRING_HPP__
  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] = { '\0' };
  45. std::snprintf(strBuf, 0xff, "%d", value);
  46. _init();
  47. _dup(strBuf);
  48. }
  49. explicit CarlaString(const unsigned int value, const bool hexadecimal = false)
  50. {
  51. char strBuf[0xff] = { '\0' };
  52. std::snprintf(strBuf, 0xff, hexadecimal ? "0x%x" : "%u", value);
  53. _init();
  54. _dup(strBuf);
  55. }
  56. explicit CarlaString(const long int value)
  57. {
  58. char strBuf[0xff] = { '\0' };
  59. std::snprintf(strBuf, 0xff, "%ld", value);
  60. _init();
  61. _dup(strBuf);
  62. }
  63. explicit CarlaString(const unsigned long int value, const bool hexadecimal = false)
  64. {
  65. char strBuf[0xff] = { '\0' };
  66. std::snprintf(strBuf, 0xff, hexadecimal ? "0x%lx" : "%lu", value);
  67. _init();
  68. _dup(strBuf);
  69. }
  70. explicit CarlaString(const float value)
  71. {
  72. char strBuf[0xff] = { '\0' };
  73. std::snprintf(strBuf, 0xff, "%f", value);
  74. _init();
  75. _dup(strBuf);
  76. }
  77. explicit CarlaString(const double value)
  78. {
  79. char strBuf[0xff] = { '\0' };
  80. std::snprintf(strBuf, 0xff, "%g", value);
  81. _init();
  82. _dup(strBuf);
  83. }
  84. // ---------------------------------------------
  85. // non-explicit constructor
  86. CarlaString(const CarlaString& str)
  87. {
  88. _init();
  89. _dup(str.buffer);
  90. }
  91. // ---------------------------------------------
  92. // destructor
  93. ~CarlaString()
  94. {
  95. CARLA_ASSERT(buffer != nullptr);
  96. delete[] buffer;
  97. }
  98. // ---------------------------------------------
  99. // public methods
  100. size_t length() const
  101. {
  102. return bufferLen;
  103. }
  104. bool isEmpty() const
  105. {
  106. return (bufferLen == 0);
  107. }
  108. bool isNotEmpty() const
  109. {
  110. return (bufferLen != 0);
  111. }
  112. #ifdef __USE_GNU
  113. bool contains(const char* const strBuf, const bool ignoreCase = false) const
  114. {
  115. if (strBuf == nullptr)
  116. return false;
  117. if (ignoreCase)
  118. return (strcasestr(buffer, strBuf) != nullptr);
  119. else
  120. return (std::strstr(buffer, strBuf) != nullptr);
  121. }
  122. bool contains(const CarlaString& str, const bool ignoreCase = false) const
  123. {
  124. return contains(str.buffer, ignoreCase);
  125. }
  126. #else
  127. bool contains(const char* const strBuf) const
  128. {
  129. if (strBuf == nullptr)
  130. return false;
  131. return (std::strstr(buffer, strBuf) != nullptr);
  132. }
  133. bool contains(const CarlaString& str) const
  134. {
  135. return contains(str.buffer);
  136. }
  137. #endif
  138. bool isDigit(const size_t pos) const
  139. {
  140. if (pos >= bufferLen)
  141. return false;
  142. return (buffer[pos] >= '0' && buffer[pos] <= '9');
  143. }
  144. void clear()
  145. {
  146. truncate(0);
  147. }
  148. size_t find(const char c) const
  149. {
  150. for (size_t i=0; i < bufferLen; ++i)
  151. {
  152. if (buffer[i] == c)
  153. return i;
  154. }
  155. return 0;
  156. }
  157. size_t rfind(const char c) const
  158. {
  159. size_t pos = 0;
  160. for (size_t i=0; i < bufferLen; ++i)
  161. {
  162. if (buffer[i] == c)
  163. pos = i;
  164. }
  165. return pos;
  166. }
  167. void replace(const char before, const char after)
  168. {
  169. if (after == '\0')
  170. return;
  171. for (size_t i=0; i < bufferLen; ++i)
  172. {
  173. if (buffer[i] == before)
  174. buffer[i] = after;
  175. else if (buffer[i] == '\0')
  176. break;
  177. }
  178. }
  179. void truncate(const size_t n)
  180. {
  181. if (n >= bufferLen)
  182. return;
  183. for (size_t i=n; i < bufferLen; ++i)
  184. buffer[i] = '\0';
  185. bufferLen = n;
  186. }
  187. void toBasic()
  188. {
  189. for (size_t i=0; i < bufferLen; ++i)
  190. {
  191. if (buffer[i] >= '0' && buffer[i] <= '9')
  192. continue;
  193. if (buffer[i] >= 'A' && buffer[i] <= 'Z')
  194. continue;
  195. if (buffer[i] >= 'a' && buffer[i] <= 'z')
  196. continue;
  197. if (buffer[i] == '_')
  198. continue;
  199. buffer[i] = '_';
  200. }
  201. }
  202. void toLower()
  203. {
  204. static const char kCharDiff = 'a' - 'A';
  205. for (size_t i=0; i < bufferLen; ++i)
  206. {
  207. if (buffer[i] >= 'A' && buffer[i] <= 'Z')
  208. buffer[i] += kCharDiff;
  209. }
  210. }
  211. void toUpper()
  212. {
  213. static const char kCharDiff = 'a' - 'A';
  214. for (size_t i=0; i < bufferLen; ++i)
  215. {
  216. if (buffer[i] >= 'a' && buffer[i] <= 'z')
  217. buffer[i] -= kCharDiff;
  218. }
  219. }
  220. // ---------------------------------------------
  221. // public operators
  222. operator const char*() const
  223. {
  224. return buffer;
  225. }
  226. char& operator[](const size_t pos)
  227. {
  228. return buffer[pos];
  229. }
  230. bool operator==(const char* const strBuf) const
  231. {
  232. return (strBuf != nullptr && std::strcmp(buffer, strBuf) == 0);
  233. }
  234. bool operator==(const CarlaString& str) const
  235. {
  236. return operator==(str.buffer);
  237. }
  238. bool operator!=(const char* const strBuf) const
  239. {
  240. return !operator==(strBuf);
  241. }
  242. bool operator!=(const CarlaString& str) const
  243. {
  244. return !operator==(str.buffer);
  245. }
  246. CarlaString& operator=(const char* const strBuf)
  247. {
  248. _dup(strBuf);
  249. return *this;
  250. }
  251. CarlaString& operator=(const CarlaString& str)
  252. {
  253. return operator=(str.buffer);
  254. }
  255. CarlaString& operator+=(const char* const strBuf)
  256. {
  257. const size_t newBufSize = bufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
  258. char newBuf[newBufSize];
  259. std::strcpy(newBuf, buffer);
  260. std::strcat(newBuf, strBuf);
  261. _dup(newBuf, newBufSize-1);
  262. return *this;
  263. }
  264. CarlaString& operator+=(const CarlaString& str)
  265. {
  266. return operator+=(str.buffer);
  267. }
  268. CarlaString operator+(const char* const strBuf)
  269. {
  270. const size_t newBufSize = bufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
  271. char newBuf[newBufSize];
  272. std::strcpy(newBuf, buffer);
  273. std::strcat(newBuf, strBuf);
  274. return CarlaString(newBuf);
  275. }
  276. CarlaString operator+(const CarlaString& str)
  277. {
  278. return operator+(str.buffer);
  279. }
  280. // ---------------------------------------------
  281. private:
  282. char* buffer;
  283. size_t bufferLen;
  284. bool firstInit;
  285. void _init()
  286. {
  287. buffer = nullptr;
  288. bufferLen = 0;
  289. firstInit = true;
  290. }
  291. // allocate string strBuf if not null
  292. // size > 0 only if strBuf is valid
  293. void _dup(const char* const strBuf, const size_t size = 0)
  294. {
  295. if (strBuf != nullptr)
  296. {
  297. // don't recreate string if contents match
  298. if (firstInit || std::strcmp(buffer, strBuf) != 0)
  299. {
  300. if (! firstInit)
  301. {
  302. CARLA_ASSERT(buffer != nullptr);
  303. delete[] buffer;
  304. }
  305. bufferLen = (size > 0) ? size : std::strlen(strBuf);
  306. buffer = new char[bufferLen+1];
  307. std::strcpy(buffer, strBuf);
  308. buffer[bufferLen] = '\0';
  309. firstInit = false;
  310. }
  311. }
  312. else
  313. {
  314. CARLA_ASSERT(size == 0);
  315. // don't recreate null string
  316. if (firstInit || bufferLen != 0)
  317. {
  318. if (! firstInit)
  319. {
  320. CARLA_ASSERT(buffer != nullptr);
  321. delete[] buffer;
  322. }
  323. bufferLen = 0;
  324. buffer = new char[1];
  325. buffer[0] = '\0';
  326. firstInit = false;
  327. }
  328. }
  329. }
  330. CARLA_LEAK_DETECTOR(CarlaString)
  331. CARLA_PREVENT_HEAP_ALLOCATION
  332. };
  333. static inline
  334. CarlaString operator+(const CarlaString& strBefore, const char* const strBufAfter)
  335. {
  336. const char* const strBufBefore = (const char*)strBefore;
  337. const size_t newBufSize = strBefore.length() + ((strBufAfter != nullptr) ? std::strlen(strBufAfter) : 0) + 1;
  338. char newBuf[newBufSize];
  339. std::strcpy(newBuf, strBufBefore);
  340. std::strcat(newBuf, strBufAfter);
  341. return CarlaString(newBuf);
  342. }
  343. static inline
  344. CarlaString operator+(const char* const strBufBefore, const CarlaString& strAfter)
  345. {
  346. const char* const strBufAfter = (const char*)strAfter;
  347. const size_t newBufSize = ((strBufBefore != nullptr) ? std::strlen(strBufBefore) : 0) + strAfter.length() + 1;
  348. char newBuf[newBufSize];
  349. std::strcpy(newBuf, strBufBefore);
  350. std::strcat(newBuf, strBufAfter);
  351. return CarlaString(newBuf);
  352. }
  353. // -------------------------------------------------
  354. #endif // __CARLA_UTILS_HPP__