Edit

kc3-lang/libqrencode/bitstream.c

Branch :

  • Show log

    Commit

  • Author : Kentaro Fukuchi
    Date : 2017-10-06 01:23:13
    Hash : 72c039f4
    Message : Fixed some warnings.

  • bitstream.c
  • /*
     * qrencode - QR Code encoder
     *
     * Binary sequence class.
     * Copyright (C) 2006-2017 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"
    
    #define DEFAULT_BUFSIZE (128)
    
    BitStream *BitStream_new(void)
    {
    	BitStream *bstream;
    
    	bstream = (BitStream *)malloc(sizeof(BitStream));
    	if(bstream == NULL) return NULL;
    
    	bstream->length = 0;
    	bstream->data = (unsigned char *)malloc(DEFAULT_BUFSIZE);
    	if(bstream->data == NULL) {
    		free(bstream);
    		return NULL;
    	}
    	bstream->datasize = DEFAULT_BUFSIZE;
    
    	return bstream;
    }
    
    #ifdef WITH_TESTS
    BitStream *BitStream_newWithBits(size_t size, unsigned char *bits)
    {
    	BitStream *bstream;
    
    	if(size == 0) return BitStream_new();
    
    	bstream = (BitStream *)malloc(sizeof(BitStream));
    	if(bstream == NULL) return NULL;
    
    	bstream->data = (unsigned char *)malloc(size);
    	if(bstream->data == NULL) {
    		free(bstream);
    		return NULL;
    	}
    
    	bstream->length = size;
    	bstream->datasize = size;
    	memcpy(bstream->data, bits, size);
    
    	return bstream;
    }
    #endif
    
    static int BitStream_expand(BitStream *bstream)
    {
    	unsigned char *data;
    
    	data = (unsigned char *)realloc(bstream->data, bstream->datasize * 2);
    	if(data == NULL) {
    		return -1;
    	}
    
    	bstream->data = data;
    	bstream->datasize *= 2;
    
    	return 0;
    }
    
    static void BitStream_writeNum(unsigned char *dest, size_t bits, unsigned int num)
    {
    	unsigned int mask;
    	size_t i;
    	unsigned char *p;
    
    	p = dest;
    	mask = 1U << (bits - 1);
    	for(i = 0; i < bits; i++) {
    		if(num & mask) {
    			*p = 1;
    		} else {
    			*p = 0;
    		}
    		p++;
    		mask = mask >> 1;
    	}
    }
    
    static void BitStream_writeBytes(unsigned char *dest, size_t size, unsigned char *data)
    {
    	unsigned char mask;
    	size_t i, j;
    	unsigned char *p;
    
    	p = dest;
    	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;
    		}
    	}
    }
    
    int BitStream_append(BitStream *bstream, BitStream *arg)
    {
    	int ret;
    
    	if(arg == NULL) {
    		return -1;
    	}
    	if(arg->length == 0) {
    		return 0;
    	}
    
    	while(bstream->length + arg->length > bstream->datasize) {
    		ret = BitStream_expand(bstream);
    		if(ret < 0) return ret;
    	}
    
    	memcpy(bstream->data + bstream->length, arg->data, arg->length);
    	bstream->length += arg->length;
    
    	return 0;
    }
    
    int BitStream_appendNum(BitStream *bstream, size_t bits, unsigned int num)
    {
    	int ret;
    
    	if(bits == 0) return 0;
    
    	while(bstream->datasize - bstream->length < bits) {
    		ret = BitStream_expand(bstream);
    		if(ret < 0) return ret;
    	}
    	BitStream_writeNum(bstream->data + bstream->length, bits, num);
    	bstream->length += bits;
    
    	return 0;
    }
    
    int BitStream_appendBytes(BitStream *bstream, size_t size, unsigned char *data)
    {
    	int ret;
    
    	if(size == 0) return 0;
    
    	while(bstream->datasize - bstream->length < size * 8) {
    		ret = BitStream_expand(bstream);
    		if(ret < 0) return ret;
    	}
    	BitStream_writeBytes(bstream->data + bstream->length, size, data);
    	bstream->length += size * 8;
    
    	return 0;
    }
    
    unsigned char *BitStream_toByte(BitStream *bstream)
    {
    	size_t i, j, size, bytes, oddbits;
    	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 = (unsigned char)(v << 1);
    			v |= *p;
    			p++;
    		}
    		data[i] = v;
    	}
    	oddbits = size & 7;
    	if(oddbits > 0) {
    		v = 0;
    		for(j = 0; j < oddbits; j++) {
    			v = (unsigned char)(v << 1);
    			v |= *p;
    			p++;
    		}
    		data[bytes] = (unsigned char)(v << (8 - oddbits));
    	}
    
    	return data;
    }
    
    void BitStream_free(BitStream *bstream)
    {
    	if(bstream != NULL) {
    		free(bstream->data);
    		free(bstream);
    	}
    }