1 /*
2 Copyright (c) 2012, Broadcom Europe Ltd
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7     * Redistributions of source code must retain the above copyright
8       notice, this list of conditions and the following disclaimer.
9     * Redistributions in binary form must reproduce the above copyright
10       notice, this list of conditions and the following disclaimer in the
11       documentation and/or other materials provided with the distribution.
12     * Neither the name of the copyright holder nor the
13       names of its contributors may be used to endorse or promote products
14       derived from this software without specific prior written permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 #ifndef VC_CONTAINERS_IO_HELPERS_H
28 #define VC_CONTAINERS_IO_HELPERS_H
29 
30 /** \file containers_io_helpers.h
31  * Helper functions and macros which provide functionality which is often used by containers
32  */
33 
34 #include "containers/core/containers_io.h"
35 #include "containers/core/containers_utils.h"
36 
37 /*****************************************************************************
38  * Helper inline functions to read integers from an i/o stream
39  *****************************************************************************/
40 
41 /** Reads an unsigned 8 bits integer from an i/o stream.
42  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
43  * \return             The integer read. In case of failure during the read,
44  *                     this will return a value of 0.
45  */
vc_container_io_read_uint8(VC_CONTAINER_IO_T * io)46 STATIC_INLINE uint8_t vc_container_io_read_uint8(VC_CONTAINER_IO_T *io)
47 {
48    uint8_t value;
49    size_t ret = vc_container_io_read(io, &value, 1);
50    return ret == 1 ? value : 0;
51 }
52 
53 /** Reads a FOURCC from an i/o stream.
54  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
55  * \return             The FOURCC to read. In case of failure during the read,
56  *                     this will return a value of 0.
57  */
vc_container_io_read_fourcc(VC_CONTAINER_IO_T * io)58 STATIC_INLINE VC_CONTAINER_FOURCC_T vc_container_io_read_fourcc(VC_CONTAINER_IO_T *io)
59 {
60    VC_CONTAINER_FOURCC_T value;
61    size_t ret = vc_container_io_read(io, (int8_t *)&value, 4);
62    return ret == 4 ? value : 0;
63 }
64 
65 /** Reads an unsigned 16 bits big endian integer from an i/o stream.
66  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
67  * \return             The integer read. In case of failure during the read,
68  *                     this will return a value of 0.
69  */
vc_container_io_read_be_uint16(VC_CONTAINER_IO_T * io)70 STATIC_INLINE uint16_t vc_container_io_read_be_uint16(VC_CONTAINER_IO_T *io)
71 {
72    uint8_t value[2];
73    size_t ret = vc_container_io_read(io, value, 2);
74    return ret == 2 ? (value[0] << 8) | value[1] : 0;
75 }
76 
77 /** Reads an unsigned 24 bits big endian integer from an i/o stream.
78  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
79  * \return             The integer read. In case of failure during the read,
80  *                     this will return a value of 0.
81  */
vc_container_io_read_be_uint24(VC_CONTAINER_IO_T * io)82 STATIC_INLINE uint32_t vc_container_io_read_be_uint24(VC_CONTAINER_IO_T *io)
83 {
84    uint8_t value[3];
85    size_t ret = vc_container_io_read(io, value, 3);
86    return ret == 3 ? (value[0] << 16) | (value[1] << 8) | value[2] : 0;
87 }
88 
89 /** Reads an unsigned 32 bits big endian integer from an i/o stream.
90  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
91  * \return             The integer read. In case of failure during the read,
92  *                     this will return a value of 0.
93  */
vc_container_io_read_be_uint32(VC_CONTAINER_IO_T * io)94 STATIC_INLINE uint32_t vc_container_io_read_be_uint32(VC_CONTAINER_IO_T *io)
95 {
96    uint8_t value[4];
97    size_t ret = vc_container_io_read(io, value, 4);
98    return ret == 4 ? (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3] : 0;
99 }
100 
101 /** Reads an unsigned 40 bits big endian integer from an i/o stream.
102  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
103  * \return             The integer read. In case of failure during the read,
104  *                     this will return a value of 0.
105  */
vc_container_io_read_be_uint40(VC_CONTAINER_IO_T * io)106 STATIC_INLINE uint64_t vc_container_io_read_be_uint40(VC_CONTAINER_IO_T *io)
107 {
108    uint8_t value[5];
109    uint32_t value1, value2;
110    size_t ret = vc_container_io_read(io, value, 5);
111 
112    value1 = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3];
113    value2 = value[4];
114 
115    return ret == 5 ? (((uint64_t)value1) << 8)|value2 : 0;
116 }
117 
118 /** Reads an unsigned 48 bits big endian integer from an i/o stream.
119  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
120  * \return             The integer read. In case of failure during the read,
121  *                     this will return a value of 0.
122  */
vc_container_io_read_be_uint48(VC_CONTAINER_IO_T * io)123 STATIC_INLINE uint64_t vc_container_io_read_be_uint48(VC_CONTAINER_IO_T *io)
124 {
125    uint8_t value[6];
126    uint32_t value1, value2;
127    size_t ret = vc_container_io_read(io, value, 6);
128 
129    value1 = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3];
130    value2 = (value[4] << 8) | value[5];
131 
132    return ret == 6 ? (((uint64_t)value1) << 16)|value2 : 0;
133 }
134 
135 /** Reads an unsigned 56 bits big endian integer from an i/o stream.
136  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
137  * \return             The integer read. In case of failure during the read,
138  *                     this will return a value of 0.
139  */
vc_container_io_read_be_uint56(VC_CONTAINER_IO_T * io)140 STATIC_INLINE uint64_t vc_container_io_read_be_uint56(VC_CONTAINER_IO_T *io)
141 {
142    uint8_t value[7];
143    uint32_t value1, value2;
144    size_t ret = vc_container_io_read(io, value, 7);
145 
146    value1 = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3];
147    value2 = (value[4] << 16) | (value[5] << 8) | value[6];
148 
149    return ret == 7 ? (((uint64_t)value1) << 24)|value2 : 0;
150 }
151 
152 /** Reads an unsigned 64 bits big endian integer from an i/o stream.
153  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
154  * \return             The integer read. In case of failure during the read,
155  *                     this will return a value of 0.
156  */
vc_container_io_read_be_uint64(VC_CONTAINER_IO_T * io)157 STATIC_INLINE uint64_t vc_container_io_read_be_uint64(VC_CONTAINER_IO_T *io)
158 {
159    uint8_t value[8];
160    uint32_t value1, value2;
161    size_t ret = vc_container_io_read(io, value, 8);
162 
163    value1 = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3];
164    value2 = (value[4] << 24) | (value[5] << 16) | (value[6] << 8) | value[7];
165 
166    return ret == 8 ? (((uint64_t)value1) << 32)|value2 : 0;
167 }
168 
169 /** Reads an unsigned 16 bits little endian integer from an i/o stream.
170  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
171  * \return             The integer read. In case of failure during the read,
172  *                     this will return a value of 0.
173  */
vc_container_io_read_le_uint16(VC_CONTAINER_IO_T * io)174 STATIC_INLINE uint16_t vc_container_io_read_le_uint16(VC_CONTAINER_IO_T *io)
175 {
176    uint8_t value[2];
177    size_t ret = vc_container_io_read(io, value, 2);
178    return ret == 2 ? (value[1] << 8) | value[0] : 0;
179 }
180 
181 /** Reads an unsigned 24 bits little endian integer from an i/o stream.
182  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
183  * \return             The integer read. In case of failure during the read,
184  *                     this will return a value of 0.
185  */
vc_container_io_read_le_uint24(VC_CONTAINER_IO_T * io)186 STATIC_INLINE uint32_t vc_container_io_read_le_uint24(VC_CONTAINER_IO_T *io)
187 {
188    uint8_t value[3];
189    size_t ret = vc_container_io_read(io, value, 3);
190    return ret == 3 ? (value[2] << 16) | (value[1] << 8) | value[0] : 0;
191 }
192 
193 /** Reads an unsigned 32 bits little endian integer from an i/o stream.
194  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
195  * \return             The integer read. In case of failure during the read,
196  *                     this will return a value of 0.
197  */
vc_container_io_read_le_uint32(VC_CONTAINER_IO_T * io)198 STATIC_INLINE uint32_t vc_container_io_read_le_uint32(VC_CONTAINER_IO_T *io)
199 {
200    uint8_t value[4];
201    size_t ret = vc_container_io_read(io, value, 4);
202    return ret == 4 ? (value[3] << 24) | (value[2] << 16) | (value[1] << 8) | value[0] : 0;
203 }
204 
205 /** Reads an unsigned 40 bits little endian integer from an i/o stream.
206  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
207  * \return             The integer read. In case of failure during the read,
208  *                     this will return a value of 0.
209  */
vc_container_io_read_le_uint40(VC_CONTAINER_IO_T * io)210 STATIC_INLINE uint64_t vc_container_io_read_le_uint40(VC_CONTAINER_IO_T *io)
211 {
212    uint8_t value[5];
213    uint32_t value1, value2;
214    size_t ret = vc_container_io_read(io, value, 5);
215 
216    value1 = (value[3] << 24) | (value[2] << 16) | (value[1] << 8) | value[0];
217    value2 = value[4];
218 
219    return ret == 5 ? (((uint64_t)value2) << 32)|value1 : 0;
220 }
221 
222 /** Reads an unsigned 48 bits little endian integer from an i/o stream.
223  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
224  * \return             The integer read. In case of failure during the read,
225  *                     this will return a value of 0.
226  */
vc_container_io_read_le_uint48(VC_CONTAINER_IO_T * io)227 STATIC_INLINE uint64_t vc_container_io_read_le_uint48(VC_CONTAINER_IO_T *io)
228 {
229    uint8_t value[6];
230    uint32_t value1, value2;
231    size_t ret = vc_container_io_read(io, value, 6);
232 
233    value1 = (value[3] << 24) | (value[2] << 16) | (value[1] << 8) | value[0];
234    value2 = (value[5] << 8) | value[4];
235 
236    return ret == 6 ? (((uint64_t)value2) << 32)|value1 : 0;
237 }
238 
239 /** Reads an unsigned 56 bits little endian integer from an i/o stream.
240  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
241  * \return             The integer read. In case of failure during the read,
242  *                     this will return a value of 0.
243  */
vc_container_io_read_le_uint56(VC_CONTAINER_IO_T * io)244 STATIC_INLINE uint64_t vc_container_io_read_le_uint56(VC_CONTAINER_IO_T *io)
245 {
246    uint8_t value[7];
247    uint32_t value1, value2;
248    size_t ret = vc_container_io_read(io, value, 7);
249 
250    value1 = (value[3] << 24) | (value[2] << 16) | (value[1] << 8) | value[0];
251    value2 = (value[6] << 16) | (value[5] << 8) | value[4];
252 
253    return ret == 7 ? (((uint64_t)value2) << 32)|value1 : 0;
254 }
255 
256 /** Reads an unsigned 64 bits little endian integer from an i/o stream.
257  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
258  * \return             The integer read. In case of failure during the read,
259  *                     this will return a value of 0.
260  */
vc_container_io_read_le_uint64(VC_CONTAINER_IO_T * io)261 STATIC_INLINE uint64_t vc_container_io_read_le_uint64(VC_CONTAINER_IO_T *io)
262 {
263    uint8_t value[8];
264    uint32_t value1, value2;
265    size_t ret = vc_container_io_read(io, value, 8);
266 
267    value1 = (value[3] << 24) | (value[2] << 16) | (value[1] << 8) | value[0];
268    value2 = (value[7] << 24) | (value[6] << 16) | (value[5] << 8) | value[4];
269 
270    return ret == 8 ? (((uint64_t)value2) << 32)|value1 : 0;
271 }
272 
273 /*****************************************************************************
274  * Helper inline functions to peek integers from an i/o stream
275  *****************************************************************************/
276 
277 /** Peeks an unsigned 8 bits integer from an i/o stream.
278  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
279  * \return             The integer read. In case of failure during the read,
280  *                     this will return a value of 0.
281  */
vc_container_io_peek_uint8(VC_CONTAINER_IO_T * io)282 STATIC_INLINE uint8_t vc_container_io_peek_uint8(VC_CONTAINER_IO_T *io)
283 {
284    uint8_t value;
285    size_t ret = vc_container_io_peek(io, &value, 1);
286    return ret == 1 ? value : 0;
287 }
288 
289 /** Peeks an unsigned 16 bits big endian integer from an i/o stream.
290  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
291  * \return             The integer read. In case of failure during the read,
292  *                     this will return a value of 0.
293  */
vc_container_io_peek_be_uint16(VC_CONTAINER_IO_T * io)294 STATIC_INLINE uint16_t vc_container_io_peek_be_uint16(VC_CONTAINER_IO_T *io)
295 {
296    uint8_t value[2];
297    size_t ret = vc_container_io_peek(io, value, 2);
298    return ret == 2 ? (value[0] << 8) | value[1] : 0;
299 }
300 
301 /** Peeks an unsigned 24 bits big endian integer from an i/o stream.
302  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
303  * \return             The integer read. In case of failure during the read,
304  *                     this will return a value of 0.
305  */
vc_container_io_peek_be_uint24(VC_CONTAINER_IO_T * io)306 STATIC_INLINE uint32_t vc_container_io_peek_be_uint24(VC_CONTAINER_IO_T *io)
307 {
308    uint8_t value[3];
309    size_t ret = vc_container_io_peek(io, value, 3);
310    return ret == 3 ? (value[0] << 16) | (value[1] << 8) | value[2] : 0;
311 }
312 
313 /** Peeks an unsigned 32 bits big endian integer from an i/o stream.
314  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
315  * \return             The integer read. In case of failure during the read,
316  *                     this will return a value of 0.
317  */
vc_container_io_peek_be_uint32(VC_CONTAINER_IO_T * io)318 STATIC_INLINE uint32_t vc_container_io_peek_be_uint32(VC_CONTAINER_IO_T *io)
319 {
320    uint8_t value[4];
321    size_t ret = vc_container_io_peek(io, value, 4);
322    return ret == 4 ? (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3] : 0;
323 }
324 
325 /** Peeks an unsigned 64 bits big endian integer from an i/o stream.
326  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
327  * \return             The integer read. In case of failure during the read,
328  *                     this will return a value of 0.
329  */
vc_container_io_peek_be_uint64(VC_CONTAINER_IO_T * io)330 STATIC_INLINE uint64_t vc_container_io_peek_be_uint64(VC_CONTAINER_IO_T *io)
331 {
332    uint8_t value[8];
333    uint32_t value1, value2;
334    size_t ret = vc_container_io_peek(io, value, 8);
335 
336    value1 = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3];
337    value2 = (value[4] << 24) | (value[5] << 16) | (value[6] << 8) | value[7];
338 
339    return ret == 8 ? (((uint64_t)value1) << 32)|value2 : 0;
340 }
341 
342 /** Peeks an unsigned 16 bits little endian integer from an i/o stream.
343  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
344  * \return             The integer read. In case of failure during the read,
345  *                     this will return a value of 0.
346  */
vc_container_io_peek_le_uint16(VC_CONTAINER_IO_T * io)347 STATIC_INLINE uint16_t vc_container_io_peek_le_uint16(VC_CONTAINER_IO_T *io)
348 {
349    uint8_t value[2];
350    size_t ret = vc_container_io_peek(io, value, 2);
351    return ret == 2 ? (value[1] << 8) | value[0] : 0;
352 }
353 
354 /** Peeks an unsigned 24 bits little endian integer from an i/o stream.
355  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
356  * \return             The integer read. In case of failure during the read,
357  *                     this will return a value of 0.
358  */
vc_container_io_peek_le_uint24(VC_CONTAINER_IO_T * io)359 STATIC_INLINE uint32_t vc_container_io_peek_le_uint24(VC_CONTAINER_IO_T *io)
360 {
361    uint8_t value[3];
362    size_t ret = vc_container_io_peek(io, value, 3);
363    return ret == 3 ? (value[2] << 16) | (value[1] << 8) | value[0] : 0;
364 }
365 
366 /** Peeks an unsigned 32 bits little endian integer from an i/o stream.
367  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
368  * \return             The integer read. In case of failure during the read,
369  *                     this will return a value of 0.
370  */
vc_container_io_peek_le_uint32(VC_CONTAINER_IO_T * io)371 STATIC_INLINE uint32_t vc_container_io_peek_le_uint32(VC_CONTAINER_IO_T *io)
372 {
373    uint8_t value[4];
374    size_t ret = vc_container_io_peek(io, value, 4);
375    return ret == 4 ? (value[3] << 24) | (value[2] << 16) | (value[1] << 8) | value[0] : 0;
376 }
377 
378 /** Peeks an unsigned 64 bits little endian integer from an i/o stream.
379  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
380  * \return             The integer read. In case of failure during the read,
381  *                     this will return a value of 0.
382  */
vc_container_io_peek_le_uint64(VC_CONTAINER_IO_T * io)383 STATIC_INLINE uint64_t vc_container_io_peek_le_uint64(VC_CONTAINER_IO_T *io)
384 {
385    uint8_t value[8];
386    uint32_t value1, value2;
387    size_t ret = vc_container_io_peek(io, value, 8);
388 
389    value1 = (value[3] << 24) | (value[2] << 16) | (value[1] << 8) | value[0];
390    value2 = (value[7] << 24) | (value[6] << 16) | (value[5] << 8) | value[4];
391 
392    return ret == 8 ? (((uint64_t)value2) << 32)|value1 : 0;
393 }
394 
395 /*****************************************************************************
396  * Helper inline functions to write integers to an i/o stream
397  *****************************************************************************/
398 
399 /** Writes an unsigned 8 bits integer to an i/o stream.
400  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
401  * \param  value       The integer to write.
402  * \return             The status of the operation.
403  */
vc_container_io_write_uint8(VC_CONTAINER_IO_T * io,uint8_t value)404 STATIC_INLINE VC_CONTAINER_STATUS_T vc_container_io_write_uint8(VC_CONTAINER_IO_T *io, uint8_t value)
405 {
406    size_t ret = vc_container_io_write(io, &value, 1);
407    return ret == 1 ? VC_CONTAINER_SUCCESS : VC_CONTAINER_ERROR_FAILED;
408 }
409 
410 /** Writes a FOURCC to an i/o stream.
411  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
412  * \param  value       The FOURCC to write.
413  * \return             The status of the operation.
414  */
vc_container_io_write_fourcc(VC_CONTAINER_IO_T * io,VC_CONTAINER_FOURCC_T value)415 STATIC_INLINE VC_CONTAINER_STATUS_T vc_container_io_write_fourcc(VC_CONTAINER_IO_T *io, VC_CONTAINER_FOURCC_T value)
416 {
417    size_t ret = vc_container_io_write(io, (uint8_t *)&value, 4);
418    return ret == 4 ? VC_CONTAINER_SUCCESS : VC_CONTAINER_ERROR_FAILED;
419 }
420 
421 /** Writes an unsigned 16 bits big endian integer to an i/o stream.
422  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
423  * \param  value       The integer to write.
424  * \return             The status of the operation.
425  */
vc_container_io_write_be_uint16(VC_CONTAINER_IO_T * io,uint16_t value)426 STATIC_INLINE VC_CONTAINER_STATUS_T vc_container_io_write_be_uint16(VC_CONTAINER_IO_T *io, uint16_t value)
427 {
428    uint8_t bytes[2] = {(uint8_t)(value >> 8), (uint8_t)value};
429    size_t ret = vc_container_io_write(io, bytes, 2);
430    return ret == 2 ? VC_CONTAINER_SUCCESS : VC_CONTAINER_ERROR_FAILED;
431 }
432 
433 /** Writes an unsigned 24 bits big endian integer to an i/o stream.
434  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
435  * \param  value       The integer to write.
436  * \return             The status of the operation.
437  */
vc_container_io_write_be_uint24(VC_CONTAINER_IO_T * io,uint32_t value)438 STATIC_INLINE VC_CONTAINER_STATUS_T vc_container_io_write_be_uint24(VC_CONTAINER_IO_T *io, uint32_t value)
439 {
440    uint8_t bytes[3] = {(uint8_t)(value >> 16), (uint8_t)(value >> 8), (uint8_t)value};
441    size_t ret = vc_container_io_write(io, bytes, 3);
442    return ret == 3 ? VC_CONTAINER_SUCCESS : VC_CONTAINER_ERROR_FAILED;
443 }
444 
445 /** Writes an unsigned 32 bits big endian integer to an i/o stream.
446  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
447  * \param  value       The integer to write.
448  * \return             The status of the operation.
449  */
vc_container_io_write_be_uint32(VC_CONTAINER_IO_T * io,uint32_t value)450 STATIC_INLINE VC_CONTAINER_STATUS_T vc_container_io_write_be_uint32(VC_CONTAINER_IO_T *io, uint32_t value)
451 {
452    uint8_t bytes[4] = {value >> 24, value >> 16, value >> 8, value};
453    size_t ret = vc_container_io_write(io, bytes, 4);
454    return ret == 4 ? VC_CONTAINER_SUCCESS : VC_CONTAINER_ERROR_FAILED;
455 }
456 
457 /** Writes an unsigned 64 bits big endian integer to an i/o stream.
458  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
459  * \param  value       The integer to write.
460  * \return             The status of the operation.
461  */
vc_container_io_write_be_uint64(VC_CONTAINER_IO_T * io,uint64_t value)462 STATIC_INLINE VC_CONTAINER_STATUS_T vc_container_io_write_be_uint64(VC_CONTAINER_IO_T *io, uint64_t value)
463 {
464    uint8_t bytes[8] =
465    {
466       (uint8_t)(value >> 56),
467       (uint8_t)(value >> 48),
468       (uint8_t)(value >> 40),
469       (uint8_t)(value >> 32),
470       (uint8_t)(value >> 24),
471       (uint8_t)(value >> 16),
472       (uint8_t)(value >> 8),
473       (uint8_t) value
474    };
475    size_t ret = vc_container_io_write(io, bytes, 8);
476    return ret == 8 ? VC_CONTAINER_SUCCESS : VC_CONTAINER_ERROR_FAILED;
477 }
478 
479 /** Writes an unsigned 16 bits little endian integer to an i/o stream.
480  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
481  * \param  value       The integer to write.
482  * \return             The status of the operation.
483  */
vc_container_io_write_le_uint16(VC_CONTAINER_IO_T * io,uint16_t value)484 STATIC_INLINE VC_CONTAINER_STATUS_T vc_container_io_write_le_uint16(VC_CONTAINER_IO_T *io, uint16_t value)
485 {
486    uint8_t bytes[2] = {(uint8_t)value, (uint8_t)(value >> 8)};
487    size_t ret = vc_container_io_write(io, bytes, 2);
488    return ret == 2 ? VC_CONTAINER_SUCCESS : VC_CONTAINER_ERROR_FAILED;
489 }
490 
491 /** Writes an unsigned 24 bits little endian integer to an i/o stream.
492  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
493  * \param  value       The integer to write.
494  * \return             The status of the operation.
495  */
vc_container_io_write_le_uint24(VC_CONTAINER_IO_T * io,uint32_t value)496 STATIC_INLINE VC_CONTAINER_STATUS_T vc_container_io_write_le_uint24(VC_CONTAINER_IO_T *io, uint32_t value)
497 {
498    uint8_t bytes[3] = {value, value >> 8, value >> 16};
499    size_t ret = vc_container_io_write(io, bytes, 3);
500    return ret == 3 ? VC_CONTAINER_SUCCESS : VC_CONTAINER_ERROR_FAILED;
501 }
502 
503 /** Writes an unsigned 32 bits little endian integer to an i/o stream.
504  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
505  * \param  value       The integer to write.
506  * \return             The status of the operation.
507  */
vc_container_io_write_le_uint32(VC_CONTAINER_IO_T * io,uint32_t value)508 STATIC_INLINE VC_CONTAINER_STATUS_T vc_container_io_write_le_uint32(VC_CONTAINER_IO_T *io, uint32_t value)
509 {
510    uint8_t bytes[4] = {value, value >> 8, value >> 16, value >> 24};
511    size_t ret = vc_container_io_write(io, bytes, 4);
512    return ret == 4 ? VC_CONTAINER_SUCCESS : VC_CONTAINER_ERROR_FAILED;
513 }
514 
515 /** Writes an unsigned 64 bits little endian integer to an i/o stream.
516  * \param  io          Pointer to the VC_CONTAINER_IO_T instance to use
517  * \param  value       The integer to write.
518  * \return             The status of the operation.
519  */
vc_container_io_write_le_uint64(VC_CONTAINER_IO_T * io,uint64_t value)520 STATIC_INLINE VC_CONTAINER_STATUS_T vc_container_io_write_le_uint64(VC_CONTAINER_IO_T *io, uint64_t value)
521 {
522    uint8_t bytes[8] =
523    {
524       (uint8_t) value,
525       (uint8_t)(value >> 8),
526       (uint8_t)(value >> 16),
527       (uint8_t)(value >> 24),
528       (uint8_t)(value >> 32),
529       (uint8_t)(value >> 40),
530       (uint8_t)(value >> 48),
531       (uint8_t)(value >> 56)
532    };
533    size_t ret = vc_container_io_write(io, bytes, 8);
534    return ret == 8 ? VC_CONTAINER_SUCCESS : VC_CONTAINER_ERROR_FAILED;
535 }
536 
537 /*****************************************************************************
538  * Helper macros for accessing the i/o stream. These will also call the right
539  * functions depending on the endianness defined.
540  *****************************************************************************/
541 
542 /** Macro which returns the current position within the stream */
543 #define STREAM_POSITION(ctx) (ctx)->priv->io->offset
544 /** Macro which returns true if the end of stream has been reached */
545 #define STREAM_EOS(ctx) ((ctx)->priv->io->status == VC_CONTAINER_ERROR_EOS)
546 /** Macro which returns the status of the stream */
547 #define STREAM_STATUS(ctx) (ctx)->priv->io->status
548 /** Macro which returns true if an error other than end of stream has occurred */
549 #define STREAM_ERROR(ctx) ((ctx)->priv->io->status && (ctx)->priv->io->status != VC_CONTAINER_ERROR_EOS)
550 /** Macro which returns true if we can seek into the stream */
551 #define STREAM_SEEKABLE(ctx) (!((ctx)->priv->io->capabilities & VC_CONTAINER_IO_CAPS_CANT_SEEK))
552 
553 #define PEEK_BYTES(ctx, buffer, size) vc_container_io_peek((ctx)->priv->io, buffer, (size_t)(size))
554 #define READ_BYTES(ctx, buffer, size) vc_container_io_read((ctx)->priv->io, buffer, (size_t)(size))
555 #define SKIP_BYTES(ctx, size) vc_container_io_skip((ctx)->priv->io, (size_t)(size))
556 #define SEEK(ctx, off) vc_container_io_seek((ctx)->priv->io, (int64_t)(off))
557 #define CACHE_BYTES(ctx, size) vc_container_io_cache((ctx)->priv->io, (size_t)(size))
558 
559 #define _SKIP_GUID(ctx) vc_container_io_skip((ctx)->priv->io, 16)
560 #define _SKIP_U8(ctx)  (vc_container_io_skip((ctx)->priv->io, 1) != 1)
561 #define _SKIP_U16(ctx) (vc_container_io_skip((ctx)->priv->io, 2) != 2)
562 #define _SKIP_U24(ctx) (vc_container_io_skip((ctx)->priv->io, 3) != 3)
563 #define _SKIP_U32(ctx) (vc_container_io_skip((ctx)->priv->io, 4) != 4)
564 #define _SKIP_U64(ctx) (vc_container_io_skip((ctx)->priv->io, 8) != 8)
565 #define _SKIP_FOURCC(ctx) (vc_container_io_skip((ctx)->priv->io, 4) != 4)
566 
567 #define _READ_GUID(ctx, buffer) vc_container_io_read((ctx)->priv->io, buffer, 16)
568 #define _READ_U8(ctx)  vc_container_io_read_uint8((ctx)->priv->io)
569 #define _READ_FOURCC(ctx) vc_container_io_read_fourcc((ctx)->priv->io)
570 #define PEEK_GUID(ctx, buffer) vc_container_io_peek((ctx)->priv->io, buffer, 16)
571 #define PEEK_U8(ctx)  vc_container_io_peek_uint8((ctx)->priv->io)
572 #ifdef CONTAINER_IS_BIG_ENDIAN
573 # define _READ_U16(ctx) vc_container_io_read_be_uint16((ctx)->priv->io)
574 # define _READ_U24(ctx) vc_container_io_read_be_uint24((ctx)->priv->io)
575 # define _READ_U32(ctx) vc_container_io_read_be_uint32((ctx)->priv->io)
576 # define _READ_U40(ctx) vc_container_io_read_be_uint40((ctx)->priv->io)
577 # define _READ_U48(ctx) vc_container_io_read_be_uint48((ctx)->priv->io)
578 # define _READ_U56(ctx) vc_container_io_read_be_uint56((ctx)->priv->io)
579 # define _READ_U64(ctx) vc_container_io_read_be_uint64((ctx)->priv->io)
580 # define PEEK_U16(ctx) vc_container_io_peek_be_uint16((ctx)->priv->io)
581 # define PEEK_U24(ctx) vc_container_io_peek_be_uint24((ctx)->priv->io)
582 # define PEEK_U32(ctx) vc_container_io_peek_be_uint32((ctx)->priv->io)
583 # define PEEK_U64(ctx) vc_container_io_peek_be_uint64((ctx)->priv->io)
584 #else
585 # define _READ_U16(ctx) vc_container_io_read_le_uint16((ctx)->priv->io)
586 # define _READ_U24(ctx) vc_container_io_read_le_uint24((ctx)->priv->io)
587 # define _READ_U32(ctx) vc_container_io_read_le_uint32((ctx)->priv->io)
588 # define _READ_U40(ctx) vc_container_io_read_le_uint40((ctx)->priv->io)
589 # define _READ_U48(ctx) vc_container_io_read_le_uint48((ctx)->priv->io)
590 # define _READ_U56(ctx) vc_container_io_read_le_uint56((ctx)->priv->io)
591 # define _READ_U64(ctx) vc_container_io_read_le_uint64((ctx)->priv->io)
592 # define PEEK_U16(ctx) vc_container_io_peek_le_uint16((ctx)->priv->io)
593 # define PEEK_U24(ctx) vc_container_io_peek_le_uint24((ctx)->priv->io)
594 # define PEEK_U32(ctx) vc_container_io_peek_le_uint32((ctx)->priv->io)
595 # define PEEK_U64(ctx) vc_container_io_peek_le_uint64((ctx)->priv->io)
596 #endif
597 
598 #define WRITE_BYTES(ctx, buffer, size) vc_container_io_write((ctx)->priv->io, buffer, (size_t)(size))
599 #define _WRITE_GUID(ctx, buffer) vc_container_io_write((ctx)->priv->io, buffer, 16)
600 #define _WRITE_U8(ctx, v)  vc_container_io_write_uint8((ctx)->priv->io, v)
601 #define _WRITE_FOURCC(ctx, v) vc_container_io_write_fourcc((ctx)->priv->io, v)
602 #ifdef CONTAINER_IS_BIG_ENDIAN
603 # define _WRITE_U16(ctx, v) vc_container_io_write_be_uint16((ctx)->priv->io, v)
604 # define _WRITE_U24(ctx, v) vc_container_io_write_be_uint24((ctx)->priv->io, v)
605 # define _WRITE_U32(ctx, v) vc_container_io_write_be_uint32((ctx)->priv->io, v)
606 # define _WRITE_U64(ctx, v) vc_container_io_write_be_uint64((ctx)->priv->io, v)
607 #else
608 # define _WRITE_U16(ctx, v) vc_container_io_write_le_uint16((ctx)->priv->io, v)
609 # define _WRITE_U24(ctx, v) vc_container_io_write_le_uint24((ctx)->priv->io, v)
610 # define _WRITE_U32(ctx, v) vc_container_io_write_le_uint32((ctx)->priv->io, v)
611 # define _WRITE_U64(ctx, v) vc_container_io_write_le_uint64((ctx)->priv->io, v)
612 #endif
613 
614 #ifndef CONTAINER_HELPER_LOG_INDENT
615 # define CONTAINER_HELPER_LOG_INDENT(a) 0
616 #endif
617 
618 #ifdef CONTAINER_IS_BIG_ENDIAN
619 # define LOG_FORMAT_TYPE_UINT LOG_FORMAT_TYPE_UINT_BE
620 # define LOG_FORMAT_TYPE_STRING_UTF16 LOG_FORMAT_TYPE_STRING_UTF16_BE
621 #else
622 # define LOG_FORMAT_TYPE_UINT LOG_FORMAT_TYPE_UINT_LE
623 # define LOG_FORMAT_TYPE_STRING_UTF16 LOG_FORMAT_TYPE_STRING_UTF16_LE
624 #endif
625 
626 #ifndef ENABLE_CONTAINERS_LOG_FORMAT
627 #define SKIP_GUID(ctx,n) _SKIP_GUID(ctx)
628 #define SKIP_U8(ctx,n)  _SKIP_U8(ctx)
629 #define SKIP_U16(ctx,n) _SKIP_U16(ctx)
630 #define SKIP_U24(ctx,n) _SKIP_U24(ctx)
631 #define SKIP_U32(ctx,n) _SKIP_U32(ctx)
632 #define SKIP_U64(ctx,n) _SKIP_U64(ctx)
633 #define SKIP_FOURCC(ctx,n) _SKIP_FOURCC(ctx)
634 #define READ_GUID(ctx,buffer,n) _READ_GUID(ctx,(uint8_t *)buffer)
635 #define READ_U8(ctx,n)  _READ_U8(ctx)
636 #define READ_U16(ctx,n) _READ_U16(ctx)
637 #define READ_U24(ctx,n) _READ_U24(ctx)
638 #define READ_U32(ctx,n) _READ_U32(ctx)
639 #define READ_U40(ctx,n) _READ_U40(ctx)
640 #define READ_U48(ctx,n) _READ_U48(ctx)
641 #define READ_U56(ctx,n) _READ_U56(ctx)
642 #define READ_U64(ctx,n) _READ_U64(ctx)
643 #define READ_FOURCC(ctx,n) _READ_FOURCC(ctx)
644 #define READ_STRING(ctx,buffer,sz,n) READ_BYTES(ctx,buffer,sz)
645 #define READ_STRING_UTF16(ctx,buffer,sz,n) READ_BYTES(ctx,buffer,sz)
646 #define SKIP_STRING(ctx,sz,n) SKIP_BYTES(ctx,sz)
647 #define SKIP_STRING_UTF16(ctx,sz,n) SKIP_BYTES(ctx,sz)
648 #else
649 #define SKIP_GUID(ctx,n) vc_container_helper_read_debug(ctx, LOG_FORMAT_TYPE_GUID, 16, n, 0, CONTAINER_HELPER_LOG_INDENT(ctx), 1)
650 #define SKIP_U8(ctx,n)  vc_container_helper_read_debug(ctx, LOG_FORMAT_TYPE_UINT, 1, n, 0, CONTAINER_HELPER_LOG_INDENT(ctx), 1)
651 #define SKIP_U16(ctx,n) vc_container_helper_read_debug(ctx, LOG_FORMAT_TYPE_UINT, 2, n, 0, CONTAINER_HELPER_LOG_INDENT(ctx), 1)
652 #define SKIP_U24(ctx,n) vc_container_helper_read_debug(ctx, LOG_FORMAT_TYPE_UINT, 3, n, 0, CONTAINER_HELPER_LOG_INDENT(ctx), 1)
653 #define SKIP_U32(ctx,n) vc_container_helper_read_debug(ctx, LOG_FORMAT_TYPE_UINT, 4, n, 0, CONTAINER_HELPER_LOG_INDENT(ctx), 1)
654 #define SKIP_U64(ctx,n) vc_container_helper_read_debug(ctx, LOG_FORMAT_TYPE_UINT, 8, n, 0, CONTAINER_HELPER_LOG_INDENT(ctx), 1)
655 #define SKIP_FOURCC(ctx,n) vc_container_helper_read_debug(ctx, LOG_FORMAT_TYPE_FOURCC, 4, n, 0, CONTAINER_HELPER_LOG_INDENT(ctx), 1)
656 #define READ_GUID(ctx,buffer,n) vc_container_helper_read_debug(ctx, LOG_FORMAT_TYPE_GUID, 16, n, (uint8_t *)buffer, CONTAINER_HELPER_LOG_INDENT(ctx), 0)
657 #define READ_U8(ctx,n)  (uint8_t)vc_container_helper_read_debug(ctx, LOG_FORMAT_TYPE_UINT, 1, n, 0, CONTAINER_HELPER_LOG_INDENT(ctx), 0)
658 #define READ_U16(ctx,n) (uint16_t)vc_container_helper_read_debug(ctx, LOG_FORMAT_TYPE_UINT, 2, n, 0, CONTAINER_HELPER_LOG_INDENT(ctx), 0)
659 #define READ_U24(ctx,n) (uint32_t)vc_container_helper_read_debug(ctx, LOG_FORMAT_TYPE_UINT, 3, n, 0, CONTAINER_HELPER_LOG_INDENT(ctx), 0)
660 #define READ_U32(ctx,n) (uint32_t)vc_container_helper_read_debug(ctx, LOG_FORMAT_TYPE_UINT, 4, n, 0, CONTAINER_HELPER_LOG_INDENT(ctx), 0)
661 #define READ_U40(ctx,n) vc_container_helper_read_debug(ctx, LOG_FORMAT_TYPE_UINT, 5, n, 0, CONTAINER_HELPER_LOG_INDENT(ctx), 0)
662 #define READ_U48(ctx,n) vc_container_helper_read_debug(ctx, LOG_FORMAT_TYPE_UINT, 6, n, 0, CONTAINER_HELPER_LOG_INDENT(ctx), 0)
663 #define READ_U56(ctx,n) vc_container_helper_read_debug(ctx, LOG_FORMAT_TYPE_UINT, 7, n, 0, CONTAINER_HELPER_LOG_INDENT(ctx), 0)
664 #define READ_U64(ctx,n) vc_container_helper_read_debug(ctx, LOG_FORMAT_TYPE_UINT, 8, n, 0, CONTAINER_HELPER_LOG_INDENT(ctx), 0)
665 #define READ_FOURCC(ctx,n) vc_container_helper_read_debug(ctx, LOG_FORMAT_TYPE_FOURCC, 4, n, 0, CONTAINER_HELPER_LOG_INDENT(ctx), 0)
666 #define READ_STRING_UTF16(ctx,buffer,sz,n) vc_container_helper_read_debug(ctx, LOG_FORMAT_TYPE_STRING_UTF16, sz, n, (uint8_t *)buffer, CONTAINER_HELPER_LOG_INDENT(ctx), 0)
667 #define READ_STRING(ctx,buffer,sz,n) vc_container_helper_read_debug(ctx, LOG_FORMAT_TYPE_STRING, sz, n, (uint8_t *)buffer, CONTAINER_HELPER_LOG_INDENT(ctx), 0)
668 #define SKIP_STRING_UTF16(ctx,sz,n)  vc_container_helper_read_debug(ctx, LOG_FORMAT_TYPE_STRING_UTF16, sz, n, 0, CONTAINER_HELPER_LOG_INDENT(ctx), 1)
669 #define SKIP_STRING(ctx,sz,n)  vc_container_helper_read_debug(ctx, LOG_FORMAT_TYPE_STRING, sz, n, 0, CONTAINER_HELPER_LOG_INDENT(ctx), 1)
670 #endif
671 
672 #ifndef ENABLE_CONTAINERS_LOG_FORMAT
673 #define WRITE_GUID(ctx,buffer,n) _WRITE_GUID(ctx,(const uint8_t *)buffer)
674 #define WRITE_U8(ctx,v,n) _WRITE_U8(ctx,(uint8_t)(v))
675 #define WRITE_FOURCC(ctx,v,n) _WRITE_FOURCC(ctx,(uint32_t)(v))
676 #define WRITE_U16(ctx,v,n) _WRITE_U16(ctx,(uint16_t)(v))
677 #define WRITE_U24(ctx,v,n) _WRITE_U24(ctx,(uint32_t)(v))
678 #define WRITE_U32(ctx,v,n) _WRITE_U32(ctx,(uint32_t)(v))
679 #define WRITE_U64(ctx,v,n) _WRITE_U64(ctx,(uint64_t)(v))
680 #define WRITE_STRING(ctx,buffer,size,n) WRITE_BYTES(ctx, buffer, size)
681 #else
682 #define WRITE_GUID(ctx,buffer,n) (vc_container_helper_write_debug(ctx, LOG_FORMAT_TYPE_GUID, 16, n, UINT64_C(0), (const uint8_t *)buffer, CONTAINER_HELPER_LOG_INDENT(ctx), !(ctx)->priv->io->module) ? 0 : 16)
683 #define WRITE_U8(ctx,v,n)  vc_container_helper_write_debug(ctx, LOG_FORMAT_TYPE_UINT, 1, n, (uint64_t)(v), 0, CONTAINER_HELPER_LOG_INDENT(ctx), !(ctx)->priv->io->module)
684 #define WRITE_FOURCC(ctx,v,n) vc_container_helper_write_debug(ctx, LOG_FORMAT_TYPE_FOURCC, 4, n, (uint64_t)(v), 0, CONTAINER_HELPER_LOG_INDENT(ctx), !(ctx)->priv->io->module)
685 #define WRITE_U16(ctx,v,n) (uint16_t)vc_container_helper_write_debug(ctx, LOG_FORMAT_TYPE_UINT, 2, n, (uint64_t)(v), 0, CONTAINER_HELPER_LOG_INDENT(ctx), !(ctx)->priv->io->module)
686 #define WRITE_U24(ctx,v,n) vc_container_helper_write_debug(ctx, LOG_FORMAT_TYPE_UINT, 3, n, (uint64_t)(v), 0, CONTAINER_HELPER_LOG_INDENT(ctx), !(ctx)->priv->io->module)
687 #define WRITE_U32(ctx,v,n) vc_container_helper_write_debug(ctx, LOG_FORMAT_TYPE_UINT, 4, n, (uint64_t)(v), 0, CONTAINER_HELPER_LOG_INDENT(ctx), !(ctx)->priv->io->module)
688 #define WRITE_U64(ctx,v,n) vc_container_helper_write_debug(ctx, LOG_FORMAT_TYPE_UINT, 8, n, (uint64_t)(v), 0, CONTAINER_HELPER_LOG_INDENT(ctx), !(ctx)->priv->io->module)
689 #define WRITE_STRING(ctx,buffer,size,n) (vc_container_helper_write_debug(ctx, LOG_FORMAT_TYPE_STRING, size, n, UINT64_C(0), (const uint8_t *)buffer, CONTAINER_HELPER_LOG_INDENT(ctx), !(ctx)->priv->io->module) ? 0 : size)
690 #endif
691 
692 #ifdef ENABLE_CONTAINERS_LOG_FORMAT
693 #define LOG_FORMAT(ctx, ...) do { if((ctx)->priv->io->module) vc_container_helper_format_debug(ctx, CONTAINER_HELPER_LOG_INDENT(ctx), __VA_ARGS__); } while(0)
694 #else
695 #define LOG_FORMAT(ctx, ...) do {} while (0)
696 #endif
697 
698 #define LOG_FORMAT_TYPE_UINT_LE  0
699 #define LOG_FORMAT_TYPE_UINT_BE  1
700 #define LOG_FORMAT_TYPE_STRING   2
701 #define LOG_FORMAT_TYPE_STRING_UTF16_LE 3
702 #define LOG_FORMAT_TYPE_STRING_UTF16_BE 4
703 #define LOG_FORMAT_TYPE_FOURCC   5
704 #define LOG_FORMAT_TYPE_GUID     6
705 #define LOG_FORMAT_TYPE_HEX  0x100
706 
707 uint64_t vc_container_helper_int_debug(VC_CONTAINER_T *ctx, int type, uint64_t value, const char *name, int indent);
708 uint64_t vc_container_helper_read_debug(VC_CONTAINER_T *ctx, int type, int size, const char *name,
709    uint8_t *buffer, int indent, int b_skip);
710 VC_CONTAINER_STATUS_T vc_container_helper_write_debug(VC_CONTAINER_T *ctx, int type, int size, const char *name,
711    uint64_t value, const uint8_t *buffer, int indent, int silent);
712 void vc_container_helper_format_debug(VC_CONTAINER_T *ctx, int indent, const char *format, ...);
713 
714 #endif /* VC_CONTAINERS_IO_HELPERS_H */
715 /* End of file */
716 /*-----------------------------------------------------------------------------*/
717