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.

645 lines
15KB

  1. //------------------------------------------------------------------------
  2. // Project : SDK Base
  3. // Version : 1.0
  4. //
  5. // Category : Helpers
  6. // Filename : base/source/fbuffer.cpp
  7. // Created by : Steinberg, 2008
  8. // Description :
  9. //
  10. //-----------------------------------------------------------------------------
  11. // LICENSE
  12. // (c) 2019, Steinberg Media Technologies GmbH, All Rights Reserved
  13. //-----------------------------------------------------------------------------
  14. // Redistribution and use in source and binary forms, with or without modification,
  15. // are permitted provided that the following conditions are met:
  16. //
  17. // * Redistributions of source code must retain the above copyright notice,
  18. // this list of conditions and the following disclaimer.
  19. // * Redistributions in binary form must reproduce the above copyright notice,
  20. // this list of conditions and the following disclaimer in the documentation
  21. // and/or other materials provided with the distribution.
  22. // * Neither the name of the Steinberg Media Technologies nor the names of its
  23. // contributors may be used to endorse or promote products derived from this
  24. // software without specific prior written permission.
  25. //
  26. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  27. // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  28. // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  29. // IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  30. // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  31. // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  32. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  33. // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  34. // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  35. // OF THE POSSIBILITY OF SUCH DAMAGE.
  36. //-----------------------------------------------------------------------------
  37. #include "base/source/fbuffer.h"
  38. #include "base/source/fstring.h"
  39. #include <stdlib.h>
  40. namespace Steinberg {
  41. //-------------------------------------------------------------------------------------
  42. Buffer::Buffer ()
  43. : buffer (nullptr)
  44. , memSize (0)
  45. , fillSize (0)
  46. , delta (defaultDelta)
  47. {}
  48. //-------------------------------------------------------------------------------------
  49. Buffer::Buffer (uint32 s, uint8 initVal)
  50. : buffer (nullptr)
  51. , memSize (s)
  52. , fillSize (0)
  53. , delta (defaultDelta)
  54. {
  55. if (memSize == 0)
  56. return;
  57. buffer = (int8*)::malloc (memSize);
  58. if (buffer)
  59. memset (buffer, initVal, memSize);
  60. else
  61. memSize = 0;
  62. }
  63. //-------------------------------------------------------------------------------------
  64. Buffer::Buffer (uint32 s)
  65. : buffer (nullptr)
  66. , memSize (s)
  67. , fillSize (0)
  68. , delta (defaultDelta)
  69. {
  70. if (memSize == 0)
  71. return;
  72. buffer = (int8*)::malloc (memSize);
  73. if (!buffer)
  74. memSize = 0;
  75. }
  76. //-------------------------------------------------------------------------------------
  77. Buffer::Buffer (const void* b , uint32 s)
  78. : buffer (nullptr)
  79. , memSize (s)
  80. , fillSize (s)
  81. , delta (defaultDelta)
  82. {
  83. if (memSize == 0)
  84. return;
  85. buffer = (int8*)::malloc (memSize);
  86. if (buffer)
  87. memcpy (buffer, b, memSize);
  88. else
  89. {
  90. memSize = 0;
  91. fillSize = 0;
  92. }
  93. }
  94. //-------------------------------------------------------------------------------------
  95. Buffer::Buffer (const Buffer& bufferR)
  96. : buffer (nullptr)
  97. , memSize (bufferR.memSize)
  98. , fillSize (bufferR.fillSize)
  99. , delta (bufferR.delta)
  100. {
  101. if (memSize == 0)
  102. return;
  103. buffer = (int8*)::malloc (memSize);
  104. if (buffer)
  105. memcpy (buffer, bufferR.buffer, memSize);
  106. else
  107. memSize = 0;
  108. }
  109. //-------------------------------------------------------------------------------------
  110. Buffer::~Buffer ()
  111. {
  112. if (buffer)
  113. ::free (buffer);
  114. buffer = nullptr;
  115. }
  116. //-------------------------------------------------------------------------------------
  117. void Buffer::operator = (const Buffer& b2)
  118. {
  119. if (&b2 != this)
  120. {
  121. setSize (b2.memSize);
  122. if (b2.memSize > 0 && buffer)
  123. memcpy (buffer, b2.buffer, b2.memSize);
  124. fillSize = b2.fillSize;
  125. delta = b2.delta;
  126. }
  127. }
  128. //-------------------------------------------------------------------------------------
  129. bool Buffer::operator == (const Buffer& b2)const
  130. {
  131. if (&b2 == this)
  132. return true;
  133. if (b2.getSize () != getSize ())
  134. return false;
  135. return memcmp (this->int8Ptr (), b2.int8Ptr (), getSize ()) == 0 ? true : false;
  136. }
  137. //-------------------------------------------------------------------------------------
  138. uint32 Buffer::get (void* b, uint32 size)
  139. {
  140. uint32 maxGet = memSize - fillSize;
  141. if (size > maxGet)
  142. size = maxGet;
  143. if (size > 0)
  144. memcpy (b, buffer + fillSize, size);
  145. fillSize += size;
  146. return size;
  147. }
  148. //-------------------------------------------------------------------------------------
  149. bool Buffer::put (char16 c)
  150. {
  151. return put ((const void*)&c, sizeof (c));
  152. }
  153. //-------------------------------------------------------------------------------------
  154. bool Buffer::put (uint8 byte)
  155. {
  156. if (grow (fillSize + 1) == false)
  157. return false;
  158. buffer [fillSize++] = byte;
  159. return true;
  160. }
  161. //-------------------------------------------------------------------------------------
  162. bool Buffer::put (char c)
  163. {
  164. if (grow (fillSize + 1) == false)
  165. return false;
  166. buffer [fillSize++] = c;
  167. return true;
  168. }
  169. //-------------------------------------------------------------------------------------
  170. bool Buffer::put (const void* toPut, uint32 s)
  171. {
  172. if (!toPut)
  173. return false;
  174. if (grow (fillSize + s) == false)
  175. return false;
  176. memcpy (buffer + fillSize, toPut, s);
  177. fillSize += s;
  178. return true;
  179. }
  180. //-------------------------------------------------------------------------------------
  181. bool Buffer::put (const String& str)
  182. {
  183. return put ((const void*)str.text () , (str.length () + 1) * sizeof (tchar));
  184. }
  185. //-------------------------------------------------------------------------------------
  186. bool Buffer::appendString8 (const char8* s)
  187. {
  188. if (!s)
  189. return false;
  190. uint32 len = (uint32) strlen (s);
  191. return put (s, len);
  192. }
  193. //-------------------------------------------------------------------------------------
  194. bool Buffer::appendString16 (const char16* s)
  195. {
  196. if (!s)
  197. return false;
  198. ConstString str (s);
  199. uint32 len = (uint32) str.length () * sizeof (char16);
  200. return put (s, len);
  201. }
  202. //-------------------------------------------------------------------------------------
  203. bool Buffer::prependString8 (const char8* s)
  204. {
  205. if (!s)
  206. return false;
  207. uint32 len = (uint32) strlen (s);
  208. if (len > 0)
  209. {
  210. shiftStart (len);
  211. memcpy (buffer, s, len);
  212. return true;
  213. }
  214. return false;
  215. }
  216. //-------------------------------------------------------------------------------------
  217. bool Buffer::prependString16 (const char16* s)
  218. {
  219. if (!s)
  220. return false;
  221. ConstString str (s);
  222. uint32 len = (uint32) str.length () * sizeof (char16);
  223. if (len > 0)
  224. {
  225. shiftStart (len);
  226. memcpy (buffer, s, len);
  227. return true;
  228. }
  229. return false;
  230. }
  231. //-------------------------------------------------------------------------------------
  232. bool Buffer::prependString8 (char8 c)
  233. {
  234. shiftStart (sizeof (char));
  235. char* b = (char*)buffer;
  236. b [0] = c;
  237. return true;
  238. }
  239. //-------------------------------------------------------------------------------------
  240. bool Buffer::prependString16 (char16 c)
  241. {
  242. shiftStart (sizeof (char16));
  243. char16* b = (char16*)buffer;
  244. b [0] = c;
  245. return true;
  246. }
  247. //-------------------------------------------------------------------------------------
  248. bool Buffer::copy (uint32 from, uint32 to, uint32 bytes)
  249. {
  250. if (from + bytes > memSize || bytes == 0)
  251. return false;
  252. if (to + bytes > memSize)
  253. setSize (to + bytes);
  254. if (from + bytes > to && from < to)
  255. { // overlap
  256. Buffer tmp (buffer + from, bytes);
  257. memcpy (buffer + to, tmp, bytes);
  258. }
  259. else
  260. memcpy (buffer + to, buffer + from, bytes);
  261. return true;
  262. }
  263. //-------------------------------------------------------------------------------------
  264. bool Buffer::makeHexString (String& result)
  265. {
  266. unsigned char* data = uint8Ptr ();
  267. uint32 bytes = getSize ();
  268. if (data == nullptr || bytes == 0)
  269. return false;
  270. char8* stringBuffer = (char8*)malloc ((bytes * 2) + 1);
  271. if (!stringBuffer)
  272. return false;
  273. int32 count = 0;
  274. while (bytes > 0)
  275. {
  276. unsigned char t1 = ((*data) >> 4) & 0x0F;
  277. unsigned char t2 = (*data) & 0x0F;
  278. if (t1 < 10)
  279. t1 += '0';
  280. else
  281. t1 = t1 - 10 + 'A';
  282. if (t2 < 10)
  283. t2 += '0';
  284. else
  285. t2 = t2 - 10 + 'A';
  286. stringBuffer [count++] = t1;
  287. stringBuffer [count++] = t2;
  288. data++;
  289. bytes--;
  290. }
  291. stringBuffer [count] = 0;
  292. result.take ((void*)stringBuffer, false);
  293. return true;
  294. }
  295. //-------------------------------------------------------------------------------------
  296. bool Buffer::fromHexString (const char8* string)
  297. {
  298. flush ();
  299. if (string == nullptr)
  300. return false;
  301. int32 len = strlen8 (string);
  302. if (len == 0 || ((len & 1) == 1)/*odd number*/ )
  303. return false;
  304. setSize (len / 2);
  305. unsigned char* data = uint8Ptr ();
  306. bool upper = true;
  307. int32 count = 0;
  308. while (count < len)
  309. {
  310. char c = string [count];
  311. unsigned char d = 0;
  312. if (c >= '0' && c <= '9') d += c - '0';
  313. else if (c >= 'A' && c <= 'F') d += c - 'A' + 10;
  314. else if (c >= 'a' && c <= 'f') d += c - 'a' + 10;
  315. else return false; // no hex string
  316. if (upper)
  317. data [count >> 1] = d << 4;
  318. else
  319. data [count >> 1] += d;
  320. upper = !upper;
  321. count++;
  322. }
  323. setFillSize (len / 2);
  324. return true;
  325. }
  326. //------------------------------------------------------------------------
  327. void Buffer::set (uint8 value)
  328. {
  329. if (buffer)
  330. memset (buffer, value, memSize);
  331. }
  332. //-------------------------------------------------------------------------------------
  333. bool Buffer::setFillSize (uint32 c)
  334. {
  335. if (c <= memSize)
  336. {
  337. fillSize = c;
  338. return true;
  339. }
  340. return false;
  341. }
  342. //-------------------------------------------------------------------------------------
  343. bool Buffer::truncateToFillSize ()
  344. {
  345. if (fillSize < memSize)
  346. setSize (fillSize);
  347. return true;
  348. }
  349. //-------------------------------------------------------------------------------------
  350. bool Buffer::grow (uint32 newSize)
  351. {
  352. if (newSize > memSize)
  353. {
  354. if (delta == 0)
  355. delta = defaultDelta;
  356. uint32 s = ((newSize + delta - 1) / delta) * delta;
  357. return setSize (s);
  358. }
  359. return true;
  360. }
  361. //------------------------------------------------------------------------
  362. void Buffer::shiftAt (uint32 position, int32 amount)
  363. {
  364. if (amount > 0)
  365. {
  366. if (grow (fillSize + amount))
  367. {
  368. if (position < fillSize)
  369. memmove (buffer + amount + position, buffer + position, fillSize - position);
  370. fillSize += amount;
  371. }
  372. }
  373. else if (amount < 0 && fillSize > 0)
  374. {
  375. uint32 toRemove = -amount;
  376. if (toRemove < fillSize)
  377. {
  378. if (position < fillSize)
  379. memmove (buffer + position, buffer + toRemove + position, fillSize - position - toRemove);
  380. fillSize -= toRemove;
  381. }
  382. }
  383. }
  384. //-------------------------------------------------------------------------------------
  385. void Buffer::move (int32 amount, uint8 initVal)
  386. {
  387. if (memSize == 0)
  388. return;
  389. if (amount > 0)
  390. {
  391. if ((uint32)amount < memSize)
  392. {
  393. memmove (buffer + amount, buffer, memSize - amount);
  394. memset (buffer, initVal, amount);
  395. }
  396. else
  397. memset (buffer, initVal, memSize);
  398. }
  399. else
  400. {
  401. uint32 toRemove = -amount;
  402. if (toRemove < memSize)
  403. {
  404. memmove (buffer, buffer + toRemove, memSize - toRemove);
  405. memset (buffer + memSize - toRemove, initVal, toRemove);
  406. }
  407. else
  408. memset (buffer, initVal, memSize);
  409. }
  410. }
  411. //-------------------------------------------------------------------------------------
  412. bool Buffer::setSize (uint32 newSize)
  413. {
  414. if (memSize != newSize)
  415. {
  416. if (buffer)
  417. {
  418. if (newSize > 0)
  419. {
  420. int8* newBuffer = (int8*) ::realloc (buffer, newSize);
  421. if (newBuffer == nullptr)
  422. {
  423. newBuffer = (int8*)::malloc (newSize);
  424. if (newBuffer)
  425. {
  426. uint32 tmp = newSize;
  427. if (tmp > memSize)
  428. tmp = memSize;
  429. memcpy (newBuffer, buffer, tmp);
  430. ::free (buffer);
  431. buffer = newBuffer;
  432. }
  433. else
  434. {
  435. ::free (buffer);
  436. buffer = nullptr;
  437. }
  438. }
  439. else
  440. buffer = newBuffer;
  441. }
  442. else
  443. {
  444. ::free (buffer);
  445. buffer = nullptr;
  446. }
  447. }
  448. else
  449. buffer = (int8*)::malloc (newSize);
  450. if (newSize > 0 && !buffer)
  451. memSize = 0;
  452. else
  453. memSize = newSize;
  454. if (fillSize > memSize)
  455. fillSize = memSize;
  456. }
  457. return (newSize > 0) == (buffer != nullptr);
  458. }
  459. //-------------------------------------------------------------------------------------
  460. void Buffer::fillup (uint8 value)
  461. {
  462. if (getFree () > 0)
  463. memset (buffer + fillSize, value, getFree ());
  464. }
  465. //-------------------------------------------------------------------------------------
  466. int8* Buffer::operator + (uint32 i)
  467. {
  468. if (i < memSize)
  469. return buffer + i;
  470. else
  471. {
  472. static int8 eof;
  473. eof = 0;
  474. return &eof;
  475. }
  476. }
  477. //-------------------------------------------------------------------------------------
  478. bool Buffer::swap (int16 swapSize)
  479. {
  480. return swap (buffer, memSize, swapSize);
  481. }
  482. //-------------------------------------------------------------------------------------
  483. bool Buffer::swap (void* buffer, uint32 bufferSize, int16 swapSize)
  484. {
  485. if (swapSize != kSwap16 && swapSize != kSwap32 && swapSize != kSwap64)
  486. return false;
  487. if (swapSize == kSwap16)
  488. {
  489. for (uint32 count = 0 ; count < bufferSize ; count += 2)
  490. {
  491. SWAP_16 ( * (((int16*)buffer) + count) );
  492. }
  493. }
  494. else if (swapSize == kSwap32)
  495. {
  496. for (uint32 count = 0 ; count < bufferSize ; count += 4)
  497. {
  498. SWAP_32 ( * (((int32*)buffer) + count) );
  499. }
  500. }
  501. else if (swapSize == kSwap64)
  502. {
  503. for (uint32 count = 0 ; count < bufferSize ; count += 8)
  504. {
  505. SWAP_64 ( * (((int64*)buffer) + count) );
  506. }
  507. }
  508. return true;
  509. }
  510. //-------------------------------------------------------------------------------------
  511. void Buffer::take (Buffer& from)
  512. {
  513. setSize (0);
  514. memSize = from.memSize;
  515. fillSize = from.fillSize;
  516. buffer = from.buffer;
  517. from.buffer = nullptr;
  518. from.memSize = 0;
  519. from.fillSize = 0;
  520. }
  521. //-------------------------------------------------------------------------------------
  522. int8* Buffer::pass ()
  523. {
  524. int8* res = buffer;
  525. buffer = nullptr;
  526. memSize = 0;
  527. fillSize = 0;
  528. return res;
  529. }
  530. //-------------------------------------------------------------------------------------
  531. bool Buffer::toWideString (int32 sourceCodePage)
  532. {
  533. if (getFillSize () > 0)
  534. {
  535. if (str8 () [getFillSize () - 1] != 0) // multiByteToWideString only works with 0-terminated strings
  536. endString8 ();
  537. Buffer dest (getFillSize () * sizeof (char16));
  538. int32 result = String::multiByteToWideString (dest.str16 (), buffer, dest.getFree () / sizeof (char16), sourceCodePage);
  539. if (result > 0)
  540. {
  541. dest.setFillSize ((result - 1) * sizeof (char16));
  542. take (dest);
  543. return true;
  544. }
  545. return false;
  546. }
  547. return true;
  548. }
  549. //-------------------------------------------------------------------------------------
  550. bool Buffer::toMultibyteString (int32 destCodePage)
  551. {
  552. if (getFillSize () > 0)
  553. {
  554. int32 textLength = getFillSize () / sizeof (char16); // wideStringToMultiByte only works with 0-terminated strings
  555. if (str16 () [textLength - 1] != 0)
  556. endString16 ();
  557. Buffer dest (getFillSize ());
  558. int32 result = String::wideStringToMultiByte (dest.str8 (), str16 (), dest.getFree (), destCodePage);
  559. if (result > 0)
  560. {
  561. dest.setFillSize (result - 1);
  562. take (dest);
  563. return true;
  564. }
  565. return false;
  566. }
  567. return true;
  568. }
  569. //------------------------------------------------------------------------
  570. } // namespace Steinberg