1 //------------------------------------------------------------------------
2 // Project     : SDK Base
3 // Version     : 1.0
4 //
5 // Category    : Helpers
6 // Filename    : base/source/fbuffer.h
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 
38 #pragma once
39 
40 #include "pluginterfaces/base/ftypes.h"
41 #include <cstring>
42 
43 namespace Steinberg {
44 class String;
45 
46 //------------------------------------------------------------------------
47 /** Buffer.
48 @ingroup adt
49 
50 A Buffer is an object-oriented wrapper for a piece of memory.
51 It adds several utility functions, e.g. for managing the size of the Buffer,
52 appending or prepending values or strings to it.
53 Internally it uses the standard memory functions malloc(), free(), etc. */
54 //------------------------------------------------------------------------
55 class Buffer
56 {
57 public:
58 //---------------------------------------------------------------------
59 
60 	/**	Default constructor, allocates no memory at all.
61 	*/
62 	Buffer ();
63 
64 	/**	Constructor - creates a new Buffer with a given size and copies contents from optional memory pointer.
65 	\param[in] b : optional memory pointer with the size of at least the given size
66 	\param[in] size : the size of the new Buffer to be allocated, in bytes.
67 	*/
68 	Buffer (const void* b, uint32 size);
69 
70 	/**	Constructor - creates a new Buffer with a given size and fills it all with a given value.
71 	\param[in] size : the size of the new Buffer to be allocated, in bytes.
72 	\param[in] initVal : the initial value the Buffer will be completely filled with
73 	*/
74 	Buffer (uint32 size, uint8 initVal);
75 
76 	/**	Constructor - creates a new Buffer with a given size.
77 	\param[in] size : the size of the new Buffer to be allocated, in bytes.
78 	*/
79 	Buffer (uint32 size);
80 
81 	/**	Copy constructor - creates a new Buffer from a given Buffer.
82 	\param[in] buff : the Buffer from which all memory will be copied to the new one
83 	*/
84 	Buffer (const Buffer& buff);
85 
86 	/**	Destructor - deallocates the internal memory.
87 	*/
88 	~Buffer ();
89 
90 	/**	Assignment operator - copies contents from a given Buffer and increases the size if necessary.
91 	\param[in] buff : the Buffer from which all memory will be copied
92 	*/
93 	void operator = (const Buffer& buff);
94 
95 	/**	Comparison operator - copies contents from a given Buffer and increases the size if necessary.
96 	\param[in] buff : the Buffer to be compared to
97 	\return true, if the given Buffer's content is equal to this one, else false
98 	*/
99 	bool operator == (const Buffer& buff)const;
100 
getSize()101 	uint32 getSize () const {return memSize;}		///< \return the actual size of the Buffer's memory, in bytes.
102 
103 	/**	Sets a new size for this Buffer, keeping as much content as possible.
104 	\param[in] newSize : the new size for the Buffer, in bytes, newSize maybe zero
105 	\return true, if the new size could be adapted, else false
106 	*/
107 	bool setSize (uint32 newSize);
108 
109 	/**	Increases the Buffer to the next block, block size given by delta.
110 	\param[in] memSize : the new minimum size of the Buffer, newSize maybe zero
111 	\return true, if the Buffer could be grown successfully, else false
112 	*/
113 	bool grow (uint32 memSize);
setMaxSize(uint32 size)114 	bool setMaxSize (uint32 size) {return grow (size);}	///< see \ref grow()
115 
116 	void fillup (uint8 initVal = 0);				///< set from fillSize to end
getFillSize()117 	uint32 getFillSize ()const {return fillSize;}	///< \return the actual fill size
118 	bool setFillSize (uint32 c);					///< sets a new fill size, does not change any memory
flush()119 	inline void flush () {setFillSize (0);}			///< sets fill size to zero
120 	bool truncateToFillSize ();						///< \return always true, truncates the size of the Buffer to the actual fill size
121 
isFull()122 	bool isFull () const { return (fillSize == memSize); }	///< \return true, if all memory is filled up, else false
getFree()123 	uint32 getFree () const { return (memSize - fillSize); }///< \return remaining memory
124 
shiftStart(int32 amount)125 	inline void shiftStart (int32 amount) {return shiftAt (0, amount);} ///< moves all memory by given amount, grows the Buffer if necessary
126 	void shiftAt (uint32 position, int32 amount);						///< moves memory starting at the given position
127 	void move (int32 amount, uint8 initVal = 0);						///< shifts memory at start without growing the buffer, so data is lost and initialized with init val
128 
129 	bool copy (uint32 from, uint32 to, uint32 bytes);	///< copies a number of bytes from one position to another, the size may be adapted
130 	uint32 get (void* b, uint32 size);					///< copy to buffer from fillSize, and shift fillSize
131 
setDelta(uint32 d)132 	void setDelta (uint32 d) {delta = d;}				///< define the block size by which the Buffer grows, see \ref grow()
133 
134 	bool put (uint8);							///< append value at end, grows Buffer if necessary
135 	bool put (char16 c);                        ///< append value at end, grows Buffer if necessary
136 	bool put (char c);							///< append value at end, grows Buffer if necessary
137 	bool put (const void* , uint32 size);		///< append bytes from a given buffer, grows Buffer if necessary
138 	bool put (void* , uint32 size);				///< append bytes from a given buffer, grows Buffer if necessary
139 	bool put (uint8* , uint32 size);			///< append bytes from a given buffer, grows Buffer if necessary
140 	bool put (char8* , uint32 size);			///< append bytes from a given buffer, grows Buffer if necessary
141 	bool put (const uint8* , uint32 size);		///< append bytes from a given buffer, grows Buffer if necessary
142 	bool put (const char8* , uint32 size);		///< append bytes from a given buffer, grows Buffer if necessary
143 	bool put (const String&);					///< append String at end, grows Buffer if necessary
144 
145 	void set (uint8 value);		///< fills complete Buffer with given value
146 
147 	// strings ----------------
148 	bool appendString (const tchar* s);
149 	bool appendString (tchar* s);
appendString(tchar c)150 	bool appendString (tchar c)                   { return put (c); }
151 
152 	bool appendString8 (const char8* s);
153 	bool appendString16 (const char16* s);
154 
appendString8(char8 * s)155 	bool appendString8 (char8* s)                 { return appendString8 ((const char8*)s); }
appendString8(unsigned char * s)156 	bool appendString8 (unsigned char* s)		  { return appendString8 ((const char8*)s); }
appendString8(const unsigned char * s)157 	bool appendString8 (const unsigned char* s)   { return appendString8 ((const char8*)s); }
158 
appendString8(char8 c)159 	bool appendString8 (char8 c)                  { return put ((uint8)c); }
appendString8(unsigned char c)160 	bool appendString8 (unsigned char c)          { return put (c); }
appendString16(char16 c)161 	bool appendString16 (char16 c)                { return put (c); }
appendString16(char16 * s)162 	bool appendString16 (char16* s)               { return appendString16 ((const char16*)s); }
163 
164 	bool prependString (const tchar* s);
165 	bool prependString (tchar* s);
166 	bool prependString (tchar c);
167 
168 	bool prependString8 (const char8* s);
169 	bool prependString16 (const char16* s);
170 
171 	bool prependString8 (char8 c);
prependString8(unsigned char c)172 	bool prependString8 (unsigned char c)         { return prependString8 ((char8)c); }
prependString8(char8 * s)173 	bool prependString8 (char8* s)                { return prependString8 ((const char8*)s); }
prependString8(unsigned char * s)174 	bool prependString8 (unsigned char* s)        { return prependString8((const char8*)s); }
prependString8(const unsigned char * s)175 	bool prependString8 (const unsigned char* s)  { return prependString8 ((const char8*)s); }
176 	bool prependString16 (char16 c);
prependString16(char16 * s)177 	bool prependString16 (char16* s)              { return prependString16 ((const char16*)s); }
178 
179 	bool operator+= (const char* s)               { return appendString8 (s); }
180 	bool operator+= (char c)                      { return appendString8 (c); }
181 	bool operator+= (const char16* s)             { return appendString16 (s); }
182 	bool operator+= (char16 c)                    { return appendString16 (c); }
183 
184 	bool operator= (const char* s)                { flush (); return appendString8 (s); }
185 	bool operator= (const char16* s)              { flush (); return appendString16 (s); }
186 	bool operator= (char8 c)                      { flush (); return appendString8 (c); }
187 	bool operator= (char16 c)                     { flush (); return appendString16 (c); }
188 
endString()189 	void endString () {put (tchar (0));}
endString8()190 	void endString8 () {put (char8 (0));}
endString16()191 	void endString16 () {put (char16 (0));}
192 
193 	bool makeHexString (String& result);
194 	bool fromHexString (const char8* string);
195 
196 	// conversion
197 	operator void* () const { return (void*)buffer; }				///< conversion
str()198 	inline tchar*   str ()   const {return (tchar*)buffer;}			///< conversion
str8()199 	inline char8*   str8 ()   const {return (char8*)buffer;}		///< conversion
str16()200 	inline char16*  str16 ()   const {return (char16*)buffer;}		///< conversion
int8Ptr()201 	inline int8*   int8Ptr ()   const {return (int8*)buffer;}		///< conversion
uint8Ptr()202 	inline uint8*  uint8Ptr ()  const {return (uint8*)buffer; }		///< conversion
int16Ptr()203 	inline int16*  int16Ptr ()  const {return (int16*)buffer; }		///< conversion
uint16Ptr()204     inline uint16* uint16Ptr () const {return (uint16*)buffer; }	///< conversion
int32Ptr()205 	inline int32*  int32Ptr ()  const {return (int32*)buffer; }		///< conversion
uint32Ptr()206 	inline uint32* uint32Ptr () const {return (uint32*)buffer; }	///< conversion
floatPtr()207 	inline float*  floatPtr ()  const {return (float*)buffer; }		///< conversion
doublePtr()208 	inline double* doublePtr () const {return (double*)buffer; }	///< conversion
wcharPtr()209 	inline char16*  wcharPtr ()  const {return (char16*)buffer;}	///< conversion
210 
211 	int8* operator + (uint32 i);	///< \return the internal Buffer's address plus the given offset i, zero if offset is out of range
212 
213 	int32 operator ! ()  { return buffer == 0; }
214 
215 	enum swapSize
216 	{
217 		kSwap16 = 2,
218 		kSwap32 = 4,
219 		kSwap64 = 8
220 	};
221 	bool swap (int16 swapSize);											///< swap all bytes of this Buffer by the given swapSize
222 	static bool swap (void* buffer, uint32 bufferSize, int16 swapSize);	///< utility, swap given number of bytes in given buffer by the given swapSize
223 
224 	void take (Buffer& from);	///< takes another Buffer's memory, frees the current Buffer's memory
225 	int8* pass ();				///< pass the current Buffer's memory
226 
227 	/**	Converts a Buffer's content to UTF-16 from a given multi-byte code page, Buffer must contain char8 of given encoding.
228 		\param[in] sourceCodePage : the actual code page of the Buffer's content
229 		\return true, if the conversion was successful, else false
230 	*/
231 	virtual bool toWideString (int32 sourceCodePage); // Buffer contains char8 of given encoding -> utf16
232 
233 	/**	Converts a Buffer's content from UTF-16 to a given multi-byte code page, Buffer must contain UTF-16 encoded characters.
234 		\param[in] destCodePage : the desired code page to convert the Buffer's content to
235 		\return true, if the conversion was successful, else false
236 	*/
237 	virtual bool toMultibyteString (int32 destCodePage); // Buffer contains utf16 -> char8 of given encoding
238 
239 //------------------------------------------------------------------------
240 protected:
241 	static const uint32 defaultDelta = 0x1000; // 0x1000
242 
243 	int8* buffer;
244 	uint32 memSize;
245 	uint32 fillSize;
246 	uint32 delta;
247 };
248 
put(void * p,uint32 count)249 inline bool Buffer::put (void* p, uint32 count)     { return put ((const void*)p , count ); }
put(uint8 * p,uint32 count)250 inline bool Buffer::put (uint8 * p, uint32 count)   { return put ((const void*)p , count ); }
put(char8 * p,uint32 count)251 inline bool Buffer::put (char8* p, uint32 count)    { return put ((const void*)p , count ); }
put(const uint8 * p,uint32 count)252 inline bool Buffer::put (const uint8* p, uint32 count) { return put ((const void*)p , count ); }
put(const char8 * p,uint32 count)253 inline bool Buffer::put (const char8* p, uint32 count) { return put ((const void*)p , count ); }
254 
255 //------------------------------------------------------------------------
appendString(const tchar * s)256 inline bool Buffer::appendString (const tchar* s)
257 {
258 #ifdef UNICODE
259 	return appendString16 (s);
260 #else
261 	return appendString8 (s);
262 #endif
263 }
264 
265 //------------------------------------------------------------------------
appendString(tchar * s)266 inline bool Buffer::appendString (tchar* s)
267 {
268 #ifdef UNICODE
269 	return appendString16 (s);
270 #else
271 	return appendString8 (s);
272 #endif
273 }
274 
275 //------------------------------------------------------------------------
prependString(const tchar * s)276 inline bool Buffer::prependString (const tchar* s)
277 {
278 #ifdef UNICODE
279 	return prependString16 (s);
280 #else
281 	return prependString8 (s);
282 #endif
283 }
284 
285 //------------------------------------------------------------------------
prependString(tchar * s)286 inline bool Buffer::prependString (tchar* s)
287 {
288 #ifdef UNICODE
289 	return prependString16 (s);
290 #else
291 	return prependString8 (s);
292 #endif
293 }
294 
295 //------------------------------------------------------------------------
prependString(tchar c)296 inline bool Buffer::prependString (tchar c)
297 {
298 #ifdef UNICODE
299 	return prependString16 (c);
300 #else
301 	return prependString8 (c);
302 #endif
303 }
304 
305 //------------------------------------------------------------------------
306 } // namespace Steinberg
307