/*
 * 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);
	}
}
