Branch data Line data Source code
1 : : /* GStreamer byte writer
2 : : *
3 : : * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
4 : : *
5 : : * This library is free software; you can redistribute it and/or
6 : : * modify it under the terms of the GNU Library General Public
7 : : * License as published by the Free Software Foundation; either
8 : : * version 2 of the License, or (at your option) any later version.
9 : : *
10 : : * This library is distributed in the hope that it will be useful,
11 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : : * Library General Public License for more details.
14 : : *
15 : : * You should have received a copy of the GNU Library General Public
16 : : * License along with this library; if not, write to the
17 : : * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 : : * Boston, MA 02111-1307, USA.
19 : : */
20 : :
21 : : #ifndef __GST_BYTE_WRITER_H__
22 : : #define __GST_BYTE_WRITER_H__
23 : :
24 : : #include <gst/gst.h>
25 : : #include <gst/base/gstbytereader.h>
26 : :
27 : : #include <string.h>
28 : :
29 : : G_BEGIN_DECLS
30 : :
31 : : #define GST_BYTE_WRITER(writer) ((GstByteWriter *) (writer))
32 : :
33 : : /**
34 : : * GstByteWriter:
35 : : * @parent: #GstByteReader parent
36 : : * @alloc_size: Allocation size of the data
37 : : * @fixed: If %TRUE no reallocations are allowed
38 : : * @owned: If %FALSE no reallocations are allowed and copies of data are returned
39 : : *
40 : : * A byte writer instance.
41 : : */
42 : : typedef struct {
43 : : GstByteReader parent;
44 : :
45 : : guint alloc_size;
46 : :
47 : : gboolean fixed;
48 : : gboolean owned;
49 : : } GstByteWriter;
50 : :
51 : : GstByteWriter * gst_byte_writer_new (void);
52 : : GstByteWriter * gst_byte_writer_new_with_size (guint size, gboolean fixed);
53 : : GstByteWriter * gst_byte_writer_new_with_data (guint8 *data, guint size, gboolean initialized);
54 : : GstByteWriter * gst_byte_writer_new_with_buffer (GstBuffer *buffer, gboolean initialized);
55 : :
56 : : void gst_byte_writer_init (GstByteWriter *writer);
57 : : void gst_byte_writer_init_with_size (GstByteWriter *writer, guint size, gboolean fixed);
58 : : void gst_byte_writer_init_with_data (GstByteWriter *writer, guint8 *data, guint size, gboolean initialized);
59 : : void gst_byte_writer_init_with_buffer (GstByteWriter *writer, GstBuffer *buffer, gboolean initialized);
60 : :
61 : : void gst_byte_writer_free (GstByteWriter *writer);
62 : : guint8 * gst_byte_writer_free_and_get_data (GstByteWriter *writer);
63 : : GstBuffer *gst_byte_writer_free_and_get_buffer (GstByteWriter *writer);
64 : :
65 : : void gst_byte_writer_reset (GstByteWriter *writer);
66 : : guint8 * gst_byte_writer_reset_and_get_data (GstByteWriter *writer);
67 : : GstBuffer *gst_byte_writer_reset_and_get_buffer (GstByteWriter *writer);
68 : :
69 : : /**
70 : : * gst_byte_writer_get_pos:
71 : : * @writer: #GstByteWriter instance
72 : : *
73 : : * Returns: The current position of the read/write cursor
74 : : *
75 : : * Since: 0.10.26
76 : : */
77 : : /**
78 : : * gst_byte_writer_set_pos:
79 : : * @writer: #GstByteWriter instance
80 : : * @pos: new position
81 : : *
82 : : * Sets the current read/write cursor of @writer. The new position
83 : : * can only be between 0 and the current size.
84 : : *
85 : : * Returns: %TRUE if the new position could be set
86 : : *
87 : : * Since: 0.10.26
88 : : */
89 : : /**
90 : : * gst_byte_writer_get_size:
91 : : * @writer: #GstByteWriter instance
92 : : *
93 : : * Returns: The current, initialized size of the data
94 : : *
95 : : * Since: 0.10.26
96 : : */
97 : : #ifdef _FOOL_GTK_DOC_
98 : : G_INLINE_FUNC guint gst_byte_writer_get_pos (const GstByteWriter *writer);
99 : : G_INLINE_FUNC gboolean gst_byte_writer_set_pos (GstByteWriter *writer, guint pos);
100 : : G_INLINE_FUNC guint gst_byte_writer_get_size (const GstByteWriter *writer);
101 : : #else
102 : : static inline guint
103 : 9 : gst_byte_writer_get_pos (const GstByteWriter *writer)
104 : : {
105 : 9 : return gst_byte_reader_get_pos ((const GstByteReader *) writer);
106 : : }
107 : :
108 : : static inline gboolean
109 : 5 : gst_byte_writer_set_pos (GstByteWriter *writer, guint pos)
110 : : {
111 : 5 : return gst_byte_reader_set_pos (GST_BYTE_READER (writer), pos);
112 : : }
113 : :
114 : : static inline guint
115 : 7 : gst_byte_writer_get_size (const GstByteWriter *writer)
116 : : {
117 : 7 : return gst_byte_reader_get_size ((const GstByteReader *) writer);
118 : : }
119 : : #endif
120 : :
121 : : guint gst_byte_writer_get_remaining (const GstByteWriter *writer);
122 : : gboolean gst_byte_writer_ensure_free_space (GstByteWriter *writer, guint size);
123 : :
124 : : gboolean gst_byte_writer_put_uint8 (GstByteWriter *writer, guint8 val);
125 : : gboolean gst_byte_writer_put_int8 (GstByteWriter *writer, gint8 val);
126 : : gboolean gst_byte_writer_put_uint16_be (GstByteWriter *writer, guint16 val);
127 : : gboolean gst_byte_writer_put_uint16_le (GstByteWriter *writer, guint16 val);
128 : : gboolean gst_byte_writer_put_int16_be (GstByteWriter *writer, gint16 val);
129 : : gboolean gst_byte_writer_put_int16_le (GstByteWriter *writer, gint16 val);
130 : : gboolean gst_byte_writer_put_uint24_be (GstByteWriter *writer, guint32 val);
131 : : gboolean gst_byte_writer_put_uint24_le (GstByteWriter *writer, guint32 val);
132 : : gboolean gst_byte_writer_put_int24_be (GstByteWriter *writer, gint32 val);
133 : : gboolean gst_byte_writer_put_int24_le (GstByteWriter *writer, gint32 val);
134 : : gboolean gst_byte_writer_put_uint32_be (GstByteWriter *writer, guint32 val);
135 : : gboolean gst_byte_writer_put_uint32_le (GstByteWriter *writer, guint32 val);
136 : : gboolean gst_byte_writer_put_int32_be (GstByteWriter *writer, gint32 val);
137 : : gboolean gst_byte_writer_put_int32_le (GstByteWriter *writer, gint32 val);
138 : : gboolean gst_byte_writer_put_uint64_be (GstByteWriter *writer, guint64 val);
139 : : gboolean gst_byte_writer_put_uint64_le (GstByteWriter *writer, guint64 val);
140 : : gboolean gst_byte_writer_put_int64_be (GstByteWriter *writer, gint64 val);
141 : : gboolean gst_byte_writer_put_int64_le (GstByteWriter *writer, gint64 val);
142 : :
143 : : gboolean gst_byte_writer_put_float32_be (GstByteWriter *writer, gfloat val);
144 : : gboolean gst_byte_writer_put_float32_le (GstByteWriter *writer, gfloat val);
145 : : gboolean gst_byte_writer_put_float64_be (GstByteWriter *writer, gdouble val);
146 : : gboolean gst_byte_writer_put_float64_le (GstByteWriter *writer, gdouble val);
147 : :
148 : : gboolean gst_byte_writer_put_data (GstByteWriter *writer, const guint8 *data, guint size);
149 : : gboolean gst_byte_writer_fill (GstByteWriter *writer, guint8 value, guint size);
150 : : gboolean gst_byte_writer_put_string_utf8 (GstByteWriter *writer, const gchar *data);
151 : : gboolean gst_byte_writer_put_string_utf16 (GstByteWriter *writer, const guint16 *data);
152 : : gboolean gst_byte_writer_put_string_utf32 (GstByteWriter *writer, const guint32 *data);
153 : :
154 : : /**
155 : : * gst_byte_writer_put_string:
156 : : * @writer: #GstByteWriter instance
157 : : * @data: (in) (array zero-terminated=1): Null terminated string
158 : : *
159 : : * Write a NUL-terminated string to @writer (including the terminator). The
160 : : * string is assumed to be in an 8-bit encoding (e.g. ASCII,UTF-8 or
161 : : * ISO-8859-1).
162 : : *
163 : : * Returns: %TRUE if the string could be written
164 : : *
165 : : * Since: 0.10.26
166 : : */
167 : : #define gst_byte_writer_put_string(writer, data) \
168 : : gst_byte_writer_put_string_utf8(writer, data)
169 : :
170 : : static inline guint
171 : 4 : _gst_byte_writer_next_pow2 (guint n)
172 : : {
173 : 4 : guint ret = 16;
174 : :
175 : : /* We start with 16, smaller allocations make no sense */
176 : :
177 [ + + ][ + - ]: 5 : while (ret < n && ret > 0)
178 : 1 : ret <<= 1;
179 : :
180 [ + - ]: 4 : return ret ? ret : n;
181 : : }
182 : :
183 : : static inline gboolean
184 : 20 : _gst_byte_writer_ensure_free_space_inline (GstByteWriter * writer, guint size)
185 : : {
186 : : gpointer data;
187 : :
188 [ + + ]: 20 : if (G_LIKELY (size <= writer->alloc_size - writer->parent.byte))
189 : 13 : return TRUE;
190 [ + + ][ - + ]: 7 : if (G_UNLIKELY (writer->fixed || !writer->owned))
191 : 3 : return FALSE;
192 [ - + ]: 4 : if (G_UNLIKELY (writer->parent.byte > G_MAXUINT - size))
193 : 0 : return FALSE;
194 : :
195 : 4 : writer->alloc_size = _gst_byte_writer_next_pow2 (writer->parent.byte + size);
196 : 4 : data = g_try_realloc ((guint8 *) writer->parent.data, writer->alloc_size);
197 [ - + ]: 4 : if (G_UNLIKELY (data == NULL))
198 : 0 : return FALSE;
199 : :
200 : 4 : writer->parent.data = (guint8 *) data;
201 : :
202 : 20 : return TRUE;
203 : : }
204 : :
205 : : #define __GST_BYTE_WRITER_CREATE_WRITE_FUNC(bits,type,name,write_func) \
206 : : static inline void \
207 : : gst_byte_writer_put_##name##_unchecked (GstByteWriter *writer, type val) \
208 : : { \
209 : : guint8 *write_data; \
210 : : \
211 : : write_data = (guint8 *) writer->parent.data + writer->parent.byte; \
212 : : write_func (write_data, val); \
213 : : writer->parent.byte += bits/8; \
214 : : writer->parent.size = MAX (writer->parent.size, writer->parent.byte); \
215 : : } \
216 : : \
217 : : static inline gboolean \
218 : : _gst_byte_writer_put_##name##_inline (GstByteWriter *writer, type val) \
219 : : { \
220 : : g_return_val_if_fail (writer != NULL, FALSE); \
221 : : \
222 : : if (G_UNLIKELY (!_gst_byte_writer_ensure_free_space_inline(writer, bits/8))) \
223 : : return FALSE; \
224 : : \
225 : : gst_byte_writer_put_##name##_unchecked (writer, val); \
226 : : \
227 : : return TRUE; \
228 : : }
229 : :
230 [ - + ][ + + ]: 11 : __GST_BYTE_WRITER_CREATE_WRITE_FUNC (8, guint8, uint8, GST_WRITE_UINT8)
231 [ # # ][ # # ]: 0 : __GST_BYTE_WRITER_CREATE_WRITE_FUNC (8, gint8, int8, GST_WRITE_UINT8)
232 [ - + ][ - + ]: 4 : __GST_BYTE_WRITER_CREATE_WRITE_FUNC (16, guint16, uint16_le, GST_WRITE_UINT16_LE)
233 [ - + ][ - + ]: 4 : __GST_BYTE_WRITER_CREATE_WRITE_FUNC (16, guint16, uint16_be, GST_WRITE_UINT16_BE)
234 [ # # ][ # # ]: 0 : __GST_BYTE_WRITER_CREATE_WRITE_FUNC (16, gint16, int16_le, GST_WRITE_UINT16_LE)
235 [ # # ][ # # ]: 0 : __GST_BYTE_WRITER_CREATE_WRITE_FUNC (16, gint16, int16_be, GST_WRITE_UINT16_BE)
236 [ # # ][ # # ]: 0 : __GST_BYTE_WRITER_CREATE_WRITE_FUNC (24, guint32, uint24_le, GST_WRITE_UINT24_LE)
237 [ - + ][ - + ]: 4 : __GST_BYTE_WRITER_CREATE_WRITE_FUNC (24, guint32, uint24_be, GST_WRITE_UINT24_BE)
238 [ # # ][ # # ]: 0 : __GST_BYTE_WRITER_CREATE_WRITE_FUNC (24, gint32, int24_le, GST_WRITE_UINT24_LE)
239 [ # # ][ # # ]: 0 : __GST_BYTE_WRITER_CREATE_WRITE_FUNC (24, gint32, int24_be, GST_WRITE_UINT24_BE)
240 [ # # ][ # # ]: 0 : __GST_BYTE_WRITER_CREATE_WRITE_FUNC (32, guint32, uint32_le, GST_WRITE_UINT32_LE)
241 [ # # ][ # # ]: 0 : __GST_BYTE_WRITER_CREATE_WRITE_FUNC (32, guint32, uint32_be, GST_WRITE_UINT32_BE)
242 [ # # ][ # # ]: 0 : __GST_BYTE_WRITER_CREATE_WRITE_FUNC (32, gint32, int32_le, GST_WRITE_UINT32_LE)
243 [ # # ][ # # ]: 0 : __GST_BYTE_WRITER_CREATE_WRITE_FUNC (32, gint32, int32_be, GST_WRITE_UINT32_BE)
244 [ # # ][ # # ]: 0 : __GST_BYTE_WRITER_CREATE_WRITE_FUNC (64, guint64, uint64_le, GST_WRITE_UINT64_LE)
245 [ - + ][ + + ]: 4 : __GST_BYTE_WRITER_CREATE_WRITE_FUNC (64, guint64, uint64_be, GST_WRITE_UINT64_BE)
246 [ # # ][ # # ]: 0 : __GST_BYTE_WRITER_CREATE_WRITE_FUNC (64, gint64, int64_le, GST_WRITE_UINT64_LE)
247 [ # # ][ # # ]: 0 : __GST_BYTE_WRITER_CREATE_WRITE_FUNC (64, gint64, int64_be, GST_WRITE_UINT64_BE)
248 : :
249 [ # # ][ # # ]: 0 : __GST_BYTE_WRITER_CREATE_WRITE_FUNC (32, gfloat, float32_be, GST_WRITE_FLOAT_BE)
250 [ # # ][ # # ]: 0 : __GST_BYTE_WRITER_CREATE_WRITE_FUNC (32, gfloat, float32_le, GST_WRITE_FLOAT_LE)
251 [ # # ][ # # ]: 0 : __GST_BYTE_WRITER_CREATE_WRITE_FUNC (64, gdouble, float64_be, GST_WRITE_DOUBLE_BE)
252 [ # # ][ # # ]: 0 : __GST_BYTE_WRITER_CREATE_WRITE_FUNC (64, gdouble, float64_le, GST_WRITE_DOUBLE_LE)
253 : :
254 : : #undef __GST_BYTE_WRITER_CREATE_WRITE_FUNC
255 : :
256 : : static inline void
257 : 2 : gst_byte_writer_put_data_unchecked (GstByteWriter * writer, const guint8 * data,
258 : : guint size)
259 : : {
260 : 2 : memcpy ((guint8 *) & writer->parent.data[writer->parent.byte], data, size);
261 : 2 : writer->parent.byte += size;
262 : 2 : writer->parent.size = MAX (writer->parent.size, writer->parent.byte);
263 : 2 : }
264 : :
265 : : static inline gboolean
266 : 2 : _gst_byte_writer_put_data_inline (GstByteWriter * writer, const guint8 * data,
267 : : guint size)
268 : : {
269 [ - + ]: 2 : g_return_val_if_fail (writer != NULL, FALSE);
270 : :
271 [ - + ]: 2 : if (G_UNLIKELY (!_gst_byte_writer_ensure_free_space_inline (writer, size)))
272 : 0 : return FALSE;
273 : :
274 : 2 : gst_byte_writer_put_data_unchecked (writer, data, size);
275 : :
276 : 2 : return TRUE;
277 : : }
278 : :
279 : : static inline void
280 : 2 : gst_byte_writer_fill_unchecked (GstByteWriter * writer, guint8 value, guint size)
281 : : {
282 : 2 : memset ((guint8 *) & writer->parent.data[writer->parent.byte], value, size);
283 : 2 : writer->parent.byte += size;
284 : 2 : writer->parent.size = MAX (writer->parent.size, writer->parent.byte);
285 : 2 : }
286 : :
287 : : static inline gboolean
288 : 2 : _gst_byte_writer_fill_inline (GstByteWriter * writer, guint8 value, guint size)
289 : : {
290 [ - + ]: 2 : g_return_val_if_fail (writer != NULL, FALSE);
291 : :
292 [ - + ]: 2 : if (G_UNLIKELY (!_gst_byte_writer_ensure_free_space_inline (writer, size)))
293 : 0 : return FALSE;
294 : :
295 : 2 : gst_byte_writer_fill_unchecked (writer, value, size);
296 : :
297 : 2 : return TRUE;
298 : : }
299 : :
300 : : #ifndef GST_BYTE_WRITER_DISABLE_INLINES
301 : :
302 : : /* we use defines here so we can add the G_LIKELY() */
303 : :
304 : : #define gst_byte_writer_ensure_free_space(writer, size) \
305 : : G_LIKELY (_gst_byte_writer_ensure_free_space_inline (writer, size))
306 : : #define gst_byte_writer_put_uint8(writer, val) \
307 : : G_LIKELY (_gst_byte_writer_put_uint8_inline (writer, val))
308 : : #define gst_byte_writer_put_int8(writer, val) \
309 : : G_LIKELY (_gst_byte_writer_put_int8_inline (writer, val))
310 : : #define gst_byte_writer_put_uint16_be(writer, val) \
311 : : G_LIKELY (_gst_byte_writer_put_uint16_be_inline (writer, val))
312 : : #define gst_byte_writer_put_uint16_le(writer, val) \
313 : : G_LIKELY (_gst_byte_writer_put_uint16_le_inline (writer, val))
314 : : #define gst_byte_writer_put_int16_be(writer, val) \
315 : : G_LIKELY (_gst_byte_writer_put_int16_be_inline (writer, val))
316 : : #define gst_byte_writer_put_int16_le(writer, val) \
317 : : G_LIKELY (_gst_byte_writer_put_int16_le_inline (writer, val))
318 : : #define gst_byte_writer_put_uint24_be(writer, val) \
319 : : G_LIKELY (_gst_byte_writer_put_uint24_be_inline (writer, val))
320 : : #define gst_byte_writer_put_uint24_le(writer, val) \
321 : : G_LIKELY (_gst_byte_writer_put_uint24_le_inline (writer, val))
322 : : #define gst_byte_writer_put_int24_be(writer, val) \
323 : : G_LIKELY (_gst_byte_writer_put_int24_be_inline (writer, val))
324 : : #define gst_byte_writer_put_int24_le(writer, val) \
325 : : G_LIKELY (_gst_byte_writer_put_int24_le_inline (writer, val))
326 : : #define gst_byte_writer_put_uint32_be(writer, val) \
327 : : G_LIKELY (_gst_byte_writer_put_uint32_be_inline (writer, val))
328 : : #define gst_byte_writer_put_uint32_le(writer, val) \
329 : : G_LIKELY (_gst_byte_writer_put_uint32_le_inline (writer, val))
330 : : #define gst_byte_writer_put_int32_be(writer, val) \
331 : : G_LIKELY (_gst_byte_writer_put_int32_be_inline (writer, val))
332 : : #define gst_byte_writer_put_int32_le(writer, val) \
333 : : G_LIKELY (_gst_byte_writer_put_int32_le_inline (writer, val))
334 : : #define gst_byte_writer_put_uint64_be(writer, val) \
335 : : G_LIKELY (_gst_byte_writer_put_uint64_be_inline (writer, val))
336 : : #define gst_byte_writer_put_uint64_le(writer, val) \
337 : : G_LIKELY (_gst_byte_writer_put_uint64_le_inline (writer, val))
338 : : #define gst_byte_writer_put_int64_be(writer, val) \
339 : : G_LIKELY (_gst_byte_writer_put_int64_be_inline (writer, val))
340 : : #define gst_byte_writer_put_int64_le(writer, val) \
341 : : G_LIKELY (_gst_byte_writer_put_int64_le_inline (writer, val))
342 : :
343 : : #define gst_byte_writer_put_float32_be(writer, val) \
344 : : G_LIKELY (_gst_byte_writer_put_float32_be_inline (writer, val))
345 : : #define gst_byte_writer_put_float32_le(writer, val) \
346 : : G_LIKELY (_gst_byte_writer_put_float32_le_inline (writer, val))
347 : : #define gst_byte_writer_put_float64_be(writer, val) \
348 : : G_LIKELY (_gst_byte_writer_put_float64_be_inline (writer, val))
349 : : #define gst_byte_writer_put_float64_le(writer, val) \
350 : : G_LIKELY (_gst_byte_writer_put_float64_le_inline (writer, val))
351 : :
352 : : #define gst_byte_writer_put_data(writer, data, size) \
353 : : G_LIKELY (_gst_byte_writer_put_data_inline (writer, data, size))
354 : : #define gst_byte_writer_fill(writer, val, size) \
355 : : G_LIKELY (_gst_byte_writer_fill_inline (writer, val, size))
356 : :
357 : : #endif
358 : :
359 : : G_END_DECLS
360 : :
361 : : #endif /* __GST_BYTE_WRITER_H__ */
|