1 /*****************************************************************************
2  * bytes.c
3  *****************************************************************************
4  * Copyright (C) 2010-2017 L-SMASH project
5  *
6  * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
7  *
8  * Permission to use, copy, modify, and/or distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  *****************************************************************************/
20 
21 /* This file is available under an ISC license. */
22 
23 #include "internal.h" /* must be placed first */
24 
25 #include <string.h>
26 #include <limits.h>
27 
lsmash_bs_create(void)28 lsmash_bs_t *lsmash_bs_create( void )
29 {
30     lsmash_bs_t *bs = lsmash_malloc_zero( sizeof(lsmash_bs_t) );
31     if( !bs )
32         return NULL;
33     bs->unseekable      = 1;
34     bs->buffer.internal = 1;
35     bs->buffer.max_size = BS_MAX_DEFAULT_READ_SIZE;
36     return bs;
37 }
38 
bs_buffer_free(lsmash_bs_t * bs)39 static void bs_buffer_free( lsmash_bs_t *bs )
40 {
41     if( bs->buffer.internal )
42         lsmash_free( bs->buffer.data );
43     bs->buffer.data  = NULL;
44     bs->buffer.alloc = 0;
45     bs->buffer.store = 0;
46     bs->buffer.pos   = 0;
47 }
48 
lsmash_bs_cleanup(lsmash_bs_t * bs)49 void lsmash_bs_cleanup( lsmash_bs_t *bs )
50 {
51     if( !bs )
52         return;
53     bs_buffer_free( bs );
54     lsmash_free( bs );
55 }
56 
lsmash_bs_set_empty_stream(lsmash_bs_t * bs,uint8_t * data,size_t size)57 int lsmash_bs_set_empty_stream( lsmash_bs_t *bs, uint8_t *data, size_t size )
58 {
59     if( !bs )
60         return LSMASH_ERR_FUNCTION_PARAM;
61     bs->stream     = NULL;      /* empty stream */
62     bs->eof        = 1;         /* unreadable because of empty stream */
63     bs->eob        = 0;         /* readable on the buffer */
64     bs->error      = 0;
65     bs->unseekable = 1;         /* only seek on the buffer */
66     bs->written    = size;      /* behave as if the size of the empty stream is 'size' */
67     bs->offset     = size;      /* behave as if the poiter of the stream is at the end */
68     bs->buffer.unseekable = 0;  /* only seek on the buffer */
69     bs->buffer.internal   = 0;  /* must not be allocated internally */
70     bs->buffer.data       = data;
71     bs->buffer.store      = size;
72     bs->buffer.alloc      = size;
73     bs->buffer.pos        = 0;
74     bs->buffer.max_size   = 0;  /* make no sense */
75     bs->buffer.count      = 0;
76     bs->read  = NULL;
77     bs->write = NULL;
78     bs->seek  = NULL;
79     return 0;
80 }
81 
lsmash_bs_empty(lsmash_bs_t * bs)82 void lsmash_bs_empty( lsmash_bs_t *bs )
83 {
84     if( !bs )
85         return;
86     if( bs->buffer.data )
87         memset( bs->buffer.data, 0, bs->buffer.alloc );
88     bs->buffer.store = 0;
89     bs->buffer.pos   = 0;
90 }
91 
bs_alloc(lsmash_bs_t * bs,size_t alloc)92 static void bs_alloc( lsmash_bs_t *bs, size_t alloc )
93 {
94     if( (bs->buffer.alloc >= alloc) || bs->error )
95         return;
96     if( !bs->buffer.internal )
97     {
98         /* We cannot re-allocate the memory block. */
99         bs->error = 1;
100         return;
101     }
102     alloc  = LSMASH_MAX( alloc, bs->buffer.max_size );
103     uint8_t *data;
104     if( !bs->buffer.data )
105         data = lsmash_malloc( alloc );
106     else
107         data = lsmash_realloc( bs->buffer.data, alloc );
108     if( !data )
109     {
110         bs_buffer_free( bs );
111         bs->error = 1;
112         return;
113     }
114     bs->buffer.internal = 1;
115     bs->buffer.data     = data;
116     bs->buffer.alloc    = alloc;
117 }
118 
bs_estimate_seek_offset(lsmash_bs_t * bs,int64_t offset,int whence)119 static uint64_t bs_estimate_seek_offset( lsmash_bs_t *bs, int64_t offset, int whence )
120 {
121     /* Calculate the offset after the seek. */
122     uint64_t dst_offset;
123     if( whence == SEEK_SET )
124     {
125         assert( offset >= 0 );
126         if( bs->written < offset )
127             dst_offset = bs->written;
128         else
129             dst_offset = offset;
130     }
131     else if( whence == SEEK_CUR )
132     {
133         if( offset < 0 && bs->offset < -offset )
134             dst_offset = 0;
135         else if( offset > 0 && bs->written < bs->offset + offset )
136             dst_offset = bs->written;
137         else
138             dst_offset = bs->offset + offset;
139     }
140     else /* if( whence == SEEK_END ) */
141     {
142         assert( offset <= 0 );
143         if( bs->written < -offset )
144             dst_offset = 0;
145         else
146             dst_offset = bs->written + offset;
147     }
148     return dst_offset;
149 }
150 
151 /* TODO: Support offset > INT64_MAX */
lsmash_bs_write_seek(lsmash_bs_t * bs,int64_t offset,int whence)152 int64_t lsmash_bs_write_seek( lsmash_bs_t *bs, int64_t offset, int whence )
153 {
154     if( bs->unseekable )
155         return LSMASH_ERR_NAMELESS;
156     if( whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END )
157         return LSMASH_ERR_FUNCTION_PARAM;
158     /* Try to seek the stream. */
159     int64_t ret = bs->seek( bs->stream, offset, whence );
160     if( ret < 0 )
161         return ret;
162     bs->offset = bs_estimate_seek_offset( bs, offset, whence );
163     bs->eof    = 0;
164     bs->eob    = 0;
165     return ret;
166 }
167 
168 /* TODO: Support offset > INT64_MAX */
lsmash_bs_read_seek(lsmash_bs_t * bs,int64_t offset,int whence)169 int64_t lsmash_bs_read_seek( lsmash_bs_t *bs, int64_t offset, int whence )
170 {
171     if( whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END )
172         return LSMASH_ERR_FUNCTION_PARAM;
173     if( whence == SEEK_CUR )
174         offset -= lsmash_bs_get_remaining_buffer_size( bs );
175     /* Check whether we can seek on the buffer. */
176     if( !bs->buffer.unseekable )
177     {
178         assert( bs->offset >= bs->buffer.store );
179         uint64_t dst_offset = bs_estimate_seek_offset( bs, offset, whence );
180         uint64_t offset_s = bs->offset - bs->buffer.store;
181         uint64_t offset_e = bs->offset;
182         if( bs->unseekable || (dst_offset >= offset_s && dst_offset < offset_e) )
183         {
184             /* OK, we can. So, seek on the buffer. */
185             bs->buffer.pos = dst_offset - offset_s;
186             bs->eob        = 0;
187             return lsmash_bs_get_stream_pos( bs );
188         }
189     }
190     if( bs->unseekable )
191         return LSMASH_ERR_NAMELESS;
192     /* Try to seek the stream. */
193     int64_t ret = bs->seek( bs->stream, offset, whence );
194     if( ret < 0 )
195         return ret;
196     bs->offset  = ret;
197     bs->written = LSMASH_MAX( bs->written, bs->offset );
198     bs->eof     = 0;
199     bs->eob     = 0;
200     /* The data on the buffer is invalid. */
201     lsmash_bs_empty( bs );
202     return ret;
203 }
204 
bs_dispose_past_data(lsmash_bs_t * bs)205 static void bs_dispose_past_data( lsmash_bs_t *bs )
206 {
207     /* Move remainder bytes. */
208     assert( bs->buffer.store >= bs->buffer.pos );
209     size_t remainder = lsmash_bs_get_remaining_buffer_size( bs );
210     if( bs->buffer.pos && remainder )
211         memmove( lsmash_bs_get_buffer_data_start( bs ), lsmash_bs_get_buffer_data( bs ), remainder );
212     bs->buffer.store = remainder;
213     bs->buffer.pos   = 0;
214 }
215 
216 /*---- bitstream writer ----*/
lsmash_bs_put_byte(lsmash_bs_t * bs,uint8_t value)217 void lsmash_bs_put_byte( lsmash_bs_t *bs, uint8_t value )
218 {
219     if( bs->buffer.internal
220      || bs->buffer.data )
221     {
222         bs_alloc( bs, bs->buffer.store + 1 );
223         if( bs->error )
224             return;
225         bs->buffer.data[ bs->buffer.store ] = value;
226     }
227     ++ bs->buffer.store;
228 }
229 
lsmash_bs_put_bytes(lsmash_bs_t * bs,uint32_t size,void * value)230 void lsmash_bs_put_bytes( lsmash_bs_t *bs, uint32_t size, void *value )
231 {
232     if( size == 0 || !value )
233         return;
234     if( bs->buffer.internal
235      || bs->buffer.data )
236     {
237         bs_alloc( bs, bs->buffer.store + size );
238         if( bs->error )
239             return;
240         memcpy( lsmash_bs_get_buffer_data_end( bs ), value, size );
241     }
242     bs->buffer.store += size;
243 }
244 
lsmash_bs_put_be16(lsmash_bs_t * bs,uint16_t value)245 void lsmash_bs_put_be16( lsmash_bs_t *bs, uint16_t value )
246 {
247     lsmash_bs_put_byte( bs, value >> 8 );
248     lsmash_bs_put_byte( bs, value );
249 }
250 
lsmash_bs_put_be24(lsmash_bs_t * bs,uint32_t value)251 void lsmash_bs_put_be24( lsmash_bs_t *bs, uint32_t value )
252 {
253     lsmash_bs_put_byte( bs, value >> 16 );
254     lsmash_bs_put_be16( bs, value );
255 }
256 
lsmash_bs_put_be32(lsmash_bs_t * bs,uint32_t value)257 void lsmash_bs_put_be32( lsmash_bs_t *bs, uint32_t value )
258 {
259     lsmash_bs_put_be16( bs, value >> 16 );
260     lsmash_bs_put_be16( bs, value );
261 }
262 
lsmash_bs_put_be64(lsmash_bs_t * bs,uint64_t value)263 void lsmash_bs_put_be64( lsmash_bs_t *bs, uint64_t value )
264 {
265     lsmash_bs_put_be32( bs, value >> 32 );
266     lsmash_bs_put_be32( bs, value );
267 }
268 
lsmash_bs_put_byte_from_64(lsmash_bs_t * bs,uint64_t value)269 void lsmash_bs_put_byte_from_64( lsmash_bs_t *bs, uint64_t value )
270 {
271     lsmash_bs_put_byte( bs, value );
272 }
273 
lsmash_bs_put_be16_from_64(lsmash_bs_t * bs,uint64_t value)274 void lsmash_bs_put_be16_from_64( lsmash_bs_t *bs, uint64_t value )
275 {
276     lsmash_bs_put_be16( bs, value );
277 }
278 
lsmash_bs_put_be24_from_64(lsmash_bs_t * bs,uint64_t value)279 void lsmash_bs_put_be24_from_64( lsmash_bs_t *bs, uint64_t value )
280 {
281     lsmash_bs_put_be24( bs, value );
282 }
283 
lsmash_bs_put_be32_from_64(lsmash_bs_t * bs,uint64_t value)284 void lsmash_bs_put_be32_from_64( lsmash_bs_t *bs, uint64_t value )
285 {
286     lsmash_bs_put_be32( bs, value );
287 }
288 
lsmash_bs_put_le16(lsmash_bs_t * bs,uint16_t value)289 void lsmash_bs_put_le16( lsmash_bs_t *bs, uint16_t value )
290 {
291     lsmash_bs_put_byte( bs, value );
292     lsmash_bs_put_byte( bs, value >> 8 );
293 }
294 
lsmash_bs_put_le32(lsmash_bs_t * bs,uint32_t value)295 void lsmash_bs_put_le32( lsmash_bs_t *bs, uint32_t value )
296 {
297     lsmash_bs_put_le16( bs, value );
298     lsmash_bs_put_le16( bs, value >> 16 );
299 }
300 
lsmash_bs_flush_buffer(lsmash_bs_t * bs)301 int lsmash_bs_flush_buffer( lsmash_bs_t *bs )
302 {
303     if( !bs )
304         return LSMASH_ERR_FUNCTION_PARAM;
305     if( bs->buffer.store == 0
306      || (bs->stream && bs->write && !bs->buffer.data) )
307         return 0;
308     if( bs->error
309      || (bs->stream && bs->write && bs->write( bs->stream, lsmash_bs_get_buffer_data_start( bs ), bs->buffer.store ) != bs->buffer.store) )
310     {
311         bs_buffer_free( bs );
312         bs->error = 1;
313         return LSMASH_ERR_NAMELESS;
314     }
315     if( bs->write )
316     {
317         bs->written += bs->buffer.store;
318         bs->offset  += bs->buffer.store;
319     }
320     bs->buffer.store = 0;
321     return 0;
322 }
323 
lsmash_bs_write_data(lsmash_bs_t * bs,const uint8_t * buf,size_t size)324 int lsmash_bs_write_data( lsmash_bs_t *bs, const uint8_t *buf, size_t size )
325 {
326     if( !bs || size > INT_MAX )
327         return LSMASH_ERR_FUNCTION_PARAM;
328     if( !buf || size == 0 )
329         return 0;
330     if( bs->error || !bs->stream )
331     {
332         bs_buffer_free( bs );
333         bs->error = 1;
334         return LSMASH_ERR_NAMELESS;
335     }
336     int write_size = bs->write( bs->stream, (uint8_t *)buf, size );
337     bs->written += write_size;
338     bs->offset  += write_size;
339     return write_size != size ? LSMASH_ERR_NAMELESS : 0;
340 }
341 
lsmash_bs_export_data(lsmash_bs_t * bs,uint32_t * length)342 void *lsmash_bs_export_data( lsmash_bs_t *bs, uint32_t *length )
343 {
344     if( !bs || !bs->buffer.data || bs->buffer.store == 0 || bs->error )
345         return NULL;
346     void *buf = lsmash_memdup( lsmash_bs_get_buffer_data_start( bs ), bs->buffer.store );
347     if( !buf )
348         return NULL;
349     if( length )
350         *length = bs->buffer.store;
351     return buf;
352 }
353 /*---- ----*/
354 
355 /*---- bitstream reader ----*/
bs_fill_buffer(lsmash_bs_t * bs)356 static void bs_fill_buffer( lsmash_bs_t *bs )
357 {
358     if( bs->eof || bs->error )
359         return;
360     if( !bs->read || !bs->stream || bs->buffer.max_size == 0 )
361     {
362         bs->eof = 1;
363         return;
364     }
365     if( !bs->buffer.data )
366     {
367         bs_alloc( bs, bs->buffer.max_size );
368         if( bs->error )
369             return;
370     }
371     /* Read bytes from the stream to fill the buffer. */
372     bs_dispose_past_data( bs );
373     while( bs->buffer.alloc > bs->buffer.store )
374     {
375         uint64_t invalid_buffer_size = bs->buffer.alloc - bs->buffer.store;
376         int max_read_size = LSMASH_MIN( invalid_buffer_size, bs->buffer.max_size );
377         int read_size = bs->read( bs->stream, lsmash_bs_get_buffer_data_end( bs ), max_read_size );
378         if( read_size == 0 )
379         {
380             bs->eof = 1;
381             return;
382         }
383         else if( read_size < 0 )
384         {
385             bs->error = 1;
386             return;
387         }
388         bs->buffer.unseekable = 0;
389         bs->buffer.store += read_size;
390         bs->offset       += read_size;
391         bs->written = LSMASH_MAX( bs->written, bs->offset );
392     }
393 }
394 
lsmash_bs_show_byte(lsmash_bs_t * bs,uint32_t offset)395 uint8_t lsmash_bs_show_byte( lsmash_bs_t *bs, uint32_t offset )
396 {
397     if( bs->error )
398         return 0;
399     if( offset >= lsmash_bs_get_remaining_buffer_size( bs ) )
400     {
401         bs_fill_buffer( bs );
402         if( bs->error )
403             return 0;
404         if( offset >= lsmash_bs_get_remaining_buffer_size( bs ) )
405         {
406             if( bs->eof )
407                 /* No more read from both the stream and the buffer. */
408                 return 0;
409             /* We need increase the buffer size. */
410             bs_alloc( bs, bs->buffer.pos + offset + 1 );
411             bs_fill_buffer( bs );
412             if( bs->error )
413                 return 0;
414         }
415     }
416     return bs->buffer.data[ bs->buffer.pos + offset ];
417 }
418 
lsmash_bs_show_be16(lsmash_bs_t * bs,uint32_t offset)419 uint16_t lsmash_bs_show_be16( lsmash_bs_t *bs, uint32_t offset )
420 {
421     return ((uint16_t)lsmash_bs_show_byte( bs, offset     ) << 8)
422          | ((uint16_t)lsmash_bs_show_byte( bs, offset + 1 ));
423 }
424 
lsmash_bs_show_be24(lsmash_bs_t * bs,uint32_t offset)425 uint32_t lsmash_bs_show_be24( lsmash_bs_t *bs, uint32_t offset )
426 {
427     return ((uint32_t)lsmash_bs_show_byte( bs, offset     ) << 16)
428          | ((uint32_t)lsmash_bs_show_byte( bs, offset + 1 ) <<  8)
429          | ((uint32_t)lsmash_bs_show_byte( bs, offset + 2 ));
430 }
431 
lsmash_bs_show_be32(lsmash_bs_t * bs,uint32_t offset)432 uint32_t lsmash_bs_show_be32( lsmash_bs_t *bs, uint32_t offset )
433 {
434     return ((uint32_t)lsmash_bs_show_byte( bs, offset     ) << 24)
435          | ((uint32_t)lsmash_bs_show_byte( bs, offset + 1 ) << 16)
436          | ((uint32_t)lsmash_bs_show_byte( bs, offset + 2 ) <<  8)
437          | ((uint32_t)lsmash_bs_show_byte( bs, offset + 3 ));
438 }
439 
lsmash_bs_show_be64(lsmash_bs_t * bs,uint32_t offset)440 uint64_t lsmash_bs_show_be64( lsmash_bs_t *bs, uint32_t offset )
441 {
442     return ((uint64_t)lsmash_bs_show_byte( bs, offset     ) << 56)
443          | ((uint64_t)lsmash_bs_show_byte( bs, offset + 1 ) << 48)
444          | ((uint64_t)lsmash_bs_show_byte( bs, offset + 2 ) << 40)
445          | ((uint64_t)lsmash_bs_show_byte( bs, offset + 3 ) << 32)
446          | ((uint64_t)lsmash_bs_show_byte( bs, offset + 4 ) << 24)
447          | ((uint64_t)lsmash_bs_show_byte( bs, offset + 5 ) << 16)
448          | ((uint64_t)lsmash_bs_show_byte( bs, offset + 6 ) <<  8)
449          | ((uint64_t)lsmash_bs_show_byte( bs, offset + 7 ));
450 }
451 
lsmash_bs_get_byte(lsmash_bs_t * bs)452 uint8_t lsmash_bs_get_byte( lsmash_bs_t *bs )
453 {
454     if( bs->eob || bs->error )
455         return 0;
456     assert( bs->buffer.pos <= bs->buffer.store );
457     if( bs->buffer.pos == bs->buffer.store )
458     {
459         bs_fill_buffer( bs );
460         if( bs->error )
461             return 0;
462         if( bs->buffer.pos == bs->buffer.store && bs->eof )
463         {
464             /* No more read from both the stream and the buffer. */
465             bs->eob = 1;
466             return 0;
467         }
468     }
469     ++ bs->buffer.count;    /* increment counter */
470     return bs->buffer.data[ bs->buffer.pos ++ ];
471 }
472 
lsmash_bs_skip_bytes(lsmash_bs_t * bs,uint32_t size)473 void lsmash_bs_skip_bytes( lsmash_bs_t *bs, uint32_t size )
474 {
475     if( bs->eob || bs->error || size == 0 )
476         return;
477     uint64_t remainder;
478     uint64_t offset = 0;
479     while( size > lsmash_bs_get_remaining_buffer_size( bs ) )
480     {
481         remainder = lsmash_bs_get_remaining_buffer_size( bs );
482         offset += remainder;
483         size   -= remainder;
484         bs->buffer.pos = bs->buffer.store;
485         if( bs->eof )
486         {
487             /* No more read from both the stream and the buffer. */
488             bs->eob = 1;
489             break;
490         }
491         else
492         {
493             bs_fill_buffer( bs );
494             if( bs->error )
495                 break;
496         }
497     }
498     remainder = LSMASH_MIN( size, lsmash_bs_get_remaining_buffer_size( bs ) );
499     offset           += remainder;
500     bs->buffer.pos   += remainder;
501     bs->buffer.count += offset;
502 }
503 
lsmash_bs_skip_bytes_64(lsmash_bs_t * bs,uint64_t size)504 void lsmash_bs_skip_bytes_64( lsmash_bs_t *bs, uint64_t size )
505 {
506     while( size )
507     {
508         uint64_t skip_bytes = LSMASH_MIN( size, UINT32_MAX );
509         lsmash_bs_skip_bytes( bs, (uint32_t)skip_bytes );
510         size -= skip_bytes;
511         if( bs->eob )
512             return;
513     }
514 }
515 
bs_get_bytes(lsmash_bs_t * bs,uint32_t size,uint8_t * buf)516 static int64_t bs_get_bytes( lsmash_bs_t *bs, uint32_t size, uint8_t *buf )
517 {
518     size_t    remainder;
519     size_t    remain_size = size;
520     uintptr_t offset      = 0;
521     while( remain_size > lsmash_bs_get_remaining_buffer_size( bs ) )
522     {
523         remainder = lsmash_bs_get_remaining_buffer_size( bs );
524         memcpy( buf + offset, lsmash_bs_get_buffer_data( bs ), remainder );
525         offset      += remainder;
526         remain_size -= remainder;
527         bs->buffer.pos = bs->buffer.store;
528         if( bs->eof )
529         {
530             /* No more read from both the stream and the buffer. */
531             bs->eob = 1;
532             break;
533         }
534         else
535         {
536             bs_fill_buffer( bs );
537             if( bs->error )
538             {
539                 bs->buffer.count += offset;
540                 return LSMASH_ERR_NAMELESS;
541             }
542         }
543     }
544     remainder = LSMASH_MIN( remain_size, lsmash_bs_get_remaining_buffer_size( bs ) );
545     memcpy( buf + offset, lsmash_bs_get_buffer_data( bs ), remainder );
546     offset           += remainder;
547     bs->buffer.pos   += remainder;
548     bs->buffer.count += offset;
549     if( offset < size )
550         memset( buf + offset, 0, size - offset );
551     return (int64_t)offset;
552 }
553 
lsmash_bs_get_bytes(lsmash_bs_t * bs,uint32_t size)554 uint8_t *lsmash_bs_get_bytes( lsmash_bs_t *bs, uint32_t size )
555 {
556     if( bs->eob || bs->error || size == 0 )
557         return NULL;
558     uint8_t *value = lsmash_malloc( size );
559     if( !value )
560     {
561         bs->error = 1;
562         return NULL;
563     }
564     if( bs_get_bytes( bs, size, value ) < 0 )
565     {
566         lsmash_free( value );
567         return NULL;
568     }
569     return value;
570 }
571 
lsmash_bs_get_bytes_ex(lsmash_bs_t * bs,uint32_t size,uint8_t * value)572 int64_t lsmash_bs_get_bytes_ex( lsmash_bs_t *bs, uint32_t size, uint8_t *value )
573 {
574     if( size == 0 )
575         return 0;
576     if( bs->eob || bs->error )
577         return LSMASH_ERR_NAMELESS;
578     return bs_get_bytes( bs, size, value );
579 }
580 
lsmash_bs_get_be16(lsmash_bs_t * bs)581 uint16_t lsmash_bs_get_be16( lsmash_bs_t *bs )
582 {
583     uint16_t    value = lsmash_bs_get_byte( bs );
584     return (value<<8) | lsmash_bs_get_byte( bs );
585 }
586 
lsmash_bs_get_be24(lsmash_bs_t * bs)587 uint32_t lsmash_bs_get_be24( lsmash_bs_t *bs )
588 {
589     uint32_t     value = lsmash_bs_get_byte( bs );
590     return (value<<16) | lsmash_bs_get_be16( bs );
591 }
592 
lsmash_bs_get_be32(lsmash_bs_t * bs)593 uint32_t lsmash_bs_get_be32( lsmash_bs_t *bs )
594 {
595     uint32_t     value = lsmash_bs_get_be16( bs );
596     return (value<<16) | lsmash_bs_get_be16( bs );
597 }
598 
lsmash_bs_get_be64(lsmash_bs_t * bs)599 uint64_t lsmash_bs_get_be64( lsmash_bs_t *bs )
600 {
601     uint64_t     value = lsmash_bs_get_be32( bs );
602     return (value<<32) | lsmash_bs_get_be32( bs );
603 }
604 
lsmash_bs_get_byte_to_64(lsmash_bs_t * bs)605 uint64_t lsmash_bs_get_byte_to_64( lsmash_bs_t *bs )
606 {
607     return lsmash_bs_get_byte( bs );
608 }
609 
lsmash_bs_get_be16_to_64(lsmash_bs_t * bs)610 uint64_t lsmash_bs_get_be16_to_64( lsmash_bs_t *bs )
611 {
612     return lsmash_bs_get_be16( bs );
613 }
614 
lsmash_bs_get_be24_to_64(lsmash_bs_t * bs)615 uint64_t lsmash_bs_get_be24_to_64( lsmash_bs_t *bs )
616 {
617     return lsmash_bs_get_be24( bs );
618 }
619 
lsmash_bs_get_be32_to_64(lsmash_bs_t * bs)620 uint64_t lsmash_bs_get_be32_to_64( lsmash_bs_t *bs )
621 {
622     return lsmash_bs_get_be32( bs );
623 }
624 
lsmash_bs_get_le16(lsmash_bs_t * bs)625 uint16_t lsmash_bs_get_le16( lsmash_bs_t *bs )
626 {
627     uint16_t value = lsmash_bs_get_byte( bs );
628     return value | (lsmash_bs_get_byte( bs ) << 8);
629 }
630 
lsmash_bs_get_le32(lsmash_bs_t * bs)631 uint32_t lsmash_bs_get_le32( lsmash_bs_t *bs )
632 {
633     uint32_t value = lsmash_bs_get_le16( bs );
634     return value | (lsmash_bs_get_le16( bs ) << 16);
635 }
636 
lsmash_bs_read(lsmash_bs_t * bs,uint32_t size)637 int lsmash_bs_read( lsmash_bs_t *bs, uint32_t size )
638 {
639     if( !bs || size > INT_MAX )
640         return LSMASH_ERR_FUNCTION_PARAM;
641     if( size == 0 )
642         return 0;
643     bs_alloc( bs, bs->buffer.store + size );
644     if( bs->error || !bs->stream )
645     {
646         bs->error = 1;
647         return LSMASH_ERR_NAMELESS;
648     }
649     int read_size = bs->read( bs->stream, lsmash_bs_get_buffer_data_end( bs ), size );
650     if( read_size == 0 )
651     {
652         bs->eof = 1;
653         return 0;
654     }
655     else if( read_size < 0 )
656     {
657         bs->error = 1;
658         return LSMASH_ERR_NAMELESS;
659     }
660     bs->buffer.store += read_size;
661     bs->offset       += read_size;
662     bs->written = LSMASH_MAX( bs->written, bs->offset );
663     return read_size;
664 }
665 
lsmash_bs_read_data(lsmash_bs_t * bs,uint8_t * buf,size_t * size)666 int lsmash_bs_read_data( lsmash_bs_t *bs, uint8_t *buf, size_t *size )
667 {
668     if( !bs || !size || *size > INT_MAX )
669         return LSMASH_ERR_FUNCTION_PARAM;
670     if( !buf || *size == 0 )
671         return 0;
672     if( bs->error || !bs->stream )
673     {
674         bs->error = 1;
675         return LSMASH_ERR_NAMELESS;
676     }
677     int read_size = bs->read( bs->stream, buf, *size );
678     if( read_size == 0 )
679         bs->eof = 1;
680     else if( read_size < 0 )
681     {
682         bs->error = 1;
683         return LSMASH_ERR_NAMELESS;
684     }
685     bs->buffer.unseekable = 1;
686     bs->offset += read_size;
687     *size       = read_size;
688     bs->written = LSMASH_MAX( bs->written, bs->offset );
689     return 0;
690 }
691 
lsmash_bs_import_data(lsmash_bs_t * bs,void * data,uint32_t length)692 int lsmash_bs_import_data( lsmash_bs_t *bs, void *data, uint32_t length )
693 {
694     if( !bs || !data || length == 0 )
695         return LSMASH_ERR_FUNCTION_PARAM;
696     if( bs->error )
697         return LSMASH_ERR_NAMELESS;
698     bs_alloc( bs, bs->buffer.store + length );
699     if( bs->error || !bs->buffer.data ) /* means, failed to alloc. */
700     {
701         bs_buffer_free( bs );
702         return LSMASH_ERR_NAMELESS;
703     }
704     memcpy( lsmash_bs_get_buffer_data_end( bs ), data, length );
705     bs->buffer.store += length;
706     return 0;
707 }
708