/* * qrencode - QR Code encoder * * Binary sequence class. * Copyright (C) 2006-2017 Kentaro Fukuchi * * 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 #include #include #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); } }