2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
17 class BufferException final
22 explicit BufferException(const char* message_
) : message(message_
) {}
26 * This class is based on the java java.nio.Buffer class however, it
27 * does not implement the 'mark' functionality.
29 * [ the following is borrowed from the javadocs for java.nio.Buffer
30 * where it applies to this class]:
32 * A buffer is a linear, finite sequence of elements of a unspecified types.
33 * Aside from its content, the essential properties of a buffer are its capacity,
34 * limit, and position:
35 * A buffer's capacity is the number of elements it contains. The capacity
36 * of a buffer is never negative and never changes.
38 * A buffer's limit is the index of the first element that should not be
39 * read or written. A buffer's limit is never negative and is never greater
42 * A buffer's position is the index of the next element to be read or written.
43 * A buffer's position is never negative and is never greater than its limit.
47 * The following invariant holds for the mark, position, limit, and capacity values:
49 * 0 <= mark <= position <= limit <= capacity
51 * A newly-created buffer always has a position of zero and a limit set to the
52 * capacity. The initial content of a buffer is, in general, undefined.
55 * Buffer buffer(1024);
56 * buffer.putInt(1).putString("hello there").putLongLong( ((long long)2)^40 );
58 * std::cout << "buffer contents:" << buffer.getInt() << ", ";
59 * std::cout << buffer.getCharPointerDirect() << ", ";
60 * std::cout << buffer.getLongLong() << std::endl;
62 * Note: the 'gets' are sensitive to the order-of-operations. Therefore, while
63 * the above is correct, it would be wrong to chain the output as follows:
65 * std::cout << "buffer contents:" << buffer.getInt() << ", " << std::cout
66 * << buffer.getCharPointerDirect() << ", " << buffer.getLongLong()
69 * This would result in the get's executing from right to left and therefore would
70 * produce totally erroneous results. This is also a problem when the values are
71 * passed to a method as in:
73 * printf("buffer contents: %d, \"%s\", %ll\n", buffer.getInt(),
74 * buffer.getCharPointerDirect(), buffer.getLongLong());
76 * This would also produce erroneous results as they get's will be evaluated
77 * from right to left in the parameter list of printf.
81 std::shared_ptr
<unsigned char> bufferRef
;
82 unsigned char* buffer
= nullptr;
87 inline void check(size_t count
) const
89 if ((mposition
+ count
) > mlimit
)
90 throw BufferException("Buffer buffer overflow: Cannot add more data to the Buffer's buffer.");
95 * Construct an uninitialized buffer instance, perhaps as an lvalue.
97 inline Buffer() { clear(); }
100 * Construct a buffer given an externally managed memory buffer.
101 * The ownership of the buffer is assumed to be the code that called
102 * this constructor, therefore the Buffer destructor will not free it.
104 * The newly constructed buffer is considered empty and is ready to
105 * have data written into it.
107 * If you want to read from the buffer you just created, you can use:
109 * Buffer b = Buffer(buf,bufSize).forward(bufSize).flip();
111 inline Buffer(void* buffer_
, size_t bufferSize
) : buffer((unsigned char*)buffer_
), mcapacity(bufferSize
)
117 * Construct a buffer buffer using the size buffer provided. The
118 * buffer will be internally managed and potentially shared with
119 * other Buffer instances. It will be freed upon destruction of
120 * the last Buffer that references it.
122 inline explicit Buffer(size_t bufferSize
) : buffer(bufferSize
? new unsigned char[bufferSize
] : NULL
), mcapacity(bufferSize
)
125 bufferRef
.reset(buffer
, std::default_delete
<unsigned char[]>());
129 * Copy another buffer. This is a "shallow copy" and therefore
130 * shares the underlying data buffer with the Buffer it is a copy
131 * of. Changes made to the data through this buffer will be seen
132 * in the source buffer and vice/vrs. However, each buffer maintains
135 inline Buffer(const Buffer
& buf
) = default;
138 * Copy another buffer. This is a "shallow copy" and therefore
139 * shares the underlying data buffer with the Buffer it is a copy
140 * of. Changes made to the data through this buffer will be seen
141 * in the source buffer and vice/vrs. However, each buffer maintains
144 inline Buffer
& operator=(const Buffer
& buf
)
147 bufferRef
= buf
.bufferRef
;
148 mcapacity
= buf
.mcapacity
;
153 inline Buffer
& allocate(size_t bufferSize
)
155 buffer
= bufferSize
? new unsigned char[bufferSize
] : NULL
;
156 bufferRef
.reset(buffer
, std::default_delete
<unsigned char[]>());
157 mcapacity
= bufferSize
;
163 * Flips this buffer. The limit is set to the current position
164 * and then the position is set to zero.
166 * After a sequence of channel-read or put operations, invoke this
167 * method to prepare for a sequence of channel-write or relative
168 * get operations. For example:
170 * buf.put(magic); // Prepend header
171 * in.read(buf); // Read data into rest of buffer
172 * buf.flip(); // Flip buffer
173 * out.write(buf); // Write header + data to channel
175 * This is used to prepare the Buffer for reading from after
176 * it has been written to.
178 inline Buffer
& flip() { mlimit
= mposition
; mposition
= 0; return *this; }
181 *Clears this buffer. The position is set to zero, the limit
182 * is set to the capacity.
184 * Invoke this method before using a sequence of channel-read
185 * or put operations to fill this buffer. For example:
187 * buf.clear(); // Prepare buffer for reading
188 * in.read(buf); // Read data
190 * This method does not actually erase the data in the buffer,
191 * but it is named as if it did because it will most often be used
192 * in situations in which that might as well be the case.
194 inline Buffer
& clear() { mlimit
= mcapacity
; mposition
= 0; return *this; }
197 * This method resets the position to the beginning of the buffer
198 * so that it can be either reread or written to all over again.
200 inline Buffer
& rewind() { mposition
= 0; return *this; }
203 * This method provides for the remaining number of bytes
204 * that can be read out of the buffer or written into the
205 * buffer before it's finished.
207 inline size_t remaining() const { return mlimit
- mposition
; }
209 inline Buffer
& put(const void* src
, size_t bytes
)
210 { check(bytes
); memcpy( buffer
+ mposition
, src
, bytes
); mposition
+= bytes
; return *this; }
211 inline Buffer
& get(void* dest
, size_t bytes
)
212 { check(bytes
); memcpy( dest
, buffer
+ mposition
, bytes
); mposition
+= bytes
; return *this; }
214 inline unsigned char* data() const { return buffer
; }
215 inline unsigned char* curPosition() const { return buffer
+ mposition
; }
216 inline Buffer
& setPosition(size_t position
) { mposition
= position
; return *this; }
217 inline Buffer
& forward(size_t positionIncrement
)
218 { check(positionIncrement
); mposition
+= positionIncrement
; return *this; }
220 inline size_t limit() const { return mlimit
; }
221 inline size_t capacity() const { return mcapacity
; }
222 inline size_t position() const { return mposition
; }
224 #define DEFAULTBUFFERRELATIVERW(name,type) \
225 inline Buffer& put##name(const type & val) { return put(&val, sizeof(type)); } \
226 inline type get##name() { type ret; get(&ret, sizeof(type)); return ret; }
228 DEFAULTBUFFERRELATIVERW(Bool
,bool);
229 DEFAULTBUFFERRELATIVERW(Int
,int);
230 DEFAULTBUFFERRELATIVERW(Char
,char);
231 DEFAULTBUFFERRELATIVERW(Long
,long);
232 DEFAULTBUFFERRELATIVERW(Float
,float);
233 DEFAULTBUFFERRELATIVERW(Double
,double);
234 DEFAULTBUFFERRELATIVERW(Pointer
,void*);
235 DEFAULTBUFFERRELATIVERW(LongLong
,long long);
236 #undef DEFAULTBUFFERRELATIVERW
238 inline Buffer
& putString(const char* str
) { size_t len
= strlen(str
) + 1; check(len
); put(str
, len
); return (*this); }
239 inline Buffer
& putString(const std::string
& str
) { size_t len
= str
.length() + 1; check(len
); put(str
.c_str(), len
); return (*this); }
241 inline std::string
getString() { std::string
ret((const char*)(buffer
+ mposition
)); size_t len
= ret
.length() + 1; check(len
); mposition
+= len
; return ret
; }
242 inline std::string
getString(size_t length
)
245 std::string
ret((const char*)(buffer
+ mposition
),length
);
249 inline char* getCharPointerDirect() { char* ret
= (char*)(buffer
+ mposition
); size_t len
= strlen(ret
) + 1; check(len
); mposition
+= len
; return ret
; }