| /* | 
 |  * qrencode - QR Code encoder | 
 |  * | 
 |  * Binary sequence class. | 
 |  * Copyright (C) 2006-2011 Kentaro Fukuchi <kentaro@fukuchi.org> | 
 |  * | 
 |  * This library is free software; you can redistribute it and/or | 
 |  * modify it under the terms of the GNU Lesser General Public | 
 |  * License as published by the Free Software Foundation; either | 
 |  * version 2.1 of the License, or any later version. | 
 |  * | 
 |  * This library is distributed in the hope that it will be useful, | 
 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 
 |  * Lesser General Public License for more details. | 
 |  * | 
 |  * You should have received a copy of the GNU Lesser General Public | 
 |  * License along with this library; if not, write to the Free Software | 
 |  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 
 |  */ | 
 |  | 
 | #if HAVE_CONFIG_H | 
 | # include "config.h" | 
 | #endif | 
 | #include <stdio.h> | 
 | #include <stdlib.h> | 
 | #include <string.h> | 
 |  | 
 | #include "bitstream.h" | 
 |  | 
 | BitStream *BitStream_new(void) | 
 | { | 
 | 	BitStream *bstream; | 
 |  | 
 | 	bstream = (BitStream *)malloc(sizeof(BitStream)); | 
 | 	if(bstream == NULL) return NULL; | 
 |  | 
 | 	bstream->length = 0; | 
 | 	bstream->data = NULL; | 
 |  | 
 | 	return bstream; | 
 | } | 
 |  | 
 | static int BitStream_allocate(BitStream *bstream, int length) | 
 | { | 
 | 	unsigned char *data; | 
 |  | 
 | 	if(bstream == NULL) { | 
 | 		return -1; | 
 | 	} | 
 |  | 
 | 	data = (unsigned char *)malloc(length); | 
 | 	if(data == NULL) { | 
 | 		return -1; | 
 | 	} | 
 |  | 
 | 	if(bstream->data) { | 
 | 		free(bstream->data); | 
 | 	} | 
 | 	bstream->length = length; | 
 | 	bstream->data = data; | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static BitStream *BitStream_newFromNum(int bits, unsigned int num) | 
 | { | 
 | 	unsigned int mask; | 
 | 	int i; | 
 | 	unsigned char *p; | 
 | 	BitStream *bstream; | 
 |  | 
 | 	bstream = BitStream_new(); | 
 | 	if(bstream == NULL) return NULL; | 
 |  | 
 | 	if(BitStream_allocate(bstream, bits)) { | 
 | 		BitStream_free(bstream); | 
 | 		return NULL; | 
 | 	} | 
 |  | 
 | 	p = bstream->data; | 
 | 	mask = 1 << (bits - 1); | 
 | 	for(i=0; i<bits; i++) { | 
 | 		if(num & mask) { | 
 | 			*p = 1; | 
 | 		} else { | 
 | 			*p = 0; | 
 | 		} | 
 | 		p++; | 
 | 		mask = mask >> 1; | 
 | 	} | 
 |  | 
 | 	return bstream; | 
 | } | 
 |  | 
 | static BitStream *BitStream_newFromBytes(int size, unsigned char *data) | 
 | { | 
 | 	unsigned char mask; | 
 | 	int i, j; | 
 | 	unsigned char *p; | 
 | 	BitStream *bstream; | 
 |  | 
 | 	bstream = BitStream_new(); | 
 | 	if(bstream == NULL) return NULL; | 
 |  | 
 | 	if(BitStream_allocate(bstream, size * 8)) { | 
 | 		BitStream_free(bstream); | 
 | 		return NULL; | 
 | 	} | 
 |  | 
 | 	p = bstream->data; | 
 | 	for(i=0; i<size; i++) { | 
 | 		mask = 0x80; | 
 | 		for(j=0; j<8; j++) { | 
 | 			if(data[i] & mask) { | 
 | 				*p = 1; | 
 | 			} else { | 
 | 				*p = 0; | 
 | 			} | 
 | 			p++; | 
 | 			mask = mask >> 1; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	return bstream; | 
 | } | 
 |  | 
 | int BitStream_append(BitStream *bstream, BitStream *arg) | 
 | { | 
 | 	unsigned char *data; | 
 |  | 
 | 	if(arg == NULL) { | 
 | 		return -1; | 
 | 	} | 
 | 	if(arg->length == 0) { | 
 | 		return 0; | 
 | 	} | 
 | 	if(bstream->length == 0) { | 
 | 		if(BitStream_allocate(bstream, arg->length)) { | 
 | 			return -1; | 
 | 		} | 
 | 		memcpy(bstream->data, arg->data, arg->length); | 
 | 		return 0; | 
 | 	} | 
 |  | 
 | 	data = (unsigned char *)malloc(bstream->length + arg->length); | 
 | 	if(data == NULL) { | 
 | 		return -1; | 
 | 	} | 
 | 	memcpy(data, bstream->data, bstream->length); | 
 | 	memcpy(data + bstream->length, arg->data, arg->length); | 
 |  | 
 | 	free(bstream->data); | 
 | 	bstream->length += arg->length; | 
 | 	bstream->data = data; | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | int BitStream_appendNum(BitStream *bstream, int bits, unsigned int num) | 
 | { | 
 | 	BitStream *b; | 
 | 	int ret; | 
 |  | 
 | 	if(bits == 0) return 0; | 
 |  | 
 | 	b = BitStream_newFromNum(bits, num); | 
 | 	if(b == NULL) return -1; | 
 |  | 
 | 	ret = BitStream_append(bstream, b); | 
 | 	BitStream_free(b); | 
 |  | 
 | 	return ret; | 
 | } | 
 |  | 
 | int BitStream_appendBytes(BitStream *bstream, int size, unsigned char *data) | 
 | { | 
 | 	BitStream *b; | 
 | 	int ret; | 
 |  | 
 | 	if(size == 0) return 0; | 
 |  | 
 | 	b = BitStream_newFromBytes(size, data); | 
 | 	if(b == NULL) return -1; | 
 |  | 
 | 	ret = BitStream_append(bstream, b); | 
 | 	BitStream_free(b); | 
 |  | 
 | 	return ret; | 
 | } | 
 |  | 
 | unsigned char *BitStream_toByte(BitStream *bstream) | 
 | { | 
 | 	int i, j, size, bytes; | 
 | 	unsigned char *data, v; | 
 | 	unsigned char *p; | 
 |  | 
 | 	size = BitStream_size(bstream); | 
 | 	if(size == 0) { | 
 | 		return NULL; | 
 | 	} | 
 | 	data = (unsigned char *)malloc((size + 7) / 8); | 
 | 	if(data == NULL) { | 
 | 		return NULL; | 
 | 	} | 
 |  | 
 | 	bytes = size  / 8; | 
 |  | 
 | 	p = bstream->data; | 
 | 	for(i=0; i<bytes; i++) { | 
 | 		v = 0; | 
 | 		for(j=0; j<8; j++) { | 
 | 			v = v << 1; | 
 | 			v |= *p; | 
 | 			p++; | 
 | 		} | 
 | 		data[i] = v; | 
 | 	} | 
 | 	if(size & 7) { | 
 | 		v = 0; | 
 | 		for(j=0; j<(size & 7); j++) { | 
 | 			v = v << 1; | 
 | 			v |= *p; | 
 | 			p++; | 
 | 		} | 
 | 		data[bytes] = v; | 
 | 	} | 
 |  | 
 | 	return data; | 
 | } | 
 |  | 
 | void BitStream_free(BitStream *bstream) | 
 | { | 
 | 	if(bstream != NULL) { | 
 | 		free(bstream->data); | 
 | 		free(bstream); | 
 | 	} | 
 | } |