]> wimlib.net Git - wimlib/blob - src/comp.c
Initial commit (current version is wimlib 0.6.2)
[wimlib] / src / comp.c
1 /*
2  * comp.c
3  *
4  * Functions too long to declare as inline in comp.h.
5  *
6  * Copyright (C) 2012 Eric Biggers
7  *
8  * wimlib - Library for working with WIM files 
9  *
10  * This library is free software; you can redistribute it and/or modify it under
11  * the terms of the GNU Lesser General Public License as published by the Free
12  * Software Foundation; either version 2.1 of the License, or (at your option) any
13  * later version.
14  *
15  * This library is distributed in the hope that it will be useful, but WITHOUT ANY
16  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
17  * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License along
20  * with this library; if not, write to the Free Software Foundation, Inc., 59
21  * Temple Place, Suite 330, Boston, MA 02111-1307 USA 
22  */
23
24 #include "comp.h"
25
26 static inline void flush_bits(struct output_bitstream *ostream)
27 {
28         *(u16*)ostream->bit_output = to_le16(ostream->bitbuf);
29         ostream->bit_output = ostream->next_bit_output;
30         ostream->next_bit_output = ostream->output;
31         ostream->output += 2;
32         ostream->num_bytes_remaining -= 2;
33 }
34
35 /* Writes @num_bits bits, given by the @num_bits least significant bits of
36  * @bits, to the output @ostream. */
37 int bitstream_put_bits(struct output_bitstream *ostream, output_bitbuf_t bits, 
38                        uint num_bits)
39 {
40         uint rem_bits;
41
42         wimlib_assert(num_bits <= 16);
43         if (num_bits <= ostream->free_bits) {
44                 ostream->bitbuf = (ostream->bitbuf << num_bits) | bits;
45                 ostream->free_bits -= num_bits;
46         } else {
47
48                 if (ostream->num_bytes_remaining + (ostream->output - 
49                                                 ostream->bit_output) < 2)
50                         return 1;
51
52                 /* It is tricky to output the bits correctly.  The correct way
53                  * is to output little-endian 2-byte words, such that the bits
54                  * in the SECOND byte logically precede those in the FIRST byte.
55                  * While the byte order is little-endian, the bit order is
56                  * big-endian; the first bit in a byte is the high-order one.
57                  * Any multi-bit numbers are in bit-big-endian form, so the
58                  * low-order bit of a multi-bit number is the LAST bit to be
59                  * output. */
60                 rem_bits = num_bits - ostream->free_bits;
61                 ostream->bitbuf <<= ostream->free_bits;
62                 ostream->bitbuf |= bits >> rem_bits;
63                 flush_bits(ostream);
64                 ostream->free_bits = 16 - rem_bits;
65                 ostream->bitbuf = bits;
66
67         }
68         return 0;
69 }
70
71 /* Flushes any remaining bits in the output buffer to the output byte stream. */
72 int flush_output_bitstream(struct output_bitstream *ostream)
73 {
74         if (ostream->num_bytes_remaining + (ostream->output - 
75                                         ostream->bit_output) < 2)
76                 return 1;
77         if (ostream->free_bits != 16) {
78                 ostream->bitbuf <<= ostream->free_bits;
79                 flush_bits(ostream);
80         }
81         return 0;
82 }
83
84 /* Initializes an output bit buffer to write its output to the memory location
85  * pointer to by @data. */
86 void init_output_bitstream(struct output_bitstream *ostream, void *data, 
87                            uint num_bytes)
88 {
89         ostream->bitbuf              = 0;
90         ostream->free_bits           = 16;
91         ostream->bit_output          = (u8*)data;
92         ostream->next_bit_output     = (u8*)data + 2;
93         ostream->output              = (u8*)data + 4;
94         ostream->num_bytes_remaining = num_bytes - 4;
95 }