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.

413 lines
9.4KB

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