1 /*****************************************************************************
2 * bytes.h
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 /*---- bytestream ----*/
24 #define BS_MAX_DEFAULT_READ_SIZE (4 * 1024 * 1024)
25
26 typedef struct
27 {
28 int unseekable; /* If set to 1, the buffer is unseekable. */
29 int internal; /* If set to 1, the buffer is allocated on heap internally.
30 * The pointer to the buffer shall not be changed by any method other than internal allocation. */
31 uint8_t *data; /* the pointer to the buffer for reading/writing */
32 size_t store; /* valid data size on the buffer */
33 size_t alloc; /* total buffer size including invalid area */
34 size_t pos; /* the data position on the buffer to be read next */
35 size_t max_size; /* the maximum number of bytes for reading from the stream at one time */
36 uint64_t count; /* counter for arbitrary usage */
37 } lsmash_buffer_t;
38
39 typedef struct
40 {
41 void *stream; /* I/O stream */
42 uint8_t eof; /* If set to 1, the stream reached EOF. */
43 uint8_t eob; /* if set to 1, we cannot read more bytes from the stream and the buffer until any seek. */
44 uint8_t error; /* If set to 1, any error is detected. */
45 uint8_t unseekable; /* If set to 1, the stream is unseekable. */
46 uint64_t written; /* the number of bytes written into 'stream' already */
47 uint64_t offset; /* the current position in the 'stream'
48 * the number of bytes from the beginning */
49 lsmash_buffer_t buffer;
50 int (*read) ( void *opaque, uint8_t *buf, int size );
51 int (*write)( void *opaque, uint8_t *buf, int size );
52 int64_t (*seek) ( void *opaque, int64_t offset, int whence );
53 } lsmash_bs_t;
54
lsmash_bs_reset_counter(lsmash_bs_t * bs)55 static inline void lsmash_bs_reset_counter( lsmash_bs_t *bs )
56 {
57 bs->buffer.count = 0;
58 }
59
lsmash_bs_count(lsmash_bs_t * bs)60 static inline uint64_t lsmash_bs_count( lsmash_bs_t *bs )
61 {
62 return bs->buffer.count;
63 }
64
lsmash_bs_get_remaining_buffer_size(lsmash_bs_t * bs)65 static inline uint64_t lsmash_bs_get_remaining_buffer_size( lsmash_bs_t *bs )
66 {
67 assert( bs->buffer.store >= bs->buffer.pos );
68 return bs->buffer.store - bs->buffer.pos;
69 }
70
lsmash_bs_get_buffer_data(lsmash_bs_t * bs)71 static inline uint8_t *lsmash_bs_get_buffer_data( lsmash_bs_t *bs )
72 {
73 return bs->buffer.data + (uintptr_t)bs->buffer.pos;
74 }
75
lsmash_bs_get_buffer_data_start(lsmash_bs_t * bs)76 static inline uint8_t *lsmash_bs_get_buffer_data_start( lsmash_bs_t *bs )
77 {
78 return bs->buffer.data;
79 }
80
lsmash_bs_get_buffer_data_end(lsmash_bs_t * bs)81 static inline uint8_t *lsmash_bs_get_buffer_data_end( lsmash_bs_t *bs )
82 {
83 return bs->buffer.data + (uintptr_t)bs->buffer.store;
84 }
85
lsmash_bs_get_pos(lsmash_bs_t * bs)86 static inline uint64_t lsmash_bs_get_pos( lsmash_bs_t *bs )
87 {
88 return bs->buffer.pos;
89 }
90
lsmash_bs_get_stream_pos(lsmash_bs_t * bs)91 static inline uint64_t lsmash_bs_get_stream_pos( lsmash_bs_t *bs )
92 {
93 assert( bs->buffer.store <= bs->offset );
94 return bs->offset - lsmash_bs_get_remaining_buffer_size( bs );
95 }
96
lsmash_bs_get_valid_data_size(lsmash_bs_t * bs)97 static inline size_t lsmash_bs_get_valid_data_size( lsmash_bs_t *bs )
98 {
99 return bs->buffer.store;
100 }
101
102 lsmash_bs_t *lsmash_bs_create( void );
103 void lsmash_bs_cleanup( lsmash_bs_t *bs );
104 int lsmash_bs_set_empty_stream( lsmash_bs_t *bs, uint8_t *data, size_t size );
105 void lsmash_bs_empty( lsmash_bs_t *bs );
106 int64_t lsmash_bs_write_seek( lsmash_bs_t *bs, int64_t offset, int whence );
107 int64_t lsmash_bs_read_seek( lsmash_bs_t *bs, int64_t offset, int whence );
108
109 /*---- bytestream writer ----*/
110 void lsmash_bs_put_byte( lsmash_bs_t *bs, uint8_t value );
111 void lsmash_bs_put_bytes( lsmash_bs_t *bs, uint32_t size, void *value );
112 void lsmash_bs_put_be16( lsmash_bs_t *bs, uint16_t value );
113 void lsmash_bs_put_be24( lsmash_bs_t *bs, uint32_t value );
114 void lsmash_bs_put_be32( lsmash_bs_t *bs, uint32_t value );
115 void lsmash_bs_put_be64( lsmash_bs_t *bs, uint64_t value );
116 void lsmash_bs_put_byte_from_64( lsmash_bs_t *bs, uint64_t value );
117 void lsmash_bs_put_be16_from_64( lsmash_bs_t *bs, uint64_t value );
118 void lsmash_bs_put_be24_from_64( lsmash_bs_t *bs, uint64_t value );
119 void lsmash_bs_put_be32_from_64( lsmash_bs_t *bs, uint64_t value );
120 void lsmash_bs_put_le16( lsmash_bs_t *bs, uint16_t value );
121 void lsmash_bs_put_le32( lsmash_bs_t *bs, uint32_t value );
122 int lsmash_bs_flush_buffer( lsmash_bs_t *bs );
123 int lsmash_bs_write_data( lsmash_bs_t *bs, const uint8_t *buf, size_t size );
124 void *lsmash_bs_export_data( lsmash_bs_t *bs, uint32_t *length );
125
126 /*---- bytestream reader ----*/
127 uint8_t lsmash_bs_show_byte( lsmash_bs_t *bs, uint32_t offset );
128 uint16_t lsmash_bs_show_be16( lsmash_bs_t *bs, uint32_t offset );
129 uint32_t lsmash_bs_show_be24( lsmash_bs_t *bs, uint32_t offset );
130 uint32_t lsmash_bs_show_be32( lsmash_bs_t *bs, uint32_t offset );
131 uint64_t lsmash_bs_show_be64( lsmash_bs_t *bs, uint32_t offset );
132 uint8_t lsmash_bs_get_byte( lsmash_bs_t *bs );
133 void lsmash_bs_skip_bytes( lsmash_bs_t *bs, uint32_t size );
134 void lsmash_bs_skip_bytes_64( lsmash_bs_t *bs, uint64_t size );
135 uint8_t *lsmash_bs_get_bytes( lsmash_bs_t *bs, uint32_t size );
136 int64_t lsmash_bs_get_bytes_ex( lsmash_bs_t *bs, uint32_t size, uint8_t *value );
137 uint16_t lsmash_bs_get_be16( lsmash_bs_t *bs );
138 uint32_t lsmash_bs_get_be24( lsmash_bs_t *bs );
139 uint32_t lsmash_bs_get_be32( lsmash_bs_t *bs );
140 uint64_t lsmash_bs_get_be64( lsmash_bs_t *bs );
141 uint64_t lsmash_bs_get_byte_to_64( lsmash_bs_t *bs );
142 uint64_t lsmash_bs_get_be16_to_64( lsmash_bs_t *bs );
143 uint64_t lsmash_bs_get_be24_to_64( lsmash_bs_t *bs );
144 uint64_t lsmash_bs_get_be32_to_64( lsmash_bs_t *bs );
145 uint16_t lsmash_bs_get_le16( lsmash_bs_t *bs );
146 uint32_t lsmash_bs_get_le32( lsmash_bs_t *bs );
147 int lsmash_bs_read( lsmash_bs_t *bs, uint32_t size );
148 int lsmash_bs_read_data( lsmash_bs_t *bs, uint8_t *buf, size_t *size );
149 int lsmash_bs_import_data( lsmash_bs_t *bs, void *data, uint32_t length );
150
151 /* Check if the given offset reaches both EOF of the stream and the end of the buffer. */
lsmash_bs_is_end(lsmash_bs_t * bs,uint32_t offset)152 static inline int lsmash_bs_is_end( lsmash_bs_t *bs, uint32_t offset )
153 {
154 lsmash_bs_show_byte( bs, offset );
155 return bs->eof && (offset >= lsmash_bs_get_remaining_buffer_size( bs ));
156 }
157
158 /* Check if an error has occurred. */
lsmash_bs_is_error(lsmash_bs_t * bs)159 static inline int lsmash_bs_is_error( lsmash_bs_t *bs )
160 {
161 return bs->error;
162 }
163