configure: Add api version to mingw shared library name.
[L-SMASH.git] / common / bits.c
blob5d02f34faf7baaa6d0f9d4e2f2c0fab20aca89f2
1 /*****************************************************************************
2 * bits.c
3 *****************************************************************************
4 * Copyright (C) 2010-2015 L-SMASH project
6 * Authors: Takashi Hirata <silverfilain@gmail.com>
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.
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 *****************************************************************************/
21 /* This file is available under an ISC license. */
23 #include "internal.h" /* must be placed first */
25 void lsmash_bits_init( lsmash_bits_t *bits, lsmash_bs_t *bs )
27 debug_if( !bits || !bs )
28 return;
29 bits->bs = bs;
30 bits->store = 0;
31 bits->cache = 0;
34 lsmash_bits_t *lsmash_bits_create( lsmash_bs_t *bs )
36 debug_if( !bs )
37 return NULL;
38 lsmash_bits_t *bits = (lsmash_bits_t *)lsmash_malloc( sizeof(lsmash_bits_t) );
39 if( !bits )
40 return NULL;
41 lsmash_bits_init( bits, bs );
42 return bits;
45 /* Must be used ONLY for bits struct created with isom_create_bits.
46 * Otherwise, just lsmash_free() the bits struct. */
47 void lsmash_bits_cleanup( lsmash_bits_t *bits )
49 debug_if( !bits )
50 return;
51 lsmash_free( bits );
54 void lsmash_bits_empty( lsmash_bits_t *bits )
56 debug_if( !bits )
57 return;
58 lsmash_bs_empty( bits->bs );
59 bits->store = 0;
60 bits->cache = 0;
63 #define BITS_IN_BYTE 8
64 void lsmash_bits_put_align( lsmash_bits_t *bits )
66 debug_if( !bits )
67 return;
68 if( !bits->store )
69 return;
70 lsmash_bs_put_byte( bits->bs, bits->cache << ( BITS_IN_BYTE - bits->store ) );
73 void lsmash_bits_get_align( lsmash_bits_t *bits )
75 debug_if( !bits )
76 return;
77 bits->store = 0;
78 bits->cache = 0;
81 /* we can change value's type to unsigned int for 64-bit operation if needed. */
82 static inline uint8_t lsmash_bits_mask_lsb8( uint32_t value, uint32_t width )
84 return (uint8_t)( value & ~( ~0U << width ) );
87 void lsmash_bits_put( lsmash_bits_t *bits, uint32_t width, uint64_t value )
89 debug_if( !bits || !width )
90 return;
91 if( bits->store )
93 if( bits->store + width < BITS_IN_BYTE )
95 /* cache can contain all of value's bits. */
96 bits->cache <<= width;
97 bits->cache |= lsmash_bits_mask_lsb8( value, width );
98 bits->store += width;
99 return;
101 /* flush cache with value's some leading bits. */
102 uint32_t free_bits = BITS_IN_BYTE - bits->store;
103 bits->cache <<= free_bits;
104 bits->cache |= lsmash_bits_mask_lsb8( value >> (width -= free_bits), free_bits );
105 lsmash_bs_put_byte( bits->bs, bits->cache );
106 bits->store = 0;
107 bits->cache = 0;
109 /* cache is empty here. */
110 /* byte unit operation. */
111 while( width > BITS_IN_BYTE )
112 lsmash_bs_put_byte( bits->bs, (uint8_t)(value >> (width -= BITS_IN_BYTE)) );
113 /* bit unit operation for residual. */
114 if( width )
116 bits->cache = lsmash_bits_mask_lsb8( value, width );
117 bits->store = width;
121 uint64_t lsmash_bits_get( lsmash_bits_t *bits, uint32_t width )
123 debug_if( !bits || !width )
124 return 0;
125 uint64_t value = 0;
126 if( bits->store )
128 if( bits->store >= width )
130 /* cache contains all of bits required. */
131 bits->store -= width;
132 return lsmash_bits_mask_lsb8( bits->cache >> bits->store, width );
134 /* fill value's leading bits with cache's residual. */
135 value = lsmash_bits_mask_lsb8( bits->cache, bits->store );
136 width -= bits->store;
137 bits->store = 0;
138 bits->cache = 0;
140 /* cache is empty here. */
141 /* byte unit operation. */
142 while( width > BITS_IN_BYTE )
144 value <<= BITS_IN_BYTE;
145 width -= BITS_IN_BYTE;
146 value |= lsmash_bs_get_byte( bits->bs );
148 /* bit unit operation for residual. */
149 if( width )
151 bits->cache = lsmash_bs_get_byte( bits->bs );
152 bits->store = BITS_IN_BYTE - width;
153 value <<= width;
154 value |= lsmash_bits_mask_lsb8( bits->cache >> bits->store, width );
156 return value;
159 void *lsmash_bits_export_data( lsmash_bits_t *bits, uint32_t *length )
161 lsmash_bits_put_align( bits );
162 return lsmash_bs_export_data( bits->bs, length );
165 int lsmash_bits_import_data( lsmash_bits_t *bits, void *data, uint32_t length )
167 return lsmash_bs_import_data( bits->bs, data, length );
170 /****
171 bitstream with bytestream for adhoc operation
172 ****/
174 lsmash_bits_t *lsmash_bits_adhoc_create()
176 lsmash_bs_t *bs = lsmash_bs_create();
177 if( !bs )
178 return NULL;
179 lsmash_bits_t *bits = lsmash_bits_create( bs );
180 if( !bits )
182 lsmash_bs_cleanup( bs );
183 return NULL;
185 return bits;
188 void lsmash_bits_adhoc_cleanup( lsmash_bits_t *bits )
190 if( !bits )
191 return;
192 lsmash_bs_cleanup( bits->bs );
193 lsmash_bits_cleanup( bits );