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.

501 lines
11KB

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