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) 2018, 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
38 #include "base/source/fbuffer.h"
39 #include "base/source/fstring.h"
40 #include <stdlib.h>
41
42 namespace Steinberg {
43
44 //-------------------------------------------------------------------------------------
Buffer()45 Buffer::Buffer ()
46 : buffer (0)
47 , memSize (0)
48 , fillSize (0)
49 , delta (defaultDelta)
50 {}
51
52 //-------------------------------------------------------------------------------------
Buffer(uint32 s,uint8 initVal)53 Buffer::Buffer (uint32 s, uint8 initVal)
54 : buffer (0)
55 , memSize (s)
56 , fillSize (0)
57 , delta (defaultDelta)
58 {
59 if (memSize == 0)
60 return;
61 buffer = (int8*)::malloc (memSize);
62 if (buffer)
63 memset (buffer, initVal, memSize);
64 else
65 memSize = 0;
66 }
67
68 //-------------------------------------------------------------------------------------
Buffer(uint32 s)69 Buffer::Buffer (uint32 s)
70 : buffer (0)
71 , memSize (s)
72 , fillSize (0)
73 , delta (defaultDelta)
74 {
75 if (memSize == 0)
76 return;
77 buffer = (int8*)::malloc (memSize);
78 if (!buffer)
79 memSize = 0;
80 }
81
82 //-------------------------------------------------------------------------------------
Buffer(const void * b,uint32 s)83 Buffer::Buffer (const void* b , uint32 s)
84 : buffer (0)
85 , memSize (s)
86 , fillSize (s)
87 , delta (defaultDelta)
88 {
89 if (memSize == 0)
90 return;
91 buffer = (int8*)::malloc (memSize);
92 if (buffer)
93 memcpy (buffer, b, memSize);
94 else
95 {
96 memSize = 0;
97 fillSize = 0;
98 }
99 }
100
101 //-------------------------------------------------------------------------------------
Buffer(const Buffer & bufferR)102 Buffer::Buffer (const Buffer& bufferR)
103 : buffer (0)
104 , memSize (bufferR.memSize)
105 , fillSize (bufferR.fillSize)
106 , delta (bufferR.delta)
107 {
108 if (memSize == 0)
109 return;
110
111 buffer = (int8*)::malloc (memSize);
112 if (buffer)
113 memcpy (buffer, bufferR.buffer, memSize);
114 else
115 memSize = 0;
116 }
117
118 //-------------------------------------------------------------------------------------
~Buffer()119 Buffer::~Buffer ()
120 {
121 if (buffer)
122 ::free (buffer);
123 buffer = 0;
124 }
125
126 //-------------------------------------------------------------------------------------
operator =(const Buffer & b2)127 void Buffer::operator = (const Buffer& b2)
128 {
129 if (&b2 != this)
130 {
131 setSize (b2.memSize);
132 if (b2.memSize > 0 && buffer)
133 memcpy (buffer, b2.buffer, b2.memSize);
134 fillSize = b2.fillSize;
135 delta = b2.delta;
136 }
137 }
138
139 //-------------------------------------------------------------------------------------
operator ==(const Buffer & b2) const140 bool Buffer::operator == (const Buffer& b2)const
141 {
142 if (&b2 == this)
143 return true;
144 if (b2.getSize () != getSize ())
145 return false;
146 return memcmp (this->int8Ptr (), b2.int8Ptr (), getSize ()) == 0 ? true : false;
147 }
148
149 //-------------------------------------------------------------------------------------
get(void * b,uint32 size)150 uint32 Buffer::get (void* b, uint32 size)
151 {
152 uint32 maxGet = memSize - fillSize;
153 if (size > maxGet)
154 size = maxGet;
155 if (size > 0)
156 memcpy (b, buffer + fillSize, size);
157 fillSize += size;
158 return size;
159 }
160
161 //-------------------------------------------------------------------------------------
put(char16 c)162 bool Buffer::put (char16 c)
163 {
164 return put ((const void*)&c, sizeof (c));
165 }
166
167 //-------------------------------------------------------------------------------------
put(uint8 byte)168 bool Buffer::put (uint8 byte)
169 {
170 if (grow (fillSize + 1) == false)
171 return false;
172
173 buffer [fillSize++] = byte;
174 return true;
175 }
176
177 //-------------------------------------------------------------------------------------
put(char c)178 bool Buffer::put (char c)
179 {
180 if (grow (fillSize + 1) == false)
181 return false;
182
183 buffer [fillSize++] = c;
184 return true;
185 }
186
187 //-------------------------------------------------------------------------------------
put(const void * toPut,uint32 s)188 bool Buffer::put (const void* toPut, uint32 s)
189 {
190 if (!toPut)
191 return false;
192
193 if (grow (fillSize + s) == false)
194 return false;
195
196 memcpy (buffer + fillSize, toPut, s);
197 fillSize += s;
198 return true;
199 }
200
201 //-------------------------------------------------------------------------------------
put(const String & str)202 bool Buffer::put (const String& str)
203 {
204 return put ((const void*)str.text () , (str.length () + 1) * sizeof (tchar));
205 }
206
207 //-------------------------------------------------------------------------------------
appendString8(const char8 * s)208 bool Buffer::appendString8 (const char8* s)
209 {
210 if (!s)
211 return false;
212
213 uint32 len = (uint32) strlen (s);
214 return put (s, len);
215 }
216
217 //-------------------------------------------------------------------------------------
appendString16(const char16 * s)218 bool Buffer::appendString16 (const char16* s)
219 {
220 if (!s)
221 return false;
222 ConstString str (s);
223 uint32 len = (uint32) str.length () * sizeof (char16);
224 return put (s, len);
225 }
226
227 //-------------------------------------------------------------------------------------
prependString8(const char8 * s)228 bool Buffer::prependString8 (const char8* s)
229 {
230 if (!s)
231 return false;
232
233 uint32 len = (uint32) strlen (s);
234
235 if (len > 0)
236 {
237 shiftStart (len);
238 memcpy (buffer, s, len);
239 return true;
240 }
241 return false;
242 }
243
244 //-------------------------------------------------------------------------------------
prependString16(const char16 * s)245 bool Buffer::prependString16 (const char16* s)
246 {
247 if (!s)
248 return false;
249
250 ConstString str (s);
251 uint32 len = (uint32) str.length () * sizeof (char16);
252
253 if (len > 0)
254 {
255 shiftStart (len);
256 memcpy (buffer, s, len);
257 return true;
258 }
259 return false;
260 }
261
262 //-------------------------------------------------------------------------------------
prependString8(char8 c)263 bool Buffer::prependString8 (char8 c)
264 {
265 shiftStart (sizeof (char));
266 char* b = (char*)buffer;
267 b [0] = c;
268 return true;
269 }
270
271 //-------------------------------------------------------------------------------------
prependString16(char16 c)272 bool Buffer::prependString16 (char16 c)
273 {
274 shiftStart (sizeof (char16));
275 char16* b = (char16*)buffer;
276 b [0] = c;
277 return true;
278 }
279
280 //-------------------------------------------------------------------------------------
copy(uint32 from,uint32 to,uint32 bytes)281 bool Buffer::copy (uint32 from, uint32 to, uint32 bytes)
282 {
283 if (from + bytes > memSize || bytes == 0)
284 return false;
285
286 if (to + bytes > memSize)
287 setSize (to + bytes);
288
289 if (from + bytes > to && from < to)
290 { // overlap
291 Buffer tmp (buffer + from, bytes);
292 memcpy (buffer + to, tmp, bytes);
293 }
294 else
295 memcpy (buffer + to, buffer + from, bytes);
296 return true;
297 }
298
299 //-------------------------------------------------------------------------------------
makeHexString(String & result)300 bool Buffer::makeHexString (String& result)
301 {
302 unsigned char* data = uint8Ptr ();
303 uint32 bytes = getSize ();
304
305 if (data == 0 || bytes == 0)
306 return false;
307
308 char8* stringBuffer = (char8*)malloc ((bytes * 2) + 1);
309 if (!stringBuffer)
310 return false;
311
312 int32 count = 0;
313 while (bytes > 0)
314 {
315 unsigned char t1 = ((*data) >> 4) & 0x0F;
316 unsigned char t2 = (*data) & 0x0F;
317 if (t1 < 10)
318 t1 += '0';
319 else
320 t1 = t1 - 10 + 'A';
321 if (t2 < 10)
322 t2 += '0';
323 else
324 t2 = t2 - 10 + 'A';
325
326 stringBuffer [count++] = t1;
327 stringBuffer [count++] = t2;
328 data++;
329 bytes--;
330 }
331 stringBuffer [count] = 0;
332
333 result.take ((void*)stringBuffer, false);
334 return true;
335 }
336
337 //-------------------------------------------------------------------------------------
fromHexString(const char8 * string)338 bool Buffer::fromHexString (const char8* string)
339 {
340 flush ();
341 if (string == 0)
342 return false;
343
344 int32 len = strlen8 (string);
345 if (len == 0 || ((len & 1) == 1)/*odd number*/ )
346 return false;
347
348 setSize (len / 2);
349 unsigned char* data = uint8Ptr ();
350
351 bool upper = true;
352 int32 count = 0;
353 while (count < len)
354 {
355 char c = string [count];
356
357 unsigned char d = 0;
358 if (c >= '0' && c <= '9') d += c - '0';
359 else if (c >= 'A' && c <= 'F') d += c - 'A' + 10;
360 else if (c >= 'a' && c <= 'f') d += c - 'a' + 10;
361 else return false; // no hex string
362
363 if (upper)
364 data [count >> 1] = d << 4;
365 else
366 data [count >> 1] += d;
367
368 upper = !upper;
369 count++;
370 }
371 setFillSize (len / 2);
372 return true;
373 }
374
375 //------------------------------------------------------------------------
set(uint8 value)376 void Buffer::set (uint8 value)
377 {
378 if (buffer)
379 memset (buffer, value, memSize);
380 }
381
382 //-------------------------------------------------------------------------------------
setFillSize(uint32 c)383 bool Buffer::setFillSize (uint32 c)
384 {
385 if (c <= memSize)
386 {
387 fillSize = c;
388 return true;
389 }
390 return false;
391 }
392
393 //-------------------------------------------------------------------------------------
truncateToFillSize()394 bool Buffer::truncateToFillSize ()
395 {
396 if (fillSize < memSize)
397 setSize (fillSize);
398
399 return true;
400 }
401
402 //-------------------------------------------------------------------------------------
grow(uint32 newSize)403 bool Buffer::grow (uint32 newSize)
404 {
405 if (newSize > memSize)
406 {
407 if (delta == 0)
408 delta = defaultDelta;
409 uint32 s = ((newSize + delta - 1) / delta) * delta;
410 return setSize (s);
411 }
412 return true;
413 }
414
415 //------------------------------------------------------------------------
shiftAt(uint32 position,int32 amount)416 void Buffer::shiftAt (uint32 position, int32 amount)
417 {
418 if (amount > 0)
419 {
420 if (grow (fillSize + amount))
421 {
422 if (position < fillSize)
423 memmove (buffer + amount + position, buffer + position, fillSize - position);
424
425 fillSize += amount;
426 }
427 }
428 else if (amount < 0 && fillSize > 0)
429 {
430 uint32 toRemove = -amount;
431
432 if (toRemove < fillSize)
433 {
434 if (position < fillSize)
435 memmove (buffer + position, buffer + toRemove + position, fillSize - position - toRemove);
436 fillSize -= toRemove;
437 }
438 }
439 }
440
441 //-------------------------------------------------------------------------------------
move(int32 amount,uint8 initVal)442 void Buffer::move (int32 amount, uint8 initVal)
443 {
444 if (memSize == 0)
445 return;
446
447 if (amount > 0)
448 {
449 if ((uint32)amount < memSize)
450 {
451 memmove (buffer + amount, buffer, memSize - amount);
452 memset (buffer, initVal, amount);
453 }
454 else
455 memset (buffer, initVal, memSize);
456 }
457 else
458 {
459 uint32 toRemove = -amount;
460 if (toRemove < memSize)
461 {
462 memmove (buffer, buffer + toRemove, memSize - toRemove);
463 memset (buffer + memSize - toRemove, initVal, toRemove);
464 }
465 else
466 memset (buffer, initVal, memSize);
467 }
468 }
469
470 //-------------------------------------------------------------------------------------
setSize(uint32 newSize)471 bool Buffer::setSize (uint32 newSize)
472 {
473 if (memSize != newSize)
474 {
475 if (buffer)
476 {
477 if (newSize > 0)
478 {
479 int8* newBuffer = (int8*) ::realloc (buffer, newSize);
480 if (newBuffer == 0)
481 {
482 newBuffer = (int8*)::malloc (newSize);
483 if (newBuffer)
484 {
485 uint32 tmp = newSize;
486 if (tmp > memSize)
487 tmp = memSize;
488 memcpy (newBuffer, buffer, tmp);
489 ::free (buffer);
490 buffer = newBuffer;
491 }
492 else
493 {
494 ::free (buffer);
495 buffer = 0;
496 }
497 }
498 else
499 buffer = newBuffer;
500 }
501 else
502 {
503 ::free (buffer);
504 buffer = 0;
505 }
506 }
507 else
508 buffer = (int8*)::malloc (newSize);
509
510 if (newSize > 0 && !buffer)
511 memSize = 0;
512 else
513 memSize = newSize;
514 if (fillSize > memSize)
515 fillSize = memSize;
516 }
517
518 return (newSize > 0) == (buffer != 0);
519 }
520
521 //-------------------------------------------------------------------------------------
fillup(uint8 value)522 void Buffer::fillup (uint8 value)
523 {
524 if (getFree () > 0)
525 memset (buffer + fillSize, value, getFree ());
526 }
527
528 //-------------------------------------------------------------------------------------
operator +(uint32 i)529 int8* Buffer::operator + (uint32 i)
530 {
531 if (i < memSize)
532 return buffer + i;
533 else
534 {
535 static int8 eof;
536 eof = 0;
537 return &eof;
538 }
539 }
540
541 //-------------------------------------------------------------------------------------
swap(int16 swapSize)542 bool Buffer::swap (int16 swapSize)
543 {
544 return swap (buffer, memSize, swapSize);
545 }
546
547 //-------------------------------------------------------------------------------------
swap(void * buffer,uint32 bufferSize,int16 swapSize)548 bool Buffer::swap (void* buffer, uint32 bufferSize, int16 swapSize)
549 {
550 if (swapSize != kSwap16 && swapSize != kSwap32 && swapSize != kSwap64)
551 return false;
552
553 if (swapSize == kSwap16)
554 {
555 for (uint32 count = 0 ; count < bufferSize ; count += 2)
556 {
557 SWAP_16 ( * (((int16*)buffer) + count) );
558 }
559 }
560 else if (swapSize == kSwap32)
561 {
562 for (uint32 count = 0 ; count < bufferSize ; count += 4)
563 {
564 SWAP_32 ( * (((int32*)buffer) + count) );
565 }
566 }
567 else if (swapSize == kSwap64)
568 {
569 for (uint32 count = 0 ; count < bufferSize ; count += 8)
570 {
571 SWAP_64 ( * (((int64*)buffer) + count) );
572 }
573 }
574
575 return true;
576 }
577
578 //-------------------------------------------------------------------------------------
take(Buffer & from)579 void Buffer::take (Buffer& from)
580 {
581 setSize (0);
582 memSize = from.memSize;
583 fillSize = from.fillSize;
584 buffer = from.buffer;
585 from.buffer = 0;
586 from.memSize = 0;
587 from.fillSize = 0;
588 }
589
590 //-------------------------------------------------------------------------------------
pass()591 int8* Buffer::pass ()
592 {
593 int8* res = buffer;
594 buffer = 0;
595 memSize = 0;
596 fillSize = 0;
597 return res;
598 }
599
600 //-------------------------------------------------------------------------------------
toWideString(int32 sourceCodePage)601 bool Buffer::toWideString (int32 sourceCodePage)
602 {
603 if (getFillSize () > 0)
604 {
605 if (str8 () [getFillSize () - 1] != 0) // multiByteToWideString only works with 0-terminated strings
606 endString8 ();
607
608 Buffer dest (getFillSize () * sizeof (char16));
609 int32 result = String::multiByteToWideString (dest.str16 (), buffer, dest.getFree () / sizeof (char16), sourceCodePage);
610 if (result > 0)
611 {
612 dest.setFillSize ((result - 1) * sizeof (char16));
613 take (dest);
614 return true;
615 }
616 return false;
617 }
618 return true;
619 }
620
621 //-------------------------------------------------------------------------------------
toMultibyteString(int32 destCodePage)622 bool Buffer::toMultibyteString (int32 destCodePage)
623 {
624 if (getFillSize () > 0)
625 {
626 int32 textLength = getFillSize () / sizeof (char16); // wideStringToMultiByte only works with 0-terminated strings
627 if (str16 () [textLength - 1] != 0)
628 endString16 ();
629
630 Buffer dest (getFillSize ());
631 int32 result = String::wideStringToMultiByte (dest.str8 (), str16 (), dest.getFree (), destCodePage);
632 if (result > 0)
633 {
634 dest.setFillSize (result - 1);
635 take (dest);
636 return true;
637 }
638 return false;
639 }
640 return true;
641 }
642
643 //------------------------------------------------------------------------
644 } // namespace Steinberg
645