1660f49b0SGreg Tucker /**********************************************************************
2660f49b0SGreg Tucker Copyright(c) 2011-2016 Intel Corporation All rights reserved.
3660f49b0SGreg Tucker
4660f49b0SGreg Tucker Redistribution and use in source and binary forms, with or without
5660f49b0SGreg Tucker modification, are permitted provided that the following conditions
6660f49b0SGreg Tucker are met:
7660f49b0SGreg Tucker * Redistributions of source code must retain the above copyright
8660f49b0SGreg Tucker notice, this list of conditions and the following disclaimer.
9660f49b0SGreg Tucker * Redistributions in binary form must reproduce the above copyright
10660f49b0SGreg Tucker notice, this list of conditions and the following disclaimer in
11660f49b0SGreg Tucker the documentation and/or other materials provided with the
12660f49b0SGreg Tucker distribution.
13660f49b0SGreg Tucker * Neither the name of Intel Corporation nor the names of its
14660f49b0SGreg Tucker contributors may be used to endorse or promote products derived
15660f49b0SGreg Tucker from this software without specific prior written permission.
16660f49b0SGreg Tucker
17660f49b0SGreg Tucker THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18660f49b0SGreg Tucker "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19660f49b0SGreg Tucker LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20660f49b0SGreg Tucker A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21660f49b0SGreg Tucker OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22660f49b0SGreg Tucker SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23660f49b0SGreg Tucker LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24660f49b0SGreg Tucker DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25660f49b0SGreg Tucker THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26660f49b0SGreg Tucker (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27660f49b0SGreg Tucker OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28660f49b0SGreg Tucker **********************************************************************/
29660f49b0SGreg Tucker #ifndef BITBUF2_H
30660f49b0SGreg Tucker #define BITBUF2_H
31660f49b0SGreg Tucker
32660f49b0SGreg Tucker #include "igzip_lib.h"
33aae6e29dSRoy Oursler #include "unaligned.h"
34660f49b0SGreg Tucker
35660f49b0SGreg Tucker #ifdef _MSC_VER
36660f49b0SGreg Tucker #define inline __inline
37660f49b0SGreg Tucker #endif
38660f49b0SGreg Tucker
39660f49b0SGreg Tucker /* MAX_BITBUF_BIT WRITE is the maximum number of bits than can be safely written
40660f49b0SGreg Tucker * by consecutive calls of write_bits. Note this assumes the bitbuf is in a
41660f49b0SGreg Tucker * state that is possible at the exit of write_bits */
42660f49b0SGreg Tucker #define MAX_BITBUF_BIT_WRITE 56
43660f49b0SGreg Tucker
44*55fbfabfSMarcel Cornu static inline void
init(struct BitBuf2 * me)45*55fbfabfSMarcel Cornu init(struct BitBuf2 *me)
46660f49b0SGreg Tucker {
47660f49b0SGreg Tucker me->m_bits = 0;
48660f49b0SGreg Tucker me->m_bit_count = 0;
49660f49b0SGreg Tucker }
50660f49b0SGreg Tucker
51*55fbfabfSMarcel Cornu static inline void
set_buf(struct BitBuf2 * me,unsigned char * buf,unsigned int len)52*55fbfabfSMarcel Cornu set_buf(struct BitBuf2 *me, unsigned char *buf, unsigned int len)
53660f49b0SGreg Tucker {
54660f49b0SGreg Tucker unsigned int slop = 8;
55660f49b0SGreg Tucker me->m_out_buf = me->m_out_start = buf;
56660f49b0SGreg Tucker me->m_out_end = buf + len - slop;
57660f49b0SGreg Tucker }
58660f49b0SGreg Tucker
59*55fbfabfSMarcel Cornu static inline int
is_full(struct BitBuf2 * me)60*55fbfabfSMarcel Cornu is_full(struct BitBuf2 *me)
61660f49b0SGreg Tucker {
62660f49b0SGreg Tucker return (me->m_out_buf > me->m_out_end);
63660f49b0SGreg Tucker }
64660f49b0SGreg Tucker
65*55fbfabfSMarcel Cornu static inline uint8_t *
buffer_ptr(struct BitBuf2 * me)66*55fbfabfSMarcel Cornu buffer_ptr(struct BitBuf2 *me)
67660f49b0SGreg Tucker {
68660f49b0SGreg Tucker return me->m_out_buf;
69660f49b0SGreg Tucker }
70660f49b0SGreg Tucker
71*55fbfabfSMarcel Cornu static inline uint32_t
buffer_used(struct BitBuf2 * me)72*55fbfabfSMarcel Cornu buffer_used(struct BitBuf2 *me)
73660f49b0SGreg Tucker {
74660f49b0SGreg Tucker return (uint32_t) (me->m_out_buf - me->m_out_start);
75660f49b0SGreg Tucker }
76660f49b0SGreg Tucker
77*55fbfabfSMarcel Cornu static inline uint32_t
buffer_bits_used(struct BitBuf2 * me)78*55fbfabfSMarcel Cornu buffer_bits_used(struct BitBuf2 *me)
7901dfbcc4SRoy Oursler {
8001dfbcc4SRoy Oursler return (8 * (uint32_t) (me->m_out_buf - me->m_out_start) + me->m_bit_count);
8101dfbcc4SRoy Oursler }
8201dfbcc4SRoy Oursler
83*55fbfabfSMarcel Cornu static inline void
flush_bits(struct BitBuf2 * me)84*55fbfabfSMarcel Cornu flush_bits(struct BitBuf2 *me)
8501dfbcc4SRoy Oursler {
8601dfbcc4SRoy Oursler uint32_t bits;
87d3cfb2fbSIlya Leoshkevich store_le_u64(me->m_out_buf, me->m_bits);
8801dfbcc4SRoy Oursler bits = me->m_bit_count & ~7;
8901dfbcc4SRoy Oursler me->m_bit_count -= bits;
9001dfbcc4SRoy Oursler me->m_out_buf += bits / 8;
9101dfbcc4SRoy Oursler me->m_bits >>= bits;
9201dfbcc4SRoy Oursler }
9301dfbcc4SRoy Oursler
94e3fad7c4SRoy Oursler /* Can write up to 8 bytes to output buffer */
95*55fbfabfSMarcel Cornu static inline void
flush(struct BitBuf2 * me)96*55fbfabfSMarcel Cornu flush(struct BitBuf2 *me)
97e3fad7c4SRoy Oursler {
98e3fad7c4SRoy Oursler uint32_t bytes;
99e3fad7c4SRoy Oursler if (me->m_bit_count) {
100d3cfb2fbSIlya Leoshkevich store_le_u64(me->m_out_buf, me->m_bits);
101e3fad7c4SRoy Oursler bytes = (me->m_bit_count + 7) / 8;
102e3fad7c4SRoy Oursler me->m_out_buf += bytes;
103e3fad7c4SRoy Oursler }
104e3fad7c4SRoy Oursler me->m_bits = 0;
105e3fad7c4SRoy Oursler me->m_bit_count = 0;
106e3fad7c4SRoy Oursler }
107e3fad7c4SRoy Oursler
108*55fbfabfSMarcel Cornu static inline void
check_space(struct BitBuf2 * me,uint32_t num_bits)109*55fbfabfSMarcel Cornu check_space(struct BitBuf2 *me, uint32_t num_bits)
110660f49b0SGreg Tucker {
111660f49b0SGreg Tucker /* Checks if bitbuf has num_bits extra space and flushes the bytes in
112660f49b0SGreg Tucker * the bitbuf if it doesn't. */
11301dfbcc4SRoy Oursler if (63 - me->m_bit_count < num_bits)
11401dfbcc4SRoy Oursler flush_bits(me);
115660f49b0SGreg Tucker }
116660f49b0SGreg Tucker
117*55fbfabfSMarcel Cornu static inline void
write_bits_unsafe(struct BitBuf2 * me,uint64_t code,uint32_t count)118*55fbfabfSMarcel Cornu write_bits_unsafe(struct BitBuf2 *me, uint64_t code, uint32_t count)
119660f49b0SGreg Tucker {
120660f49b0SGreg Tucker me->m_bits |= code << me->m_bit_count;
121660f49b0SGreg Tucker me->m_bit_count += count;
122660f49b0SGreg Tucker }
123660f49b0SGreg Tucker
124*55fbfabfSMarcel Cornu static inline void
write_bits(struct BitBuf2 * me,uint64_t code,uint32_t count)125*55fbfabfSMarcel Cornu write_bits(struct BitBuf2 *me, uint64_t code, uint32_t count)
126f4a5b303SRoy Oursler { /* Assumes there is space to fit code into m_bits. */
127660f49b0SGreg Tucker me->m_bits |= code << me->m_bit_count;
128660f49b0SGreg Tucker me->m_bit_count += count;
12901dfbcc4SRoy Oursler flush_bits(me);
130660f49b0SGreg Tucker }
131660f49b0SGreg Tucker
132*55fbfabfSMarcel Cornu static inline void
write_bits_flush(struct BitBuf2 * me,uint64_t code,uint32_t count)133*55fbfabfSMarcel Cornu write_bits_flush(struct BitBuf2 *me, uint64_t code, uint32_t count)
134e3fad7c4SRoy Oursler { /* Assumes there is space to fit code into m_bits. */
135e3fad7c4SRoy Oursler me->m_bits |= code << me->m_bit_count;
136e3fad7c4SRoy Oursler me->m_bit_count += count;
137e3fad7c4SRoy Oursler flush(me);
138660f49b0SGreg Tucker }
139660f49b0SGreg Tucker
140660f49b0SGreg Tucker #endif // BITBUF2_H
141