|
- //------------------------------------------------------------------------
- // Project : SDK Base
- // Version : 1.0
- //
- // Category : Helpers
- // Filename : base/source/fbuffer.cpp
- // Created by : Steinberg, 2008
- // Description :
- //
- //-----------------------------------------------------------------------------
- // LICENSE
- // (c) 2019, Steinberg Media Technologies GmbH, All Rights Reserved
- //-----------------------------------------------------------------------------
- // Redistribution and use in source and binary forms, with or without modification,
- // are permitted provided that the following conditions are met:
- //
- // * Redistributions of source code must retain the above copyright notice,
- // this list of conditions and the following disclaimer.
- // * Redistributions in binary form must reproduce the above copyright notice,
- // this list of conditions and the following disclaimer in the documentation
- // and/or other materials provided with the distribution.
- // * Neither the name of the Steinberg Media Technologies nor the names of its
- // contributors may be used to endorse or promote products derived from this
- // software without specific prior written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- // IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- // OF THE POSSIBILITY OF SUCH DAMAGE.
- //-----------------------------------------------------------------------------
-
- #include "base/source/fbuffer.h"
- #include "base/source/fstring.h"
- #include <stdlib.h>
-
- namespace Steinberg {
-
- //-------------------------------------------------------------------------------------
- Buffer::Buffer ()
- : buffer (nullptr)
- , memSize (0)
- , fillSize (0)
- , delta (defaultDelta)
- {}
-
- //-------------------------------------------------------------------------------------
- Buffer::Buffer (uint32 s, uint8 initVal)
- : buffer (nullptr)
- , memSize (s)
- , fillSize (0)
- , delta (defaultDelta)
- {
- if (memSize == 0)
- return;
- buffer = (int8*)::malloc (memSize);
- if (buffer)
- memset (buffer, initVal, memSize);
- else
- memSize = 0;
- }
-
- //-------------------------------------------------------------------------------------
- Buffer::Buffer (uint32 s)
- : buffer (nullptr)
- , memSize (s)
- , fillSize (0)
- , delta (defaultDelta)
- {
- if (memSize == 0)
- return;
- buffer = (int8*)::malloc (memSize);
- if (!buffer)
- memSize = 0;
- }
-
- //-------------------------------------------------------------------------------------
- Buffer::Buffer (const void* b , uint32 s)
- : buffer (nullptr)
- , memSize (s)
- , fillSize (s)
- , delta (defaultDelta)
- {
- if (memSize == 0)
- return;
- buffer = (int8*)::malloc (memSize);
- if (buffer)
- memcpy (buffer, b, memSize);
- else
- {
- memSize = 0;
- fillSize = 0;
- }
- }
-
- //-------------------------------------------------------------------------------------
- Buffer::Buffer (const Buffer& bufferR)
- : buffer (nullptr)
- , memSize (bufferR.memSize)
- , fillSize (bufferR.fillSize)
- , delta (bufferR.delta)
- {
- if (memSize == 0)
- return;
-
- buffer = (int8*)::malloc (memSize);
- if (buffer)
- memcpy (buffer, bufferR.buffer, memSize);
- else
- memSize = 0;
- }
-
- //-------------------------------------------------------------------------------------
- Buffer::~Buffer ()
- {
- if (buffer)
- ::free (buffer);
- buffer = nullptr;
- }
-
- //-------------------------------------------------------------------------------------
- void Buffer::operator = (const Buffer& b2)
- {
- if (&b2 != this)
- {
- setSize (b2.memSize);
- if (b2.memSize > 0 && buffer)
- memcpy (buffer, b2.buffer, b2.memSize);
- fillSize = b2.fillSize;
- delta = b2.delta;
- }
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::operator == (const Buffer& b2)const
- {
- if (&b2 == this)
- return true;
- if (b2.getSize () != getSize ())
- return false;
- return memcmp (this->int8Ptr (), b2.int8Ptr (), getSize ()) == 0 ? true : false;
- }
-
- //-------------------------------------------------------------------------------------
- uint32 Buffer::get (void* b, uint32 size)
- {
- uint32 maxGet = memSize - fillSize;
- if (size > maxGet)
- size = maxGet;
- if (size > 0)
- memcpy (b, buffer + fillSize, size);
- fillSize += size;
- return size;
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::put (char16 c)
- {
- return put ((const void*)&c, sizeof (c));
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::put (uint8 byte)
- {
- if (grow (fillSize + 1) == false)
- return false;
-
- buffer [fillSize++] = byte;
- return true;
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::put (char c)
- {
- if (grow (fillSize + 1) == false)
- return false;
-
- buffer [fillSize++] = c;
- return true;
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::put (const void* toPut, uint32 s)
- {
- if (!toPut)
- return false;
-
- if (grow (fillSize + s) == false)
- return false;
-
- memcpy (buffer + fillSize, toPut, s);
- fillSize += s;
- return true;
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::put (const String& str)
- {
- return put ((const void*)str.text () , (str.length () + 1) * sizeof (tchar));
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::appendString8 (const char8* s)
- {
- if (!s)
- return false;
-
- uint32 len = (uint32) strlen (s);
- return put (s, len);
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::appendString16 (const char16* s)
- {
- if (!s)
- return false;
- ConstString str (s);
- uint32 len = (uint32) str.length () * sizeof (char16);
- return put (s, len);
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::prependString8 (const char8* s)
- {
- if (!s)
- return false;
-
- uint32 len = (uint32) strlen (s);
-
- if (len > 0)
- {
- shiftStart (len);
- memcpy (buffer, s, len);
- return true;
- }
- return false;
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::prependString16 (const char16* s)
- {
- if (!s)
- return false;
-
- ConstString str (s);
- uint32 len = (uint32) str.length () * sizeof (char16);
-
- if (len > 0)
- {
- shiftStart (len);
- memcpy (buffer, s, len);
- return true;
- }
- return false;
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::prependString8 (char8 c)
- {
- shiftStart (sizeof (char));
- char* b = (char*)buffer;
- b [0] = c;
- return true;
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::prependString16 (char16 c)
- {
- shiftStart (sizeof (char16));
- char16* b = (char16*)buffer;
- b [0] = c;
- return true;
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::copy (uint32 from, uint32 to, uint32 bytes)
- {
- if (from + bytes > memSize || bytes == 0)
- return false;
-
- if (to + bytes > memSize)
- setSize (to + bytes);
-
- if (from + bytes > to && from < to)
- { // overlap
- Buffer tmp (buffer + from, bytes);
- memcpy (buffer + to, tmp, bytes);
- }
- else
- memcpy (buffer + to, buffer + from, bytes);
- return true;
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::makeHexString (String& result)
- {
- unsigned char* data = uint8Ptr ();
- uint32 bytes = getSize ();
-
- if (data == nullptr || bytes == 0)
- return false;
-
- char8* stringBuffer = (char8*)malloc ((bytes * 2) + 1);
- if (!stringBuffer)
- return false;
-
- int32 count = 0;
- while (bytes > 0)
- {
- unsigned char t1 = ((*data) >> 4) & 0x0F;
- unsigned char t2 = (*data) & 0x0F;
- if (t1 < 10)
- t1 += '0';
- else
- t1 = t1 - 10 + 'A';
- if (t2 < 10)
- t2 += '0';
- else
- t2 = t2 - 10 + 'A';
-
- stringBuffer [count++] = t1;
- stringBuffer [count++] = t2;
- data++;
- bytes--;
- }
- stringBuffer [count] = 0;
-
- result.take ((void*)stringBuffer, false);
- return true;
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::fromHexString (const char8* string)
- {
- flush ();
- if (string == nullptr)
- return false;
-
- int32 len = strlen8 (string);
- if (len == 0 || ((len & 1) == 1)/*odd number*/ )
- return false;
-
- setSize (len / 2);
- unsigned char* data = uint8Ptr ();
-
- bool upper = true;
- int32 count = 0;
- while (count < len)
- {
- char c = string [count];
-
- unsigned char d = 0;
- if (c >= '0' && c <= '9') d += c - '0';
- else if (c >= 'A' && c <= 'F') d += c - 'A' + 10;
- else if (c >= 'a' && c <= 'f') d += c - 'a' + 10;
- else return false; // no hex string
-
- if (upper)
- data [count >> 1] = d << 4;
- else
- data [count >> 1] += d;
-
- upper = !upper;
- count++;
- }
- setFillSize (len / 2);
- return true;
- }
-
- //------------------------------------------------------------------------
- void Buffer::set (uint8 value)
- {
- if (buffer)
- memset (buffer, value, memSize);
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::setFillSize (uint32 c)
- {
- if (c <= memSize)
- {
- fillSize = c;
- return true;
- }
- return false;
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::truncateToFillSize ()
- {
- if (fillSize < memSize)
- setSize (fillSize);
-
- return true;
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::grow (uint32 newSize)
- {
- if (newSize > memSize)
- {
- if (delta == 0)
- delta = defaultDelta;
- uint32 s = ((newSize + delta - 1) / delta) * delta;
- return setSize (s);
- }
- return true;
- }
-
- //------------------------------------------------------------------------
- void Buffer::shiftAt (uint32 position, int32 amount)
- {
- if (amount > 0)
- {
- if (grow (fillSize + amount))
- {
- if (position < fillSize)
- memmove (buffer + amount + position, buffer + position, fillSize - position);
-
- fillSize += amount;
- }
- }
- else if (amount < 0 && fillSize > 0)
- {
- uint32 toRemove = -amount;
-
- if (toRemove < fillSize)
- {
- if (position < fillSize)
- memmove (buffer + position, buffer + toRemove + position, fillSize - position - toRemove);
- fillSize -= toRemove;
- }
- }
- }
-
- //-------------------------------------------------------------------------------------
- void Buffer::move (int32 amount, uint8 initVal)
- {
- if (memSize == 0)
- return;
-
- if (amount > 0)
- {
- if ((uint32)amount < memSize)
- {
- memmove (buffer + amount, buffer, memSize - amount);
- memset (buffer, initVal, amount);
- }
- else
- memset (buffer, initVal, memSize);
- }
- else
- {
- uint32 toRemove = -amount;
- if (toRemove < memSize)
- {
- memmove (buffer, buffer + toRemove, memSize - toRemove);
- memset (buffer + memSize - toRemove, initVal, toRemove);
- }
- else
- memset (buffer, initVal, memSize);
- }
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::setSize (uint32 newSize)
- {
- if (memSize != newSize)
- {
- if (buffer)
- {
- if (newSize > 0)
- {
- int8* newBuffer = (int8*) ::realloc (buffer, newSize);
- if (newBuffer == nullptr)
- {
- newBuffer = (int8*)::malloc (newSize);
- if (newBuffer)
- {
- uint32 tmp = newSize;
- if (tmp > memSize)
- tmp = memSize;
- memcpy (newBuffer, buffer, tmp);
- ::free (buffer);
- buffer = newBuffer;
- }
- else
- {
- ::free (buffer);
- buffer = nullptr;
- }
- }
- else
- buffer = newBuffer;
- }
- else
- {
- ::free (buffer);
- buffer = nullptr;
- }
- }
- else
- buffer = (int8*)::malloc (newSize);
-
- if (newSize > 0 && !buffer)
- memSize = 0;
- else
- memSize = newSize;
- if (fillSize > memSize)
- fillSize = memSize;
- }
-
- return (newSize > 0) == (buffer != nullptr);
- }
-
- //-------------------------------------------------------------------------------------
- void Buffer::fillup (uint8 value)
- {
- if (getFree () > 0)
- memset (buffer + fillSize, value, getFree ());
- }
-
- //-------------------------------------------------------------------------------------
- int8* Buffer::operator + (uint32 i)
- {
- if (i < memSize)
- return buffer + i;
- else
- {
- static int8 eof;
- eof = 0;
- return &eof;
- }
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::swap (int16 swapSize)
- {
- return swap (buffer, memSize, swapSize);
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::swap (void* buffer, uint32 bufferSize, int16 swapSize)
- {
- if (swapSize != kSwap16 && swapSize != kSwap32 && swapSize != kSwap64)
- return false;
-
- if (swapSize == kSwap16)
- {
- for (uint32 count = 0 ; count < bufferSize ; count += 2)
- {
- SWAP_16 ( * (((int16*)buffer) + count) );
- }
- }
- else if (swapSize == kSwap32)
- {
- for (uint32 count = 0 ; count < bufferSize ; count += 4)
- {
- SWAP_32 ( * (((int32*)buffer) + count) );
- }
- }
- else if (swapSize == kSwap64)
- {
- for (uint32 count = 0 ; count < bufferSize ; count += 8)
- {
- SWAP_64 ( * (((int64*)buffer) + count) );
- }
- }
-
- return true;
- }
-
- //-------------------------------------------------------------------------------------
- void Buffer::take (Buffer& from)
- {
- setSize (0);
- memSize = from.memSize;
- fillSize = from.fillSize;
- buffer = from.buffer;
- from.buffer = nullptr;
- from.memSize = 0;
- from.fillSize = 0;
- }
-
- //-------------------------------------------------------------------------------------
- int8* Buffer::pass ()
- {
- int8* res = buffer;
- buffer = nullptr;
- memSize = 0;
- fillSize = 0;
- return res;
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::toWideString (int32 sourceCodePage)
- {
- if (getFillSize () > 0)
- {
- if (str8 () [getFillSize () - 1] != 0) // multiByteToWideString only works with 0-terminated strings
- endString8 ();
-
- Buffer dest (getFillSize () * sizeof (char16));
- int32 result = String::multiByteToWideString (dest.str16 (), buffer, dest.getFree () / sizeof (char16), sourceCodePage);
- if (result > 0)
- {
- dest.setFillSize ((result - 1) * sizeof (char16));
- take (dest);
- return true;
- }
- return false;
- }
- return true;
- }
-
- //-------------------------------------------------------------------------------------
- bool Buffer::toMultibyteString (int32 destCodePage)
- {
- if (getFillSize () > 0)
- {
- int32 textLength = getFillSize () / sizeof (char16); // wideStringToMultiByte only works with 0-terminated strings
- if (str16 () [textLength - 1] != 0)
- endString16 ();
-
- Buffer dest (getFillSize ());
- int32 result = String::wideStringToMultiByte (dest.str8 (), str16 (), dest.getFree (), destCodePage);
- if (result > 0)
- {
- dest.setFillSize (result - 1);
- take (dest);
- return true;
- }
- return false;
- }
- return true;
- }
-
- //------------------------------------------------------------------------
- } // namespace Steinberg
|