1/* 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} 239