You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
235 lines
4.2 KiB
235 lines
4.2 KiB
/* |
|
* qrencode - QR Code encoder |
|
* |
|
* Binary sequence class. |
|
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> |
|
* |
|
* 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 |
|
*/ |
|
|
|
#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); |
|
} |
|
}
|
|
|