blob: a0b9283cb0f0695cd78b5308319fdbace12c2ef6 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/*
2 * qrencode - QR Code encoder
3 *
4 * Binary sequence class.
5 * Copyright (C) 2006-2011 Kentaro Fukuchi <kentaro@fukuchi.org>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#if HAVE_CONFIG_H
23# include "config.h"
24#endif
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28
29#include "bitstream.h"
30
31BitStream *BitStream_new(void)
32{
33 BitStream *bstream;
34
35 bstream = (BitStream *)malloc(sizeof(BitStream));
36 if(bstream == NULL) return NULL;
37
38 bstream->length = 0;
39 bstream->data = NULL;
40
41 return bstream;
42}
43
44static int BitStream_allocate(BitStream *bstream, int length)
45{
46 unsigned char *data;
47
48 if(bstream == NULL) {
49 return -1;
50 }
51
52 data = (unsigned char *)malloc(length);
53 if(data == NULL) {
54 return -1;
55 }
56
57 if(bstream->data) {
58 free(bstream->data);
59 }
60 bstream->length = length;
61 bstream->data = data;
62
63 return 0;
64}
65
66static BitStream *BitStream_newFromNum(int bits, unsigned int num)
67{
68 unsigned int mask;
69 int i;
70 unsigned char *p;
71 BitStream *bstream;
72
73 bstream = BitStream_new();
74 if(bstream == NULL) return NULL;
75
76 if(BitStream_allocate(bstream, bits)) {
77 BitStream_free(bstream);
78 return NULL;
79 }
80
81 p = bstream->data;
82 mask = 1 << (bits - 1);
83 for(i=0; i<bits; i++) {
84 if(num & mask) {
85 *p = 1;
86 } else {
87 *p = 0;
88 }
89 p++;
90 mask = mask >> 1;
91 }
92
93 return bstream;
94}
95
96static BitStream *BitStream_newFromBytes(int size, unsigned char *data)
97{
98 unsigned char mask;
99 int i, j;
100 unsigned char *p;
101 BitStream *bstream;
102
103 bstream = BitStream_new();
104 if(bstream == NULL) return NULL;
105
106 if(BitStream_allocate(bstream, size * 8)) {
107 BitStream_free(bstream);
108 return NULL;
109 }
110
111 p = bstream->data;
112 for(i=0; i<size; i++) {
113 mask = 0x80;
114 for(j=0; j<8; j++) {
115 if(data[i] & mask) {
116 *p = 1;
117 } else {
118 *p = 0;
119 }
120 p++;
121 mask = mask >> 1;
122 }
123 }
124
125 return bstream;
126}
127
128int BitStream_append(BitStream *bstream, BitStream *arg)
129{
130 unsigned char *data;
131
132 if(arg == NULL) {
133 return -1;
134 }
135 if(arg->length == 0) {
136 return 0;
137 }
138 if(bstream->length == 0) {
139 if(BitStream_allocate(bstream, arg->length)) {
140 return -1;
141 }
142 memcpy(bstream->data, arg->data, arg->length);
143 return 0;
144 }
145
146 data = (unsigned char *)malloc(bstream->length + arg->length);
147 if(data == NULL) {
148 return -1;
149 }
150 memcpy(data, bstream->data, bstream->length);
151 memcpy(data + bstream->length, arg->data, arg->length);
152
153 free(bstream->data);
154 bstream->length += arg->length;
155 bstream->data = data;
156
157 return 0;
158}
159
160int BitStream_appendNum(BitStream *bstream, int bits, unsigned int num)
161{
162 BitStream *b;
163 int ret;
164
165 if(bits == 0) return 0;
166
167 b = BitStream_newFromNum(bits, num);
168 if(b == NULL) return -1;
169
170 ret = BitStream_append(bstream, b);
171 BitStream_free(b);
172
173 return ret;
174}
175
176int BitStream_appendBytes(BitStream *bstream, int size, unsigned char *data)
177{
178 BitStream *b;
179 int ret;
180
181 if(size == 0) return 0;
182
183 b = BitStream_newFromBytes(size, data);
184 if(b == NULL) return -1;
185
186 ret = BitStream_append(bstream, b);
187 BitStream_free(b);
188
189 return ret;
190}
191
192unsigned char *BitStream_toByte(BitStream *bstream)
193{
194 int i, j, size, bytes;
195 unsigned char *data, v;
196 unsigned char *p;
197
198 size = BitStream_size(bstream);
199 if(size == 0) {
200 return NULL;
201 }
202 data = (unsigned char *)malloc((size + 7) / 8);
203 if(data == NULL) {
204 return NULL;
205 }
206
207 bytes = size / 8;
208
209 p = bstream->data;
210 for(i=0; i<bytes; i++) {
211 v = 0;
212 for(j=0; j<8; j++) {
213 v = v << 1;
214 v |= *p;
215 p++;
216 }
217 data[i] = v;
218 }
219 if(size & 7) {
220 v = 0;
221 for(j=0; j<(size & 7); j++) {
222 v = v << 1;
223 v |= *p;
224 p++;
225 }
226 data[bytes] = v;
227 }
228
229 return data;
230}
231
232void BitStream_free(BitStream *bstream)
233{
234 if(bstream != NULL) {
235 free(bstream->data);
236 free(bstream);
237 }
238}