From aa97e4d4981d61808a558c5ab36be6d3bcc2c4f6 Mon Sep 17 00:00:00 2001 From: Dave Chapman Date: Wed, 16 Feb 2005 19:33:19 +0000 Subject: Initial import of libFLAC from flac-1.1.2.tar.gz git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5983 a1c6a512-1295-4272-9138-f99709370657 --- apps/codecs/libFLAC/bitbuffer.c | 2690 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 2690 insertions(+) create mode 100644 apps/codecs/libFLAC/bitbuffer.c (limited to 'apps/codecs/libFLAC/bitbuffer.c') diff --git a/apps/codecs/libFLAC/bitbuffer.c b/apps/codecs/libFLAC/bitbuffer.c new file mode 100644 index 0000000000..8f5aefa67b --- /dev/null +++ b/apps/codecs/libFLAC/bitbuffer.c @@ -0,0 +1,2690 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the Xiph.org Foundation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include /* for malloc() */ +#include /* for memcpy(), memset() */ +#include "private/bitbuffer.h" +#include "private/bitmath.h" +#include "private/crc.h" +#include "FLAC/assert.h" + +/* + * Along the way you will see two versions of some functions, selected + * by a FLAC__NO_MANUAL_INLINING macro. One is the simplified, more + * readable, and slow version, and the other is the same function + * where crucial parts have been manually inlined and are much faster. + * + */ + +/* + * Some optimization strategies are slower with older versions of MSVC + */ +#if defined _MSC_VER && _MSC_VER <= 1200 +#define FLAC__OLD_MSVC_FLAVOR +#endif + +/* + * This should be at least twice as large as the largest number of blurbs + * required to represent any 'number' (in any encoding) you are going to + * read. With FLAC this is on the order of maybe a few hundred bits. + * If the buffer is smaller than that, the decoder won't be able to read + * in a whole number that is in a variable length encoding (e.g. Rice). + * + * The number we are actually using here is based on what would be the + * approximate maximum size of a verbatim frame at the default block size, + * for CD audio (4096 sample * 4 bytes per sample), plus some wiggle room. + * 32kbytes sounds reasonable. For kicks we subtract out 64 bytes for any + * alignment or malloc overhead. + * + * Increase this number to decrease the number of read callbacks, at the + * expense of using more memory. Or decrease for the reverse effect, + * keeping in mind the limit from the first paragraph. + */ +static const unsigned FLAC__BITBUFFER_DEFAULT_CAPACITY = ((65536 - 64) * 8) / FLAC__BITS_PER_BLURB; /* blurbs */ + +#ifndef FLAC__OLD_MSVC_FLAVOR +static const unsigned char byte_to_unary_table[] = { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; +#endif + +#if FLAC__BITS_PER_BLURB == 8 +#define FLAC__BITS_PER_BLURB_LOG2 3 +#define FLAC__BYTES_PER_BLURB 1 +#define FLAC__BLURB_ALL_ONES ((FLAC__byte)0xff) +#define FLAC__BLURB_TOP_BIT_ONE ((FLAC__byte)0x80) +#define BLURB_BIT_TO_MASK(b) (((FLAC__blurb)'\x80') >> (b)) +#define CRC16_UPDATE_BLURB(bb, blurb, crc) FLAC__CRC16_UPDATE((blurb), (crc)); +#ifndef FLAC__OLD_MSVC_FLAVOR +#define FLAC__ALIGNED_BLURB_UNARY(blurb) (byte_to_unary_table[blurb]) +#endif +#elif FLAC__BITS_PER_BLURB == 32 +#define FLAC__BITS_PER_BLURB_LOG2 5 +#define FLAC__BYTES_PER_BLURB 4 +#define FLAC__BLURB_ALL_ONES ((FLAC__uint32)0xffffffff) +#define FLAC__BLURB_TOP_BIT_ONE ((FLAC__uint32)0x80000000) +#define BLURB_BIT_TO_MASK(b) (((FLAC__blurb)0x80000000) >> (b)) +#define CRC16_UPDATE_BLURB(bb, blurb, crc) crc16_update_blurb((bb), (blurb)); +#ifndef FLAC__OLD_MSVC_FLAVOR +#define FLAC__ALIGNED_BLURB_UNARY(blurb) ((blurb) <= 0xff ? byte_to_unary_table[blurb] + 24 : ((blurb) <= 0xffff ? byte_to_unary_table[(blurb) >> 8] + 16 : ((blurb) <= 0xffffff ? byte_to_unary_table[(blurb) >> 16] + 8 : byte_to_unary_table[(blurb) >> 24]))) +#endif +#else +/* ERROR, only sizes of 8 and 32 are supported */ +#endif + +#define FLAC__BLURBS_TO_BITS(blurbs) ((blurbs) << FLAC__BITS_PER_BLURB_LOG2) + +#ifdef min +#undef min +#endif +#define min(x,y) ((x)<(y)?(x):(y)) +#ifdef max +#undef max +#endif +#define max(x,y) ((x)>(y)?(x):(y)) + +/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */ +#ifdef _MSC_VER +#define FLAC__U64L(x) x +#else +#define FLAC__U64L(x) x##LLU +#endif + +#ifndef FLaC__INLINE +#define FLaC__INLINE +#endif + +struct FLAC__BitBuffer { + FLAC__blurb *buffer; + unsigned capacity; /* in blurbs */ + unsigned blurbs, bits; + unsigned total_bits; /* must always == FLAC__BITS_PER_BLURB*blurbs+bits */ + unsigned consumed_blurbs, consumed_bits; + unsigned total_consumed_bits; /* must always == FLAC__BITS_PER_BLURB*consumed_blurbs+consumed_bits */ + FLAC__uint16 read_crc16; +#if FLAC__BITS_PER_BLURB == 32 + unsigned crc16_align; +#endif + FLAC__blurb save_head, save_tail; +}; + +#if FLAC__BITS_PER_BLURB == 32 +static void crc16_update_blurb(FLAC__BitBuffer *bb, FLAC__blurb blurb) +{ + if(bb->crc16_align == 0) { + FLAC__CRC16_UPDATE(blurb >> 24, bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> 16) & 0xff, bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> 8) & 0xff, bb->read_crc16); + FLAC__CRC16_UPDATE(blurb & 0xff, bb->read_crc16); + } + else if(bb->crc16_align == 8) { + FLAC__CRC16_UPDATE((blurb >> 16) & 0xff, bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> 8) & 0xff, bb->read_crc16); + FLAC__CRC16_UPDATE(blurb & 0xff, bb->read_crc16); + } + else if(bb->crc16_align == 16) { + FLAC__CRC16_UPDATE((blurb >> 8) & 0xff, bb->read_crc16); + FLAC__CRC16_UPDATE(blurb & 0xff, bb->read_crc16); + } + else if(bb->crc16_align == 24) { + FLAC__CRC16_UPDATE(blurb & 0xff, bb->read_crc16); + } + bb->crc16_align = 0; +} +#endif + +/* + * WATCHOUT: The current implentation is not friendly to shrinking, i.e. it + * does not shift left what is consumed, it just chops off the end, whether + * there is unconsumed data there or not. This is OK because currently we + * never shrink the buffer, but if this ever changes, we'll have to do some + * fixups here. + */ +static FLAC__bool bitbuffer_resize_(FLAC__BitBuffer *bb, unsigned new_capacity) +{ + FLAC__blurb *new_buffer; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + if(bb->capacity == new_capacity) + return true; + + new_buffer = (FLAC__blurb*)calloc(new_capacity, sizeof(FLAC__blurb)); + if(new_buffer == 0) + return false; + memcpy(new_buffer, bb->buffer, sizeof(FLAC__blurb)*min(bb->blurbs+(bb->bits?1:0), new_capacity)); + if(new_capacity < bb->blurbs+(bb->bits?1:0)) { + bb->blurbs = new_capacity; + bb->bits = 0; + bb->total_bits = FLAC__BLURBS_TO_BITS(new_capacity); + } + if(new_capacity < bb->consumed_blurbs+(bb->consumed_bits?1:0)) { + bb->consumed_blurbs = new_capacity; + bb->consumed_bits = 0; + bb->total_consumed_bits = FLAC__BLURBS_TO_BITS(new_capacity); + } + free(bb->buffer); /* we've already asserted above that (0 != bb->buffer) */ + bb->buffer = new_buffer; + bb->capacity = new_capacity; + return true; +} + +static FLAC__bool bitbuffer_grow_(FLAC__BitBuffer *bb, unsigned min_blurbs_to_add) +{ + unsigned new_capacity; + + FLAC__ASSERT(min_blurbs_to_add > 0); + + new_capacity = max(bb->capacity * 2, bb->capacity + min_blurbs_to_add); + return bitbuffer_resize_(bb, new_capacity); +} + +static FLAC__bool bitbuffer_ensure_size_(FLAC__BitBuffer *bb, unsigned bits_to_add) +{ + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + if(FLAC__BLURBS_TO_BITS(bb->capacity) < bb->total_bits + bits_to_add) + return bitbuffer_grow_(bb, (bits_to_add >> FLAC__BITS_PER_BLURB_LOG2) + 2); + else + return true; +} + +static FLAC__bool bitbuffer_read_from_client_(FLAC__BitBuffer *bb, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + unsigned bytes; + FLAC__byte *target; + + /* first shift the unconsumed buffer data toward the front as much as possible */ + if(bb->total_consumed_bits >= FLAC__BITS_PER_BLURB) { +#if FLAC__BITS_PER_BLURB == 8 + /* + * memset and memcpy are usually implemented in assembly language + * by the system libc, and they can be much faster + */ + const unsigned r_end = bb->blurbs + (bb->bits? 1:0); + const unsigned r = bb->consumed_blurbs, l = r_end - r; + memmove(&bb->buffer[0], &bb->buffer[r], l); + memset(&bb->buffer[l], 0, r); +#elif FLAC__BITS_PER_BLURB == 32 + /* still needs optimization */ + const unsigned r_end = bb->blurbs + (bb->bits? 1:0); + unsigned l = 0, r = bb->consumed_blurbs; + for( ; r < r_end; l++, r++) + bb->buffer[l] = bb->buffer[r]; + for( ; l < r_end; l++) + bb->buffer[l] = 0; +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif /* FLAC__BITS_PER_BLURB == 32 or 8 */ + + bb->blurbs -= bb->consumed_blurbs; + bb->total_bits -= FLAC__BLURBS_TO_BITS(bb->consumed_blurbs); + bb->consumed_blurbs = 0; + bb->total_consumed_bits = bb->consumed_bits; + } + + /* grow if we need to */ + if(bb->capacity <= 1) { + if(!bitbuffer_resize_(bb, 16)) + return false; + } + + /* set the target for reading, taking into account blurb alignment */ +#if FLAC__BITS_PER_BLURB == 8 + /* blurb == byte, so no gyrations necessary: */ + target = bb->buffer + bb->blurbs; + bytes = bb->capacity - bb->blurbs; +#elif FLAC__BITS_PER_BLURB == 32 + /* @@@ WATCHOUT: code currently only works for big-endian: */ + FLAC__ASSERT((bb->bits & 7) == 0); + target = (FLAC__byte*)(bb->buffer + bb->blurbs) + (bb->bits >> 3); + bytes = ((bb->capacity - bb->blurbs) << 2) - (bb->bits >> 3); /* i.e. (bb->capacity - bb->blurbs) * FLAC__BYTES_PER_BLURB - (bb->bits / 8) */ +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif + + /* finally, read in some data */ + if(!read_callback(target, &bytes, client_data)) + return false; + + /* now we have to handle partial blurb cases: */ +#if FLAC__BITS_PER_BLURB == 8 + /* blurb == byte, so no gyrations necessary: */ + bb->blurbs += bytes; + bb->total_bits += FLAC__BLURBS_TO_BITS(bytes); +#elif FLAC__BITS_PER_BLURB == 32 + /* @@@ WATCHOUT: code currently only works for big-endian: */ + { + const unsigned aligned_bytes = (bb->bits >> 3) + bytes; + bb->blurbs += (aligned_bytes >> 2); /* i.e. aligned_bytes / FLAC__BYTES_PER_BLURB */ + bb->bits = (aligned_bytes & 3u) << 3; /* i.e. (aligned_bytes % FLAC__BYTES_PER_BLURB) * 8 */ + bb->total_bits += (bytes << 3); + } +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif + return true; +} + +/*********************************************************************** + * + * Class constructor/destructor + * + ***********************************************************************/ + +FLAC__BitBuffer *FLAC__bitbuffer_new() +{ + FLAC__BitBuffer *bb = (FLAC__BitBuffer*)calloc(1, sizeof(FLAC__BitBuffer)); + + /* calloc() implies: + memset(bb, 0, sizeof(FLAC__BitBuffer)); + bb->buffer = 0; + bb->capacity = 0; + bb->blurbs = bb->bits = bb->total_bits = 0; + bb->consumed_blurbs = bb->consumed_bits = bb->total_consumed_bits = 0; + */ + return bb; +} + +void FLAC__bitbuffer_delete(FLAC__BitBuffer *bb) +{ + FLAC__ASSERT(0 != bb); + + FLAC__bitbuffer_free(bb); + free(bb); +} + +/*********************************************************************** + * + * Public class methods + * + ***********************************************************************/ + +FLAC__bool FLAC__bitbuffer_init(FLAC__BitBuffer *bb) +{ + FLAC__ASSERT(0 != bb); + + bb->buffer = 0; + bb->capacity = 0; + bb->blurbs = bb->bits = bb->total_bits = 0; + bb->consumed_blurbs = bb->consumed_bits = bb->total_consumed_bits = 0; + + return FLAC__bitbuffer_clear(bb); +} + +FLAC__bool FLAC__bitbuffer_init_from(FLAC__BitBuffer *bb, const FLAC__byte buffer[], unsigned bytes) +{ + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(bytes > 0); + + if(!FLAC__bitbuffer_init(bb)) + return false; + + if(!bitbuffer_ensure_size_(bb, bytes << 3)) + return false; + + FLAC__ASSERT(0 != buffer); + /* @@@ WATCHOUT: code currently only works for 8-bits-per-blurb inclusive-or big-endian: */ + memcpy((FLAC__byte*)bb->buffer, buffer, sizeof(FLAC__byte)*bytes); + bb->blurbs = bytes / FLAC__BYTES_PER_BLURB; + bb->bits = (bytes % FLAC__BYTES_PER_BLURB) << 3; + bb->total_bits = bytes << 3; + return true; +} + +FLAC__bool FLAC__bitbuffer_concatenate_aligned(FLAC__BitBuffer *dest, const FLAC__BitBuffer *src) +{ + unsigned bits_to_add = src->total_bits - src->total_consumed_bits; + + FLAC__ASSERT(0 != dest); + FLAC__ASSERT(0 != src); + + if(bits_to_add == 0) + return true; + if(dest->bits != src->consumed_bits) + return false; + if(!bitbuffer_ensure_size_(dest, bits_to_add)) + return false; + if(dest->bits == 0) { + memcpy(dest->buffer+dest->blurbs, src->buffer+src->consumed_blurbs, sizeof(FLAC__blurb)*(src->blurbs-src->consumed_blurbs + ((src->bits)? 1:0))); + } + else if(dest->bits + bits_to_add > FLAC__BITS_PER_BLURB) { + dest->buffer[dest->blurbs] <<= (FLAC__BITS_PER_BLURB - dest->bits); + dest->buffer[dest->blurbs] |= (src->buffer[src->consumed_blurbs] & ((1u << (FLAC__BITS_PER_BLURB-dest->bits)) - 1)); + memcpy(dest->buffer+dest->blurbs+1, src->buffer+src->consumed_blurbs+1, sizeof(FLAC__blurb)*(src->blurbs-src->consumed_blurbs-1 + ((src->bits)? 1:0))); + } + else { + dest->buffer[dest->blurbs] <<= bits_to_add; + dest->buffer[dest->blurbs] |= (src->buffer[src->consumed_blurbs] & ((1u << bits_to_add) - 1)); + } + dest->bits = src->bits; + dest->total_bits += bits_to_add; + dest->blurbs = dest->total_bits / FLAC__BITS_PER_BLURB; + + return true; +} + +void FLAC__bitbuffer_free(FLAC__BitBuffer *bb) +{ + FLAC__ASSERT(0 != bb); + + if(0 != bb->buffer) + free(bb->buffer); + bb->buffer = 0; + bb->capacity = 0; + bb->blurbs = bb->bits = bb->total_bits = 0; + bb->consumed_blurbs = bb->consumed_bits = bb->total_consumed_bits = 0; +} + +FLAC__bool FLAC__bitbuffer_clear(FLAC__BitBuffer *bb) +{ + if(bb->buffer == 0) { + bb->capacity = FLAC__BITBUFFER_DEFAULT_CAPACITY; + bb->buffer = (FLAC__blurb*)calloc(bb->capacity, sizeof(FLAC__blurb)); + if(bb->buffer == 0) + return false; + } + else { + memset(bb->buffer, 0, bb->blurbs + (bb->bits?1:0)); + } + bb->blurbs = bb->bits = bb->total_bits = 0; + bb->consumed_blurbs = bb->consumed_bits = bb->total_consumed_bits = 0; + return true; +} + +FLAC__bool FLAC__bitbuffer_clone(FLAC__BitBuffer *dest, const FLAC__BitBuffer *src) +{ + FLAC__ASSERT(0 != dest); + FLAC__ASSERT(0 != dest->buffer); + FLAC__ASSERT(0 != src); + FLAC__ASSERT(0 != src->buffer); + + if(dest->capacity < src->capacity) + if(!bitbuffer_resize_(dest, src->capacity)) + return false; + memcpy(dest->buffer, src->buffer, sizeof(FLAC__blurb)*min(src->capacity, src->blurbs+1)); + dest->blurbs = src->blurbs; + dest->bits = src->bits; + dest->total_bits = src->total_bits; + dest->consumed_blurbs = src->consumed_blurbs; + dest->consumed_bits = src->consumed_bits; + dest->total_consumed_bits = src->total_consumed_bits; + dest->read_crc16 = src->read_crc16; + return true; +} + +void FLAC__bitbuffer_reset_read_crc16(FLAC__BitBuffer *bb, FLAC__uint16 seed) +{ + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT((bb->consumed_bits & 7) == 0); + + bb->read_crc16 = seed; +#if FLAC__BITS_PER_BLURB == 8 + /* no need to do anything */ +#elif FLAC__BITS_PER_BLURB == 32 + bb->crc16_align = bb->consumed_bits; +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif +} + +FLAC__uint16 FLAC__bitbuffer_get_read_crc16(FLAC__BitBuffer *bb) +{ + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT((bb->bits & 7) == 0); + FLAC__ASSERT((bb->consumed_bits & 7) == 0); + +#if FLAC__BITS_PER_BLURB == 8 + /* no need to do anything */ +#elif FLAC__BITS_PER_BLURB == 32 + /*@@@ BUG: even though this probably can't happen with FLAC, need to fix the case where we are called here for the very first blurb and crc16_align is > 0 */ + if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { + if(bb->consumed_bits == 8) { + const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; + FLAC__CRC16_UPDATE(blurb >> 24, bb->read_crc16); + } + else if(bb->consumed_bits == 16) { + const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; + FLAC__CRC16_UPDATE(blurb >> 24, bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> 16) & 0xff, bb->read_crc16); + } + else if(bb->consumed_bits == 24) { + const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; + FLAC__CRC16_UPDATE(blurb >> 24, bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> 16) & 0xff, bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> 8) & 0xff, bb->read_crc16); + } + } + else { + if(bb->consumed_bits == 8) { + const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; + FLAC__CRC16_UPDATE(blurb >> (bb->bits-8), bb->read_crc16); + } + else if(bb->consumed_bits == 16) { + const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; + FLAC__CRC16_UPDATE(blurb >> (bb->bits-8), bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> (bb->bits-16)) & 0xff, bb->read_crc16); + } + else if(bb->consumed_bits == 24) { + const FLAC__blurb blurb = bb->buffer[bb->consumed_blurbs]; + FLAC__CRC16_UPDATE(blurb >> (bb->bits-8), bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> (bb->bits-16)) & 0xff, bb->read_crc16); + FLAC__CRC16_UPDATE((blurb >> (bb->bits-24)) & 0xff, bb->read_crc16); + } + } + bb->crc16_align = bb->consumed_bits; +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif + return bb->read_crc16; +} + +FLAC__uint16 FLAC__bitbuffer_get_write_crc16(const FLAC__BitBuffer *bb) +{ + FLAC__ASSERT((bb->bits & 7) == 0); /* assert that we're byte-aligned */ + +#if FLAC__BITS_PER_BLURB == 8 + return FLAC__crc16(bb->buffer, bb->blurbs); +#elif FLAC__BITS_PER_BLURB == 32 + /* @@@ WATCHOUT: code currently only works for big-endian: */ + return FLAC__crc16((FLAC__byte*)(bb->buffer), (bb->blurbs * FLAC__BYTES_PER_BLURB) + (bb->bits >> 3)); +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif +} + +FLAC__byte FLAC__bitbuffer_get_write_crc8(const FLAC__BitBuffer *bb) +{ + FLAC__ASSERT(0 != bb); + FLAC__ASSERT((bb->bits & 7) == 0); /* assert that we're byte-aligned */ + FLAC__ASSERT(bb->buffer[0] == 0xff); /* MAGIC NUMBER for the first byte of the sync code */ +#if FLAC__BITS_PER_BLURB == 8 + return FLAC__crc8(bb->buffer, bb->blurbs); +#elif FLAC__BITS_PER_BLURB == 32 + /* @@@ WATCHOUT: code currently only works for big-endian: */ + return FLAC__crc8((FLAC__byte*)(bb->buffer), (bb->blurbs * FLAC__BYTES_PER_BLURB) + (bb->bits >> 3)); +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif +} + +FLAC__bool FLAC__bitbuffer_is_byte_aligned(const FLAC__BitBuffer *bb) +{ + return ((bb->bits & 7) == 0); +} + +FLAC__bool FLAC__bitbuffer_is_consumed_byte_aligned(const FLAC__BitBuffer *bb) +{ + return ((bb->consumed_bits & 7) == 0); +} + +unsigned FLAC__bitbuffer_bits_left_for_byte_alignment(const FLAC__BitBuffer *bb) +{ + return 8 - (bb->consumed_bits & 7); +} + +unsigned FLAC__bitbuffer_get_input_bytes_unconsumed(const FLAC__BitBuffer *bb) +{ + FLAC__ASSERT((bb->consumed_bits & 7) == 0 && (bb->bits & 7) == 0); + return (bb->total_bits - bb->total_consumed_bits) >> 3; +} + +void FLAC__bitbuffer_get_buffer(FLAC__BitBuffer *bb, const FLAC__byte **buffer, unsigned *bytes) +{ + FLAC__ASSERT((bb->consumed_bits & 7) == 0 && (bb->bits & 7) == 0); +#if FLAC__BITS_PER_BLURB == 8 + *buffer = bb->buffer + bb->consumed_blurbs; + *bytes = bb->blurbs - bb->consumed_blurbs; +#elif FLAC__BITS_PER_BLURB == 32 + /* @@@ WATCHOUT: code currently only works for big-endian: */ + *buffer = (FLAC__byte*)(bb->buffer + bb->consumed_blurbs) + (bb->consumed_bits >> 3); + *bytes = (bb->total_bits - bb->total_consumed_bits) >> 3; +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif +} + +void FLAC__bitbuffer_release_buffer(FLAC__BitBuffer *bb) +{ +#if FLAC__BITS_PER_BLURB == 8 + (void)bb; +#elif FLAC__BITS_PER_BLURB == 32 + /* @@@ WATCHOUT: code currently only works for big-endian: */ + (void)bb; +#else + FLAC__ASSERT(false); /* ERROR, only sizes of 8 and 32 are supported */ +#endif +} + +FLAC__bool FLAC__bitbuffer_write_zeroes(FLAC__BitBuffer *bb, unsigned bits) +{ + unsigned n; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + if(bits == 0) + return true; + if(!bitbuffer_ensure_size_(bb, bits)) + return false; + bb->total_bits += bits; + while(bits > 0) { + n = min(FLAC__BITS_PER_BLURB - bb->bits, bits); + bb->buffer[bb->blurbs] <<= n; + bits -= n; + bb->bits += n; + if(bb->bits == FLAC__BITS_PER_BLURB) { + bb->blurbs++; + bb->bits = 0; + } + } + return true; +} + +FLaC__INLINE FLAC__bool FLAC__bitbuffer_write_raw_uint32(FLAC__BitBuffer *bb, FLAC__uint32 val, unsigned bits) +{ + unsigned n, k; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 32); + if(bits == 0) + return true; + /* inline the size check so we don't incure a function call unnecessarily */ + if(FLAC__BLURBS_TO_BITS(bb->capacity) < bb->total_bits + bits) { + if(!bitbuffer_ensure_size_(bb, bits)) + return false; + } + + /* zero-out unused bits; WATCHOUT: other code relies on this, so this needs to stay */ + if(bits < 32) /* @@@ gcc seems to require this because the following line causes incorrect results when bits==32; investigate */ + val &= (~(0xffffffff << bits)); /* zero-out unused bits */ + + bb->total_bits += bits; + while(bits > 0) { + n = FLAC__BITS_PER_BLURB - bb->bits; + if(n == FLAC__BITS_PER_BLURB) { /* i.e. bb->bits == 0 */ + if(bits < FLAC__BITS_PER_BLURB) { + bb->buffer[bb->blurbs] = (FLAC__blurb)val; + bb->bits = bits; + break; + } + else if(bits == FLAC__BITS_PER_BLURB) { + bb->buffer[bb->blurbs++] = (FLAC__blurb)val; + break; + } + else { + k = bits - FLAC__BITS_PER_BLURB; + bb->buffer[bb->blurbs++] = (FLAC__blurb)(val >> k); + /* we know k < 32 so no need to protect against the gcc bug mentioned above */ + val &= (~(0xffffffff << k)); + bits -= FLAC__BITS_PER_BLURB; + } + } + else if(bits <= n) { + bb->buffer[bb->blurbs] <<= bits; + bb->buffer[bb->blurbs] |= val; + if(bits == n) { + bb->blurbs++; + bb->bits = 0; + } + else + bb->bits += bits; + break; + } + else { + k = bits - n; + bb->buffer[bb->blurbs] <<= n; + bb->buffer[bb->blurbs] |= (val >> k); + /* we know n > 0 so k < 32 so no need to protect against the gcc bug mentioned above */ + val &= (~(0xffffffff << k)); + bits -= n; + bb->blurbs++; + bb->bits = 0; + } + } + + return true; +} + +FLAC__bool FLAC__bitbuffer_write_raw_int32(FLAC__BitBuffer *bb, FLAC__int32 val, unsigned bits) +{ + return FLAC__bitbuffer_write_raw_uint32(bb, (FLAC__uint32)val, bits); +} + +FLAC__bool FLAC__bitbuffer_write_raw_uint64(FLAC__BitBuffer *bb, FLAC__uint64 val, unsigned bits) +{ + static const FLAC__uint64 mask[] = { + 0, + FLAC__U64L(0x0000000000000001), FLAC__U64L(0x0000000000000003), FLAC__U64L(0x0000000000000007), FLAC__U64L(0x000000000000000F), + FLAC__U64L(0x000000000000001F), FLAC__U64L(0x000000000000003F), FLAC__U64L(0x000000000000007F), FLAC__U64L(0x00000000000000FF), + FLAC__U64L(0x00000000000001FF), FLAC__U64L(0x00000000000003FF), FLAC__U64L(0x00000000000007FF), FLAC__U64L(0x0000000000000FFF), + FLAC__U64L(0x0000000000001FFF), FLAC__U64L(0x0000000000003FFF), FLAC__U64L(0x0000000000007FFF), FLAC__U64L(0x000000000000FFFF), + FLAC__U64L(0x000000000001FFFF), FLAC__U64L(0x000000000003FFFF), FLAC__U64L(0x000000000007FFFF), FLAC__U64L(0x00000000000FFFFF), + FLAC__U64L(0x00000000001FFFFF), FLAC__U64L(0x00000000003FFFFF), FLAC__U64L(0x00000000007FFFFF), FLAC__U64L(0x0000000000FFFFFF), + FLAC__U64L(0x0000000001FFFFFF), FLAC__U64L(0x0000000003FFFFFF), FLAC__U64L(0x0000000007FFFFFF), FLAC__U64L(0x000000000FFFFFFF), + FLAC__U64L(0x000000001FFFFFFF), FLAC__U64L(0x000000003FFFFFFF), FLAC__U64L(0x000000007FFFFFFF), FLAC__U64L(0x00000000FFFFFFFF), + FLAC__U64L(0x00000001FFFFFFFF), FLAC__U64L(0x00000003FFFFFFFF), FLAC__U64L(0x00000007FFFFFFFF), FLAC__U64L(0x0000000FFFFFFFFF), + FLAC__U64L(0x0000001FFFFFFFFF), FLAC__U64L(0x0000003FFFFFFFFF), FLAC__U64L(0x0000007FFFFFFFFF), FLAC__U64L(0x000000FFFFFFFFFF), + FLAC__U64L(0x000001FFFFFFFFFF), FLAC__U64L(0x000003FFFFFFFFFF), FLAC__U64L(0x000007FFFFFFFFFF), FLAC__U64L(0x00000FFFFFFFFFFF), + FLAC__U64L(0x00001FFFFFFFFFFF), FLAC__U64L(0x00003FFFFFFFFFFF), FLAC__U64L(0x00007FFFFFFFFFFF), FLAC__U64L(0x0000FFFFFFFFFFFF), + FLAC__U64L(0x0001FFFFFFFFFFFF), FLAC__U64L(0x0003FFFFFFFFFFFF), FLAC__U64L(0x0007FFFFFFFFFFFF), FLAC__U64L(0x000FFFFFFFFFFFFF), + FLAC__U64L(0x001FFFFFFFFFFFFF), FLAC__U64L(0x003FFFFFFFFFFFFF), FLAC__U64L(0x007FFFFFFFFFFFFF), FLAC__U64L(0x00FFFFFFFFFFFFFF), + FLAC__U64L(0x01FFFFFFFFFFFFFF), FLAC__U64L(0x03FFFFFFFFFFFFFF), FLAC__U64L(0x07FFFFFFFFFFFFFF), FLAC__U64L(0x0FFFFFFFFFFFFFFF), + FLAC__U64L(0x1FFFFFFFFFFFFFFF), FLAC__U64L(0x3FFFFFFFFFFFFFFF), FLAC__U64L(0x7FFFFFFFFFFFFFFF), FLAC__U64L(0xFFFFFFFFFFFFFFFF) + }; + unsigned n, k; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 64); + if(bits == 0) + return true; + if(!bitbuffer_ensure_size_(bb, bits)) + return false; + val &= mask[bits]; + bb->total_bits += bits; + while(bits > 0) { + if(bb->bits == 0) { + if(bits < FLAC__BITS_PER_BLURB) { + bb->buffer[bb->blurbs] = (FLAC__blurb)val; + bb->bits = bits; + break; + } + else if(bits == FLAC__BITS_PER_BLURB) { + bb->buffer[bb->blurbs++] = (FLAC__blurb)val; + break; + } + else { + k = bits - FLAC__BITS_PER_BLURB; + bb->buffer[bb->blurbs++] = (FLAC__blurb)(val >> k); + /* we know k < 64 so no need to protect against the gcc bug mentioned above */ + val &= (~(FLAC__U64L(0xffffffffffffffff) << k)); + bits -= FLAC__BITS_PER_BLURB; + } + } + else { + n = min(FLAC__BITS_PER_BLURB - bb->bits, bits); + k = bits - n; + bb->buffer[bb->blurbs] <<= n; + bb->buffer[bb->blurbs] |= (val >> k); + /* we know n > 0 so k < 64 so no need to protect against the gcc bug mentioned above */ + val &= (~(FLAC__U64L(0xffffffffffffffff) << k)); + bits -= n; + bb->bits += n; + if(bb->bits == FLAC__BITS_PER_BLURB) { + bb->blurbs++; + bb->bits = 0; + } + } + } + + return true; +} + +#if 0 /* UNUSED */ +FLAC__bool FLAC__bitbuffer_write_raw_int64(FLAC__BitBuffer *bb, FLAC__int64 val, unsigned bits) +{ + return FLAC__bitbuffer_write_raw_uint64(bb, (FLAC__uint64)val, bits); +} +#endif + +FLaC__INLINE FLAC__bool FLAC__bitbuffer_write_raw_uint32_little_endian(FLAC__BitBuffer *bb, FLAC__uint32 val) +{ + /* this doesn't need to be that fast as currently it is only used for vorbis comments */ + + /* NOTE: we rely on the fact that FLAC__bitbuffer_write_raw_uint32() masks out the unused bits */ + if(!FLAC__bitbuffer_write_raw_uint32(bb, val, 8)) + return false; + if(!FLAC__bitbuffer_write_raw_uint32(bb, val>>8, 8)) + return false; + if(!FLAC__bitbuffer_write_raw_uint32(bb, val>>16, 8)) + return false; + if(!FLAC__bitbuffer_write_raw_uint32(bb, val>>24, 8)) + return false; + + return true; +} + +FLaC__INLINE FLAC__bool FLAC__bitbuffer_write_byte_block(FLAC__BitBuffer *bb, const FLAC__byte vals[], unsigned nvals) +{ + unsigned i; + + /* this could be faster but currently we don't need it to be */ + for(i = 0; i < nvals; i++) { + if(!FLAC__bitbuffer_write_raw_uint32(bb, (FLAC__uint32)(vals[i]), 8)) + return false; + } + + return true; +} + +FLAC__bool FLAC__bitbuffer_write_unary_unsigned(FLAC__BitBuffer *bb, unsigned val) +{ + if(val < 32) + return FLAC__bitbuffer_write_raw_uint32(bb, 1, ++val); + else if(val < 64) + return FLAC__bitbuffer_write_raw_uint64(bb, 1, ++val); + else { + if(!FLAC__bitbuffer_write_zeroes(bb, val)) + return false; + return FLAC__bitbuffer_write_raw_uint32(bb, 1, 1); + } +} + +unsigned FLAC__bitbuffer_rice_bits(int val, unsigned parameter) +{ + unsigned msbs, uval; + + /* fold signed to unsigned */ + if(val < 0) + /* equivalent to + * (unsigned)(((--val) << 1) - 1); + * but without the overflow problem at MININT + */ + uval = (unsigned)(((-(++val)) << 1) + 1); + else + uval = (unsigned)(val << 1); + + msbs = uval >> parameter; + + return 1 + parameter + msbs; +} + +#if 0 /* UNUSED */ +unsigned FLAC__bitbuffer_golomb_bits_signed(int val, unsigned parameter) +{ + unsigned bits, msbs, uval; + unsigned k; + + FLAC__ASSERT(parameter > 0); + + /* fold signed to unsigned */ + if(val < 0) + /* equivalent to + * (unsigned)(((--val) << 1) - 1); + * but without the overflow problem at MININT + */ + uval = (unsigned)(((-(++val)) << 1) + 1); + else + uval = (unsigned)(val << 1); + + k = FLAC__bitmath_ilog2(parameter); + if(parameter == 1u<> k; + bits = 1 + k + msbs; + } + else { + unsigned q, r, d; + + d = (1 << (k+1)) - parameter; + q = uval / parameter; + r = uval - (q * parameter); + + bits = 1 + q + k; + if(r >= d) + bits++; + } + return bits; +} + +unsigned FLAC__bitbuffer_golomb_bits_unsigned(unsigned uval, unsigned parameter) +{ + unsigned bits, msbs; + unsigned k; + + FLAC__ASSERT(parameter > 0); + + k = FLAC__bitmath_ilog2(parameter); + if(parameter == 1u<> k; + bits = 1 + k + msbs; + } + else { + unsigned q, r, d; + + d = (1 << (k+1)) - parameter; + q = uval / parameter; + r = uval - (q * parameter); + + bits = 1 + q + k; + if(r >= d) + bits++; + } + return bits; +} +#endif /* UNUSED */ + +#ifdef FLAC__SYMMETRIC_RICE +FLAC__bool FLAC__bitbuffer_write_symmetric_rice_signed(FLAC__BitBuffer *bb, int val, unsigned parameter) +{ + unsigned total_bits, interesting_bits, msbs; + FLAC__uint32 pattern; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(parameter <= 31); + + /* init pattern with the unary end bit and the sign bit */ + if(val < 0) { + pattern = 3; + val = -val; + } + else + pattern = 2; + + msbs = val >> parameter; + interesting_bits = 2 + parameter; + total_bits = interesting_bits + msbs; + pattern <<= parameter; + pattern |= (val & ((1<buffer); + FLAC__ASSERT(parameter <= 31); + + *overflow = false; + + /* init pattern with the unary end bit and the sign bit */ + if(val < 0) { + pattern = 3; + val = -val; + } + else + pattern = 2; + + msbs = val >> parameter; + interesting_bits = 2 + parameter; + total_bits = interesting_bits + msbs; + pattern <<= parameter; + pattern |= (val & ((1< max_bits) { + *overflow = true; + return true; + } + else { + /* write the unary MSBs */ + if(!FLAC__bitbuffer_write_zeroes(bb, msbs)) + return false; + /* write the unary end bit, the sign bit, and binary LSBs */ + if(!FLAC__bitbuffer_write_raw_uint32(bb, pattern, interesting_bits)) + return false; + } + return true; +} +#endif /* UNUSED */ + +FLAC__bool FLAC__bitbuffer_write_symmetric_rice_signed_escape(FLAC__BitBuffer *bb, int val, unsigned parameter) +{ + unsigned total_bits, val_bits; + FLAC__uint32 pattern; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(parameter <= 31); + + val_bits = FLAC__bitmath_silog2(val); + total_bits = 2 + parameter + 5 + val_bits; + + if(total_bits <= 32) { + pattern = 3; + pattern <<= (parameter + 5); + pattern |= val_bits; + pattern <<= val_bits; + pattern |= (val & ((1 << val_bits) - 1)); + if(!FLAC__bitbuffer_write_raw_uint32(bb, pattern, total_bits)) + return false; + } + else { + /* write the '-0' escape code first */ + if(!FLAC__bitbuffer_write_raw_uint32(bb, 3u << parameter, 2+parameter)) + return false; + /* write the length */ + if(!FLAC__bitbuffer_write_raw_uint32(bb, val_bits, 5)) + return false; + /* write the value */ + if(!FLAC__bitbuffer_write_raw_int32(bb, val, val_bits)) + return false; + } + return true; +} +#endif /* ifdef FLAC__SYMMETRIC_RICE */ + +FLAC__bool FLAC__bitbuffer_write_rice_signed(FLAC__BitBuffer *bb, int val, unsigned parameter) +{ + unsigned total_bits, interesting_bits, msbs, uval; + FLAC__uint32 pattern; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(parameter <= 30); + + /* fold signed to unsigned */ + if(val < 0) + /* equivalent to + * (unsigned)(((--val) << 1) - 1); + * but without the overflow problem at MININT + */ + uval = (unsigned)(((-(++val)) << 1) + 1); + else + uval = (unsigned)(val << 1); + + msbs = uval >> parameter; + interesting_bits = 1 + parameter; + total_bits = interesting_bits + msbs; + pattern = 1 << parameter; /* the unary end bit */ + pattern |= (uval & ((1<buffer); + FLAC__ASSERT(parameter <= 30); + + *overflow = false; + + /* fold signed to unsigned */ + if(val < 0) + /* equivalent to + * (unsigned)(((--val) << 1) - 1); + * but without the overflow problem at MININT + */ + uval = (unsigned)(((-(++val)) << 1) + 1); + else + uval = (unsigned)(val << 1); + + msbs = uval >> parameter; + interesting_bits = 1 + parameter; + total_bits = interesting_bits + msbs; + pattern = 1 << parameter; /* the unary end bit */ + pattern |= (uval & ((1< max_bits) { + *overflow = true; + return true; + } + else { + /* write the unary MSBs */ + if(!FLAC__bitbuffer_write_zeroes(bb, msbs)) + return false; + /* write the unary end bit and binary LSBs */ + if(!FLAC__bitbuffer_write_raw_uint32(bb, pattern, interesting_bits)) + return false; + } + return true; +} +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +FLAC__bool FLAC__bitbuffer_write_golomb_signed(FLAC__BitBuffer *bb, int val, unsigned parameter) +{ + unsigned total_bits, msbs, uval; + unsigned k; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(parameter > 0); + + /* fold signed to unsigned */ + if(val < 0) + /* equivalent to + * (unsigned)(((--val) << 1) - 1); + * but without the overflow problem at MININT + */ + uval = (unsigned)(((-(++val)) << 1) + 1); + else + uval = (unsigned)(val << 1); + + k = FLAC__bitmath_ilog2(parameter); + if(parameter == 1u<> k; + total_bits = 1 + k + msbs; + pattern = 1 << k; /* the unary end bit */ + pattern |= (uval & ((1u<= d) { + if(!FLAC__bitbuffer_write_raw_uint32(bb, r+d, k+1)) + return false; + } + else { + if(!FLAC__bitbuffer_write_raw_uint32(bb, r, k)) + return false; + } + } + return true; +} + +FLAC__bool FLAC__bitbuffer_write_golomb_unsigned(FLAC__BitBuffer *bb, unsigned uval, unsigned parameter) +{ + unsigned total_bits, msbs; + unsigned k; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(parameter > 0); + + k = FLAC__bitmath_ilog2(parameter); + if(parameter == 1u<> k; + total_bits = 1 + k + msbs; + pattern = 1 << k; /* the unary end bit */ + pattern |= (uval & ((1u<= d) { + if(!FLAC__bitbuffer_write_raw_uint32(bb, r+d, k+1)) + return false; + } + else { + if(!FLAC__bitbuffer_write_raw_uint32(bb, r, k)) + return false; + } + } + return true; +} +#endif /* UNUSED */ + +FLAC__bool FLAC__bitbuffer_write_utf8_uint32(FLAC__BitBuffer *bb, FLAC__uint32 val) +{ + FLAC__bool ok = 1; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(!(val & 0x80000000)); /* this version only handles 31 bits */ + + if(val < 0x80) { + return FLAC__bitbuffer_write_raw_uint32(bb, val, 8); + } + else if(val < 0x800) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xC0 | (val>>6), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8); + } + else if(val < 0x10000) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xE0 | (val>>12), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8); + } + else if(val < 0x200000) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xF0 | (val>>18), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>12)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8); + } + else if(val < 0x4000000) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xF8 | (val>>24), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>18)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>12)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8); + } + else { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xFC | (val>>30), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>24)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>18)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>12)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8); + } + + return ok; +} + +FLAC__bool FLAC__bitbuffer_write_utf8_uint64(FLAC__BitBuffer *bb, FLAC__uint64 val) +{ + FLAC__bool ok = 1; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(!(val & FLAC__U64L(0xFFFFFFF000000000))); /* this version only handles 36 bits */ + + if(val < 0x80) { + return FLAC__bitbuffer_write_raw_uint32(bb, (FLAC__uint32)val, 8); + } + else if(val < 0x800) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xC0 | (FLAC__uint32)(val>>6), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + else if(val < 0x10000) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xE0 | (FLAC__uint32)(val>>12), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + else if(val < 0x200000) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xF0 | (FLAC__uint32)(val>>18), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + else if(val < 0x4000000) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xF8 | (FLAC__uint32)(val>>24), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + else if(val < 0x80000000) { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xFC | (FLAC__uint32)(val>>30), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>24)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + else { + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xFE, 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>30)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>24)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8); + ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (FLAC__uint32)(val&0x3F), 8); + } + + return ok; +} + +FLAC__bool FLAC__bitbuffer_zero_pad_to_byte_boundary(FLAC__BitBuffer *bb) +{ + /* 0-pad to byte boundary */ + if(bb->bits & 7u) + return FLAC__bitbuffer_write_zeroes(bb, 8 - (bb->bits & 7u)); + else + return true; +} + +FLAC__bool FLAC__bitbuffer_peek_bit(FLAC__BitBuffer *bb, unsigned *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + /* to avoid a drastic speed penalty we don't: + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(bb->bits == 0); + */ + + while(1) { + if(bb->total_consumed_bits < bb->total_bits) { + *val = (bb->buffer[bb->consumed_blurbs] & BLURB_BIT_TO_MASK(bb->consumed_bits))? 1 : 0; + return true; + } + else { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } + } +} + +FLAC__bool FLAC__bitbuffer_read_bit(FLAC__BitBuffer *bb, unsigned *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + /* to avoid a drastic speed penalty we don't: + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(bb->bits == 0); + */ + + while(1) { + if(bb->total_consumed_bits < bb->total_bits) { + *val = (bb->buffer[bb->consumed_blurbs] & BLURB_BIT_TO_MASK(bb->consumed_bits))? 1 : 0; + bb->consumed_bits++; + if(bb->consumed_bits == FLAC__BITS_PER_BLURB) { + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + } + bb->total_consumed_bits++; + return true; + } + else { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } + } +} + +FLAC__bool FLAC__bitbuffer_read_bit_to_uint32(FLAC__BitBuffer *bb, FLAC__uint32 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + /* to avoid a drastic speed penalty we don't: + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(bb->bits == 0); + */ + + while(1) { + if(bb->total_consumed_bits < bb->total_bits) { + *val <<= 1; + *val |= (bb->buffer[bb->consumed_blurbs] & BLURB_BIT_TO_MASK(bb->consumed_bits))? 1 : 0; + bb->consumed_bits++; + if(bb->consumed_bits == FLAC__BITS_PER_BLURB) { + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + } + bb->total_consumed_bits++; + return true; + } + else { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } + } +} + +FLAC__bool FLAC__bitbuffer_read_bit_to_uint64(FLAC__BitBuffer *bb, FLAC__uint64 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + /* to avoid a drastic speed penalty we don't: + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(bb->bits == 0); + */ + + while(1) { + if(bb->total_consumed_bits < bb->total_bits) { + *val <<= 1; + *val |= (bb->buffer[bb->consumed_blurbs] & BLURB_BIT_TO_MASK(bb->consumed_bits))? 1 : 0; + bb->consumed_bits++; + if(bb->consumed_bits == FLAC__BITS_PER_BLURB) { + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + } + bb->total_consumed_bits++; + return true; + } + else { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } + } +} + +FLaC__INLINE FLAC__bool FLAC__bitbuffer_read_raw_uint32(FLAC__BitBuffer *bb, FLAC__uint32 *val, const unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +#ifdef FLAC__NO_MANUAL_INLINING +{ + unsigned i; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 32); + + *val = 0; + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint32(bb, val, read_callback, client_data)) + return false; + } + return true; +} +#else +{ + unsigned i, bits_ = bits; + FLAC__uint32 v = 0; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 32); + FLAC__ASSERT((bb->capacity*FLAC__BITS_PER_BLURB) * 2 >= bits); + + if(bits == 0) { + *val = 0; + return true; + } + + while(bb->total_consumed_bits + bits > bb->total_bits) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } +#if FLAC__BITS_PER_BLURB > 8 + if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { /*@@@ comment on why this is here*/ +#endif + if(bb->consumed_bits) { + i = FLAC__BITS_PER_BLURB - bb->consumed_bits; + if(i <= bits_) { + v = bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits); + bits_ -= i; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + /* we hold off updating bb->total_consumed_bits until the end */ + } + else { + *val = (bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits)) >> (i-bits_); + bb->consumed_bits += bits_; + bb->total_consumed_bits += bits_; + return true; + } + } +#if FLAC__BITS_PER_BLURB == 32 + /* note that we know bits_ cannot be > 32 because of previous assertions */ + if(bits_ == FLAC__BITS_PER_BLURB) { + v = bb->buffer[bb->consumed_blurbs]; + CRC16_UPDATE_BLURB(bb, v, bb->read_crc16); + bb->consumed_blurbs++; + /* bb->consumed_bits is already 0 */ + bb->total_consumed_bits += bits; + *val = v; + return true; + } +#else + while(bits_ >= FLAC__BITS_PER_BLURB) { + v <<= FLAC__BITS_PER_BLURB; + v |= bb->buffer[bb->consumed_blurbs]; + bits_ -= FLAC__BITS_PER_BLURB; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + /* bb->consumed_bits is already 0 */ + /* we hold off updating bb->total_consumed_bits until the end */ + } +#endif + if(bits_ > 0) { + v <<= bits_; + v |= (bb->buffer[bb->consumed_blurbs] >> (FLAC__BITS_PER_BLURB-bits_)); + bb->consumed_bits = bits_; + /* we hold off updating bb->total_consumed_bits until the end */ + } + bb->total_consumed_bits += bits; + *val = v; +#if FLAC__BITS_PER_BLURB > 8 + } + else { + *val = 0; + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint32(bb, val, read_callback, client_data)) + return false; + } + } +#endif + return true; +} +#endif + +FLAC__bool FLAC__bitbuffer_read_raw_int32(FLAC__BitBuffer *bb, FLAC__int32 *val, const unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +#ifdef FLAC__NO_MANUAL_INLINING +{ + unsigned i; + FLAC__uint32 v; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 32); + + if(bits == 0) { + *val = 0; + return true; + } + + v = 0; + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint32(bb, &v, read_callback, client_data)) + return false; + } + + /* fix the sign */ + i = 32 - bits; + if(i) { + v <<= i; + *val = (FLAC__int32)v; + *val >>= i; + } + else + *val = (FLAC__int32)v; + + return true; +} +#else +{ + unsigned i, bits_ = bits; + FLAC__uint32 v = 0; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 32); + FLAC__ASSERT((bb->capacity*FLAC__BITS_PER_BLURB) * 2 >= bits); + + if(bits == 0) { + *val = 0; + return true; + } + + while(bb->total_consumed_bits + bits > bb->total_bits) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } +#if FLAC__BITS_PER_BLURB > 8 + if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { /*@@@ comment on why this is here*/ +#endif + if(bb->consumed_bits) { + i = FLAC__BITS_PER_BLURB - bb->consumed_bits; + if(i <= bits_) { + v = bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits); + bits_ -= i; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + /* we hold off updating bb->total_consumed_bits until the end */ + } + else { + /* bits_ must be < FLAC__BITS_PER_BLURB-1 if we get to here */ + v = (bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits)); + v <<= (32-i); + *val = (FLAC__int32)v; + *val >>= (32-bits_); + bb->consumed_bits += bits_; + bb->total_consumed_bits += bits_; + return true; + } + } +#if FLAC__BITS_PER_BLURB == 32 + /* note that we know bits_ cannot be > 32 because of previous assertions */ + if(bits_ == FLAC__BITS_PER_BLURB) { + v = bb->buffer[bb->consumed_blurbs]; + bits_ = 0; + CRC16_UPDATE_BLURB(bb, v, bb->read_crc16); + bb->consumed_blurbs++; + /* bb->consumed_bits is already 0 */ + /* we hold off updating bb->total_consumed_bits until the end */ + } +#else + while(bits_ >= FLAC__BITS_PER_BLURB) { + v <<= FLAC__BITS_PER_BLURB; + v |= bb->buffer[bb->consumed_blurbs]; + bits_ -= FLAC__BITS_PER_BLURB; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + /* bb->consumed_bits is already 0 */ + /* we hold off updating bb->total_consumed_bits until the end */ + } +#endif + if(bits_ > 0) { + v <<= bits_; + v |= (bb->buffer[bb->consumed_blurbs] >> (FLAC__BITS_PER_BLURB-bits_)); + bb->consumed_bits = bits_; + /* we hold off updating bb->total_consumed_bits until the end */ + } + bb->total_consumed_bits += bits; +#if FLAC__BITS_PER_BLURB > 8 + } + else { + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint32(bb, &v, read_callback, client_data)) + return false; + } + } +#endif + + /* fix the sign */ + i = 32 - bits; + if(i) { + v <<= i; + *val = (FLAC__int32)v; + *val >>= i; + } + else + *val = (FLAC__int32)v; + + return true; +} +#endif + +FLAC__bool FLAC__bitbuffer_read_raw_uint64(FLAC__BitBuffer *bb, FLAC__uint64 *val, const unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +#ifdef FLAC__NO_MANUAL_INLINING +{ + unsigned i; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 64); + + *val = 0; + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint64(bb, val, read_callback, client_data)) + return false; + } + return true; +} +#else +{ + unsigned i, bits_ = bits; + FLAC__uint64 v = 0; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 64); + FLAC__ASSERT((bb->capacity*FLAC__BITS_PER_BLURB) * 2 >= bits); + + if(bits == 0) { + *val = 0; + return true; + } + + while(bb->total_consumed_bits + bits > bb->total_bits) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } +#if FLAC__BITS_PER_BLURB > 8 + if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { /*@@@ comment on why this is here*/ +#endif + if(bb->consumed_bits) { + i = FLAC__BITS_PER_BLURB - bb->consumed_bits; + if(i <= bits_) { + v = bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits); + bits_ -= i; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + /* we hold off updating bb->total_consumed_bits until the end */ + } + else { + *val = (bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits)) >> (i-bits_); + bb->consumed_bits += bits_; + bb->total_consumed_bits += bits_; + return true; + } + } + while(bits_ >= FLAC__BITS_PER_BLURB) { + v <<= FLAC__BITS_PER_BLURB; + v |= bb->buffer[bb->consumed_blurbs]; + bits_ -= FLAC__BITS_PER_BLURB; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + /* bb->consumed_bits is already 0 */ + /* we hold off updating bb->total_consumed_bits until the end */ + } + if(bits_ > 0) { + v <<= bits_; + v |= (bb->buffer[bb->consumed_blurbs] >> (FLAC__BITS_PER_BLURB-bits_)); + bb->consumed_bits = bits_; + /* we hold off updating bb->total_consumed_bits until the end */ + } + bb->total_consumed_bits += bits; + *val = v; +#if FLAC__BITS_PER_BLURB > 8 + } + else { + *val = 0; + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint64(bb, val, read_callback, client_data)) + return false; + } + } +#endif + return true; +} +#endif + +#if 0 /* UNUSED */ +FLAC__bool FLAC__bitbuffer_read_raw_int64(FLAC__BitBuffer *bb, FLAC__int64 *val, const unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +#ifdef FLAC__NO_MANUAL_INLINING +{ + unsigned i; + FLAC__uint64 v; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 64); + + v = 0; + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint64(bb, &v, read_callback, client_data)) + return false; + } + /* fix the sign */ + i = 64 - bits; + if(i) { + v <<= i; + *val = (FLAC__int64)v; + *val >>= i; + } + else + *val = (FLAC__int64)v; + + return true; +} +#else +{ + unsigned i, bits_ = bits; + FLAC__uint64 v = 0; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + FLAC__ASSERT(bits <= 64); + FLAC__ASSERT((bb->capacity*FLAC__BITS_PER_BLURB) * 2 >= bits); + + if(bits == 0) { + *val = 0; + return true; + } + + while(bb->total_consumed_bits + bits > bb->total_bits) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } +#if FLAC__BITS_PER_BLURB > 8 + if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { /*@@@ comment on why this is here*/ +#endif + if(bb->consumed_bits) { + i = FLAC__BITS_PER_BLURB - bb->consumed_bits; + if(i <= bits_) { + v = bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits); + bits_ -= i; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + /* we hold off updating bb->total_consumed_bits until the end */ + } + else { + /* bits_ must be < FLAC__BITS_PER_BLURB-1 if we get to here */ + v = (bb->buffer[bb->consumed_blurbs] & (FLAC__BLURB_ALL_ONES >> bb->consumed_bits)); + v <<= (64-i); + *val = (FLAC__int64)v; + *val >>= (64-bits_); + bb->consumed_bits += bits_; + bb->total_consumed_bits += bits_; + return true; + } + } + while(bits_ >= FLAC__BITS_PER_BLURB) { + v <<= FLAC__BITS_PER_BLURB; + v |= bb->buffer[bb->consumed_blurbs]; + bits_ -= FLAC__BITS_PER_BLURB; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + /* bb->consumed_bits is already 0 */ + /* we hold off updating bb->total_consumed_bits until the end */ + } + if(bits_ > 0) { + v <<= bits_; + v |= (bb->buffer[bb->consumed_blurbs] >> (FLAC__BITS_PER_BLURB-bits_)); + bb->consumed_bits = bits_; + /* we hold off updating bb->total_consumed_bits until the end */ + } + bb->total_consumed_bits += bits; +#if FLAC__BITS_PER_BLURB > 8 + } + else { + for(i = 0; i < bits; i++) { + if(!FLAC__bitbuffer_read_bit_to_uint64(bb, &v, read_callback, client_data)) + return false; + } + } +#endif + + /* fix the sign */ + i = 64 - bits; + if(i) { + v <<= i; + *val = (FLAC__int64)v; + *val >>= i; + } + else + *val = (FLAC__int64)v; + + return true; +} +#endif +#endif + +FLaC__INLINE FLAC__bool FLAC__bitbuffer_read_raw_uint32_little_endian(FLAC__BitBuffer *bb, FLAC__uint32 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + FLAC__uint32 x8, x32 = 0; + + /* this doesn't need to be that fast as currently it is only used for vorbis comments */ + + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x32, 8, read_callback, client_data)) + return false; + + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x8, 8, read_callback, client_data)) + return false; + x32 |= (x8 << 8); + + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x8, 8, read_callback, client_data)) + return false; + x32 |= (x8 << 16); + + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x8, 8, read_callback, client_data)) + return false; + x32 |= (x8 << 24); + + *val = x32; + return true; +} + +FLAC__bool FLAC__bitbuffer_skip_bits_no_crc(FLAC__BitBuffer *bb, unsigned bits, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + /* + * @@@ a slightly faster implementation is possible but + * probably not that useful since this is only called a + * couple of times in the metadata readers. + */ + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + if(bits > 0) { + const unsigned n = bb->consumed_bits & 7; + unsigned m; + FLAC__uint32 x; + + if(n != 0) { + m = min(8-n, bits); + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, m, read_callback, client_data)) + return false; + bits -= m; + } + m = bits / 8; + if(m > 0) { + if(!FLAC__bitbuffer_read_byte_block_aligned_no_crc(bb, 0, m, read_callback, client_data)) + return false; + bits %= 8; + } + if(bits > 0) { + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, bits, read_callback, client_data)) + return false; + } + } + + return true; +} + +FLAC__bool FLAC__bitbuffer_read_byte_block_aligned_no_crc(FLAC__BitBuffer *bb, FLAC__byte *val, unsigned nvals, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(FLAC__bitbuffer_is_byte_aligned(bb)); + FLAC__ASSERT(FLAC__bitbuffer_is_consumed_byte_aligned(bb)); +#if FLAC__BITS_PER_BLURB == 8 + while(nvals > 0) { + unsigned chunk = min(nvals, bb->blurbs - bb->consumed_blurbs); + if(chunk == 0) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + } + else { + if(0 != val) { + memcpy(val, bb->buffer + bb->consumed_blurbs, FLAC__BYTES_PER_BLURB * chunk); + val += FLAC__BYTES_PER_BLURB * chunk; + } + nvals -= chunk; + bb->consumed_blurbs += chunk; + bb->total_consumed_bits = (bb->consumed_blurbs << FLAC__BITS_PER_BLURB_LOG2); + } + } +#else + @@@ need to write this still + FLAC__ASSERT(0); +#endif + + return true; +} + +FLaC__INLINE FLAC__bool FLAC__bitbuffer_read_unary_unsigned(FLAC__BitBuffer *bb, unsigned *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +#ifdef FLAC__NO_MANUAL_INLINING +{ + unsigned bit, val_ = 0; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + while(1) { + if(!FLAC__bitbuffer_read_bit(bb, &bit, read_callback, client_data)) + return false; + if(bit) + break; + else + val_++; + } + *val = val_; + return true; +} +#else +{ + unsigned i, val_ = 0; + unsigned total_blurbs_ = (bb->total_bits + (FLAC__BITS_PER_BLURB-1)) / FLAC__BITS_PER_BLURB; + FLAC__blurb b; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + +#if FLAC__BITS_PER_BLURB > 8 + if(bb->bits == 0 || bb->consumed_blurbs < bb->blurbs) { /*@@@ comment on why this is here*/ +#endif + if(bb->consumed_bits) { + b = bb->buffer[bb->consumed_blurbs] << bb->consumed_bits; + if(b) { + for(i = 0; !(b & FLAC__BLURB_TOP_BIT_ONE); i++) + b <<= 1; + *val = i; + i++; + bb->consumed_bits += i; + bb->total_consumed_bits += i; + if(bb->consumed_bits == FLAC__BITS_PER_BLURB) { + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + } + return true; + } + else { + val_ = FLAC__BITS_PER_BLURB - bb->consumed_bits; + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + bb->total_consumed_bits += val_; + } + } + while(1) { + if(bb->consumed_blurbs >= total_blurbs_) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + total_blurbs_ = (bb->total_bits + (FLAC__BITS_PER_BLURB-1)) / FLAC__BITS_PER_BLURB; + } + b = bb->buffer[bb->consumed_blurbs]; + if(b) { + for(i = 0; !(b & FLAC__BLURB_TOP_BIT_ONE); i++) + b <<= 1; + val_ += i; + i++; + bb->consumed_bits = i; + *val = val_; + if(i == FLAC__BITS_PER_BLURB) { + CRC16_UPDATE_BLURB(bb, bb->buffer[bb->consumed_blurbs], bb->read_crc16); + bb->consumed_blurbs++; + bb->consumed_bits = 0; + } + bb->total_consumed_bits += i; + return true; + } + else { + val_ += FLAC__BITS_PER_BLURB; + CRC16_UPDATE_BLURB(bb, 0, bb->read_crc16); + bb->consumed_blurbs++; + /* bb->consumed_bits is already 0 */ + bb->total_consumed_bits += FLAC__BITS_PER_BLURB; + } + } +#if FLAC__BITS_PER_BLURB > 8 + } + else { + while(1) { + if(!FLAC__bitbuffer_read_bit(bb, &i, read_callback, client_data)) + return false; + if(i) + break; + else + val_++; + } + *val = val_; + return true; + } +#endif +} +#endif + +#ifdef FLAC__SYMMETRIC_RICE +FLAC__bool FLAC__bitbuffer_read_symmetric_rice_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + FLAC__uint32 sign = 0, lsbs = 0, msbs = 0; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(parameter <= 31); + + /* read the unary MSBs and end bit */ + if(!FLAC__bitbuffer_read_unary_unsigned(bb, &msbs, read_callback, client_data)) + return false; + + /* read the sign bit */ + if(!FLAC__bitbuffer_read_bit_to_uint32(bb, &sign, read_callback, client_data)) + return false; + + /* read the binary LSBs */ + if(!FLAC__bitbuffer_read_raw_uint32(bb, &lsbs, parameter, read_callback, client_data)) + return false; + + /* compose the value */ + *val = (msbs << parameter) | lsbs; + if(sign) + *val = -(*val); + + return true; +} +#endif /* ifdef FLAC__SYMMETRIC_RICE */ + +FLAC__bool FLAC__bitbuffer_read_rice_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + FLAC__uint32 lsbs = 0, msbs = 0; + unsigned uval; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(parameter <= 31); + + /* read the unary MSBs and end bit */ + if(!FLAC__bitbuffer_read_unary_unsigned(bb, &msbs, read_callback, client_data)) + return false; + + /* read the binary LSBs */ + if(!FLAC__bitbuffer_read_raw_uint32(bb, &lsbs, parameter, read_callback, client_data)) + return false; + + /* compose the value */ + uval = (msbs << parameter) | lsbs; + if(uval & 1) + *val = -((int)(uval >> 1)) - 1; + else + *val = (int)(uval >> 1); + + return true; +} + +FLAC__bool FLAC__bitbuffer_read_rice_signed_block(FLAC__BitBuffer *bb, int vals[], unsigned nvals, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +#ifdef FLAC__OLD_MSVC_FLAVOR +{ + const FLAC__blurb *buffer = bb->buffer; + + unsigned i, j, val_i = 0; + unsigned cbits = 0, uval = 0, msbs = 0, lsbs_left = 0; + FLAC__blurb blurb, save_blurb; + unsigned state = 0; /* 0 = getting unary MSBs, 1 = getting binary LSBs */ + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(parameter <= 31); + + if(nvals == 0) + return true; + + i = bb->consumed_blurbs; + /* + * We unroll the main loop to take care of partially consumed blurbs here. + */ + if(bb->consumed_bits > 0) { + save_blurb = blurb = buffer[i]; + cbits = bb->consumed_bits; + blurb <<= cbits; + + while(1) { + if(state == 0) { + if(blurb) { + for(j = 0; !(blurb & FLAC__BLURB_TOP_BIT_ONE); j++) + blurb <<= 1; + msbs += j; + + /* dispose of the unary end bit */ + blurb <<= 1; + j++; + cbits += j; + + uval = 0; + lsbs_left = parameter; + state++; + if(cbits == FLAC__BITS_PER_BLURB) { + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + break; + } + } + else { + msbs += FLAC__BITS_PER_BLURB - cbits; + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + break; + } + } + else { + const unsigned available_bits = FLAC__BITS_PER_BLURB - cbits; + if(lsbs_left >= available_bits) { + uval <<= available_bits; + uval |= (blurb >> cbits); + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + + if(lsbs_left == available_bits) { + /* compose the value */ + uval |= (msbs << parameter); + if(uval & 1) + vals[val_i++] = -((int)(uval >> 1)) - 1; + else + vals[val_i++] = (int)(uval >> 1); + if(val_i == nvals) + break; + + msbs = 0; + state = 0; + } + + lsbs_left -= available_bits; + break; + } + else { + uval <<= lsbs_left; + uval |= (blurb >> (FLAC__BITS_PER_BLURB - lsbs_left)); + blurb <<= lsbs_left; + cbits += lsbs_left; + + /* compose the value */ + uval |= (msbs << parameter); + if(uval & 1) + vals[val_i++] = -((int)(uval >> 1)) - 1; + else + vals[val_i++] = (int)(uval >> 1); + if(val_i == nvals) { + /* back up one if we exited the for loop because we read all nvals but the end came in the middle of a blurb */ + i--; + break; + } + + msbs = 0; + state = 0; + } + } + } + i++; + + bb->consumed_blurbs = i; + bb->consumed_bits = cbits; + bb->total_consumed_bits = (i << FLAC__BITS_PER_BLURB_LOG2) | cbits; + } + + /* + * Now that we are blurb-aligned the logic is slightly simpler + */ + while(val_i < nvals) { + for( ; i < bb->blurbs && val_i < nvals; i++) { + save_blurb = blurb = buffer[i]; + cbits = 0; + while(1) { + if(state == 0) { + if(blurb) { + for(j = 0; !(blurb & FLAC__BLURB_TOP_BIT_ONE); j++) + blurb <<= 1; + msbs += j; + + /* dispose of the unary end bit */ + blurb <<= 1; + j++; + cbits += j; + + uval = 0; + lsbs_left = parameter; + state++; + if(cbits == FLAC__BITS_PER_BLURB) { + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + break; + } + } + else { + msbs += FLAC__BITS_PER_BLURB - cbits; + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + break; + } + } + else { + const unsigned available_bits = FLAC__BITS_PER_BLURB - cbits; + if(lsbs_left >= available_bits) { + uval <<= available_bits; + uval |= (blurb >> cbits); + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + + if(lsbs_left == available_bits) { + /* compose the value */ + uval |= (msbs << parameter); + if(uval & 1) + vals[val_i++] = -((int)(uval >> 1)) - 1; + else + vals[val_i++] = (int)(uval >> 1); + if(val_i == nvals) + break; + + msbs = 0; + state = 0; + } + + lsbs_left -= available_bits; + break; + } + else { + uval <<= lsbs_left; + uval |= (blurb >> (FLAC__BITS_PER_BLURB - lsbs_left)); + blurb <<= lsbs_left; + cbits += lsbs_left; + + /* compose the value */ + uval |= (msbs << parameter); + if(uval & 1) + vals[val_i++] = -((int)(uval >> 1)) - 1; + else + vals[val_i++] = (int)(uval >> 1); + if(val_i == nvals) { + /* back up one if we exited the for loop because we read all nvals but the end came in the middle of a blurb */ + i--; + break; + } + + msbs = 0; + state = 0; + } + } + } + } + bb->consumed_blurbs = i; + bb->consumed_bits = cbits; + bb->total_consumed_bits = (i << FLAC__BITS_PER_BLURB_LOG2) | cbits; + if(val_i < nvals) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + /* these must be zero because we can only get here if we got to the end of the buffer */ + FLAC__ASSERT(bb->consumed_blurbs == 0); + FLAC__ASSERT(bb->consumed_bits == 0); + i = 0; + } + } + + return true; +} +#else +{ + const FLAC__blurb *buffer = bb->buffer; + + unsigned i, j, val_i = nvals; + unsigned cbits = 0, uval = 0, msbs = 0, lsbs_left = 0; + FLAC__blurb blurb, save_blurb; + unsigned state = 0; /* 0 = getting unary MSBs, 1 = getting binary LSBs */ + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + FLAC__ASSERT(parameter <= 31); + + if(nvals == 0) + return true; + + cbits = bb->consumed_bits; + i = bb->consumed_blurbs; + while(val_i != 0) { + for( ; i < bb->blurbs; i++) { + blurb = (save_blurb = buffer[i]) << cbits; + while(1) { + if(state == 0) { + if(blurb) { + j = FLAC__ALIGNED_BLURB_UNARY(blurb); + msbs += j; + j++; + cbits += j; + + uval = 0; + lsbs_left = parameter; + state++; + if(cbits == FLAC__BITS_PER_BLURB) { + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + break; + } + blurb <<= j; + } + else { + msbs += FLAC__BITS_PER_BLURB - cbits; + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + break; + } + } + else { + const unsigned available_bits = FLAC__BITS_PER_BLURB - cbits; + if(lsbs_left >= available_bits) { + uval <<= available_bits; + uval |= (blurb >> cbits); + cbits = 0; + CRC16_UPDATE_BLURB(bb, save_blurb, bb->read_crc16); + + if(lsbs_left == available_bits) { + /* compose the value */ + uval |= (msbs << parameter); + *vals = (int)(uval >> 1 ^ -(int)(uval & 1)); + --val_i; + if(val_i == 0) { + i++; + goto break2; + } + ++vals; + + msbs = 0; + state = 0; + } + + lsbs_left -= available_bits; + break; + } + else { + cbits += lsbs_left; + uval <<= lsbs_left; + uval |= (blurb >> (FLAC__BITS_PER_BLURB - lsbs_left)); + blurb <<= lsbs_left; + + /* compose the value */ + uval |= (msbs << parameter); + *vals = (int)(uval >> 1 ^ -(int)(uval & 1)); + --val_i; + if(val_i == 0) + goto break2; + ++vals; + + msbs = 0; + state = 0; + } + } + } + } +break2: + bb->consumed_blurbs = i; + bb->consumed_bits = cbits; + bb->total_consumed_bits = (i << FLAC__BITS_PER_BLURB_LOG2) | cbits; + if(val_i != 0) { + if(!bitbuffer_read_from_client_(bb, read_callback, client_data)) + return false; + /* these must be zero because we can only get here if we got to the end of the buffer */ + FLAC__ASSERT(bb->consumed_blurbs == 0); + FLAC__ASSERT(bb->consumed_bits == 0); + i = 0; + } + } + + return true; +} +#endif + +#if 0 /* UNUSED */ +FLAC__bool FLAC__bitbuffer_read_golomb_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + FLAC__uint32 lsbs = 0, msbs = 0; + unsigned bit, uval, k; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + k = FLAC__bitmath_ilog2(parameter); + + /* read the unary MSBs and end bit */ + if(!FLAC__bitbuffer_read_unary_unsigned(bb, &msbs, read_callback, client_data)) + return false; + + /* read the binary LSBs */ + if(!FLAC__bitbuffer_read_raw_uint32(bb, &lsbs, k, read_callback, client_data)) + return false; + + if(parameter == 1u<= d) { + if(!FLAC__bitbuffer_read_bit(bb, &bit, read_callback, client_data)) + return false; + lsbs <<= 1; + lsbs |= bit; + lsbs -= d; + } + /* compose the value */ + uval = msbs * parameter + lsbs; + } + + /* unfold unsigned to signed */ + if(uval & 1) + *val = -((int)(uval >> 1)) - 1; + else + *val = (int)(uval >> 1); + + return true; +} + +FLAC__bool FLAC__bitbuffer_read_golomb_unsigned(FLAC__BitBuffer *bb, unsigned *val, unsigned parameter, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data) +{ + FLAC__uint32 lsbs, msbs = 0; + unsigned bit, k; + + FLAC__ASSERT(0 != bb); + FLAC__ASSERT(0 != bb->buffer); + + k = FLAC__bitmath_ilog2(parameter); + + /* read the unary MSBs and end bit */ + if(!FLAC__bitbuffer_read_unary_unsigned(bb, &msbs, read_callback, client_data)) + return false; + + /* read the binary LSBs */ + if(!FLAC__bitbuffer_read_raw_uint32(bb, &lsbs, k, read_callback, client_data)) + return false; + + if(parameter == 1u<= d) { + if(!FLAC__bitbuffer_read_bit(bb, &bit, read_callback, client_data)) + return false; + lsbs <<= 1; + lsbs |= bit; + lsbs -= d; + } + /* compose the value */ + *val = msbs * parameter + lsbs; + } + + return true; +} +#endif /* UNUSED */ + +/* on return, if *val == 0xffffffff then the utf-8 sequence was invalid, but the return value will be true */ +FLAC__bool FLAC__bitbuffer_read_utf8_uint32(FLAC__BitBuffer *bb, FLAC__uint32 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data, FLAC__byte *raw, unsigned *rawlen) +{ + FLAC__uint32 v = 0; + FLAC__uint32 x; + unsigned i; + + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, 8, read_callback, client_data)) + return false; + if(raw) + raw[(*rawlen)++] = (FLAC__byte)x; + if(!(x & 0x80)) { /* 0xxxxxxx */ + v = x; + i = 0; + } + else if(x & 0xC0 && !(x & 0x20)) { /* 110xxxxx */ + v = x & 0x1F; + i = 1; + } + else if(x & 0xE0 && !(x & 0x10)) { /* 1110xxxx */ + v = x & 0x0F; + i = 2; + } + else if(x & 0xF0 && !(x & 0x08)) { /* 11110xxx */ + v = x & 0x07; + i = 3; + } + else if(x & 0xF8 && !(x & 0x04)) { /* 111110xx */ + v = x & 0x03; + i = 4; + } + else if(x & 0xFC && !(x & 0x02)) { /* 1111110x */ + v = x & 0x01; + i = 5; + } + else { + *val = 0xffffffff; + return true; + } + for( ; i; i--) { + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, 8, read_callback, client_data)) + return false; + if(raw) + raw[(*rawlen)++] = (FLAC__byte)x; + if(!(x & 0x80) || (x & 0x40)) { /* 10xxxxxx */ + *val = 0xffffffff; + return true; + } + v <<= 6; + v |= (x & 0x3F); + } + *val = v; + return true; +} + +/* on return, if *val == 0xffffffffffffffff then the utf-8 sequence was invalid, but the return value will be true */ +FLAC__bool FLAC__bitbuffer_read_utf8_uint64(FLAC__BitBuffer *bb, FLAC__uint64 *val, FLAC__bool (*read_callback)(FLAC__byte buffer[], unsigned *bytes, void *client_data), void *client_data, FLAC__byte *raw, unsigned *rawlen) +{ + FLAC__uint64 v = 0; + FLAC__uint32 x; + unsigned i; + + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, 8, read_callback, client_data)) + return false; + if(raw) + raw[(*rawlen)++] = (FLAC__byte)x; + if(!(x & 0x80)) { /* 0xxxxxxx */ + v = x; + i = 0; + } + else if(x & 0xC0 && !(x & 0x20)) { /* 110xxxxx */ + v = x & 0x1F; + i = 1; + } + else if(x & 0xE0 && !(x & 0x10)) { /* 1110xxxx */ + v = x & 0x0F; + i = 2; + } + else if(x & 0xF0 && !(x & 0x08)) { /* 11110xxx */ + v = x & 0x07; + i = 3; + } + else if(x & 0xF8 && !(x & 0x04)) { /* 111110xx */ + v = x & 0x03; + i = 4; + } + else if(x & 0xFC && !(x & 0x02)) { /* 1111110x */ + v = x & 0x01; + i = 5; + } + else if(x & 0xFE && !(x & 0x01)) { /* 11111110 */ + v = 0; + i = 6; + } + else { + *val = FLAC__U64L(0xffffffffffffffff); + return true; + } + for( ; i; i--) { + if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, 8, read_callback, client_data)) + return false; + if(raw) + raw[(*rawlen)++] = (FLAC__byte)x; + if(!(x & 0x80) || (x & 0x40)) { /* 10xxxxxx */ + *val = FLAC__U64L(0xffffffffffffffff); + return true; + } + v <<= 6; + v |= (x & 0x3F); + } + *val = v; + return true; +} + +void FLAC__bitbuffer_dump(const FLAC__BitBuffer *bb, FILE *out) +{ + unsigned i, j; + if(bb == 0) { + fprintf(out, "bitbuffer is NULL\n"); + } + else { + fprintf(out, "bitbuffer: capacity=%u blurbs=%u bits=%u total_bits=%u consumed: blurbs=%u, bits=%u, total_bits=%u\n", bb->capacity, bb->blurbs, bb->bits, bb->total_bits, bb->consumed_blurbs, bb->consumed_bits, bb->total_consumed_bits); + + for(i = 0; i < bb->blurbs; i++) { + fprintf(out, "%08X: ", i); + for(j = 0; j < FLAC__BITS_PER_BLURB; j++) + if(i*FLAC__BITS_PER_BLURB+j < bb->total_consumed_bits) + fprintf(out, "."); + else + fprintf(out, "%01u", bb->buffer[i] & (1 << (FLAC__BITS_PER_BLURB-j-1)) ? 1:0); + fprintf(out, "\n"); + } + if(bb->bits > 0) { + fprintf(out, "%08X: ", i); + for(j = 0; j < bb->bits; j++) + if(i*FLAC__BITS_PER_BLURB+j < bb->total_consumed_bits) + fprintf(out, "."); + else + fprintf(out, "%01u", bb->buffer[i] & (1 << (bb->bits-j-1)) ? 1:0); + fprintf(out, "\n"); + } + } +} -- cgit v1.2.3