From 285f5bec5bb03d4e825e5d866e94008088dd6155 Mon Sep 17 00:00:00 2001 From: xleroy Date: Sat, 9 Aug 2008 08:06:33 +0000 Subject: Ajout nouveaux tests git-svn-id: https://yquem.inria.fr/compcert/svn/compcert/trunk@708 fca1b0fc-160b-0410-b1d3-a4f43f01ea2e --- test/compression/bitfile.c | 1043 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1043 insertions(+) create mode 100644 test/compression/bitfile.c (limited to 'test/compression/bitfile.c') diff --git a/test/compression/bitfile.c b/test/compression/bitfile.c new file mode 100644 index 00000000..7480ce99 --- /dev/null +++ b/test/compression/bitfile.c @@ -0,0 +1,1043 @@ +/*************************************************************************** +* Bit Stream File Implementation +* +* File : bitfile.c +* Purpose : This file implements a simple library of I/O functions for +* files that contain data in sizes that aren't integral bytes. +* An attempt was made to make the functions in this library +* analogous to functions provided to manipulate byte streams. +* The functions contained in this library were created with +* compression algorithms in mind, but may be suited to other +* applications. +* Author : Michael Dipperstein +* Date : January 9, 2004 +* +**************************************************************************** +* UPDATES +* +* $Id: bitfile.c,v 1.10 2007/08/26 21:53:48 michael Exp $ +* $Log: bitfile.c,v $ +* Revision 1.10 2007/08/26 21:53:48 michael +* Changes required for LGPL v3. +* +* Revision 1.9 2007/07/10 05:34:07 michael +* Remove ',' after last element in the enum endian_t. +* +* Revision 1.8 2007/02/06 06:22:07 michael +* Used trim program to remove trailing spaces. +* +* Revision 1.7 2006/06/03 19:32:38 michael +* Corrected error reporetd anonymous. The allocation of constants used to +* open underlying read/write/append files did not account for a terminating +* null. +* +* Used spell checker to correct spelling. +* +* Revision 1.6 2005/12/08 06:56:55 michael +* Minor text corrections. +* +* Revision 1.5 2005/12/06 15:06:37 michael +* Added BitFileGetBitsInt and BitFilePutBitsInt for integer types. +* +* Revision 1.4 2005/06/23 04:34:18 michael +* Prevent BitfileGetBits/PutBits from accessing an extra byte when given +* an integral number of bytes. +* +* Revision 1.3 2004/11/09 14:16:58 michael +* Added functions to convert open bit_file_t to FILE and to +* align open bit_file_t to the next byte. +* +* Revision 1.2 2004/06/15 13:15:58 michael +* Use incomplete type to hide definition of bitfile structure +* +* Revision 1.1.1.1 2004/02/09 05:31:42 michael +* Initial release +* +* +**************************************************************************** +* +* Bitfile: Bit stream File I/O Routines +* Copyright (C) 2004-2007 by Michael Dipperstein (mdipper@cs.ucsb.edu) +* +* This file is part of the bit file library. +* +* The bit file 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 3 of the +* License, or (at your option) any later version. +* +* The bit file 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 program. If not, see . +* +***************************************************************************/ + +/*************************************************************************** +* INCLUDED FILES +***************************************************************************/ +#include +#include +#include "bitfile.h" + +/*************************************************************************** +* TYPE DEFINITIONS +***************************************************************************/ + +typedef enum +{ + BF_UNKNOWN_ENDIAN, + BF_LITTLE_ENDIAN, + BF_BIG_ENDIAN +} endian_t; + +struct bit_file_t +{ + FILE *fp; /* file pointer used by stdio functions */ + endian_t endian; /* endianess of architecture */ + unsigned char bitBuffer; /* bits waiting to be read/written */ + unsigned char bitCount; /* number of bits in bitBuffer */ + BF_MODES mode; /* open for read, write, or append */ +}; + +/* union used to test for endianess */ +typedef union +{ + unsigned long word; + unsigned char bytes[sizeof(unsigned long)]; +} endian_test_t; + +/*************************************************************************** +* PROTOTYPES +***************************************************************************/ +endian_t DetermineEndianess(void); + +int BitFilePutBitsLE(bit_file_t *stream, void *bits, const unsigned int count); +int BitFilePutBitsBE(bit_file_t *stream, void *bits, const unsigned int count, + const size_t size); + +int BitFileGetBitsLE(bit_file_t *stream, void *bits, const unsigned int count); +int BitFileGetBitsBE(bit_file_t *stream, void *bits, const unsigned int count, + const size_t size); + +/*************************************************************************** +* FUNCTIONS +***************************************************************************/ + +/*************************************************************************** +* Function : BitFileOpen +* Description: This function opens a bit file for reading, writing, +* or appending. If successful, a bit_file_t data +* structure will be allocated and a pointer to the +* structure will be returned. +* Parameters : fileName - NULL terminated string containing the name of +* the file to be opened. +* mode - The mode of the file to be opened +* Effects : The specified file will be opened and file structure will +* be allocated. +* Returned : Pointer to the bit_file_t structure for the bit file +* opened, or NULL on failure. errno will be set for all +* failure cases. +***************************************************************************/ +bit_file_t *BitFileOpen(const char *fileName, const BF_MODES mode) +{ + char modes[3][3] = {"rb", "wb", "ab"}; /* binary modes for fopen */ + bit_file_t *bf; + + bf = (bit_file_t *)malloc(sizeof(bit_file_t)); + + if (bf == NULL) + { + /* malloc failed */ + errno = ENOMEM; + } + else + { + bf->fp = fopen(fileName, modes[mode]); + + if (bf->fp == NULL) + { + /* fopen failed */ + free(bf); + bf = NULL; + } + else + { + /* fopen succeeded fill in remaining bf data */ + bf->bitBuffer = 0; + bf->bitCount = 0; + bf->mode = mode; + + /*************************************************************** + * TO DO: Consider using the last byte in a file to indicate + * the number of bits in the previous byte that actually have + * data. If I do that, I'll need special handling of files + * opened with a mode of BF_APPEND. + ***************************************************************/ + } + } + + bf->endian = DetermineEndianess(); + return (bf); +} + +/*************************************************************************** +* Function : MakeBitFile +* Description: This function naively wraps a standard file in a +* bit_file_t structure. ANSI-C doesn't support file status +* functions commonly found in other C variants, so the +* caller must be passed as a parameter. +* Parameters : stream - pointer to the standard file being wrapped. +* mode - The mode of the file being wrapped. +* Effects : A bit_file_t structure will be created for the stream +* passed as a parameter. +* Returned : Pointer to the bit_file_t structure for the bit file +* or NULL on failure. errno will be set for all failure +* cases. +***************************************************************************/ +bit_file_t *MakeBitFile(FILE *stream, const BF_MODES mode) +{ + bit_file_t *bf; + + if (stream == NULL) + { + /* can't wrapper empty steam */ + errno = EBADF; + bf = NULL; + } + else + { + bf = (bit_file_t *)malloc(sizeof(bit_file_t)); + + if (bf == NULL) + { + /* malloc failed */ + errno = ENOMEM; + } + else + { + /* set structure data */ + bf->fp = stream; + bf->bitBuffer = 0; + bf->bitCount = 0; + bf->mode = mode; + } + } + + bf->endian = DetermineEndianess(); + + return (bf); +} + +/*************************************************************************** +* Function : DetermineEndianess +* Description: This function determines the endianess of the current +* hardware architecture. An unsigned long is set to 1. If +* the 1st byte of the unsigned long gets the 1, this is a +* little endian machine. If the last byte gets the 1, this +* is a big endian machine. +* Parameters : None +* Effects : None +* Returned : endian_t for current machine architecture +***************************************************************************/ +endian_t DetermineEndianess(void) +{ + endian_t endian; + endian_test_t endianTest; + + endianTest.word = 1; + + if (endianTest.bytes[0] == 1) + { + /* LSB is 1st byte (little endian)*/ + endian = BF_LITTLE_ENDIAN; + } + else if (endianTest.bytes[sizeof(unsigned long) - 1] == 1) + { + /* LSB is last byte (big endian)*/ + endian = BF_BIG_ENDIAN; + } + else + { + endian = BF_UNKNOWN_ENDIAN; + } + + return endian; +} + +/*************************************************************************** +* Function : BitFileClose +* Description: This function closes a bit file and frees all associated +* data. +* Parameters : stream - pointer to bit file stream being closed +* Effects : The specified file will be closed and the file structure +* will be freed. +* Returned : 0 for success or EOF for failure. +***************************************************************************/ +int BitFileClose(bit_file_t *stream) +{ + int returnValue = 0; + + if (stream == NULL) + { + return(EOF); + } + + if ((stream->mode == BF_WRITE) || (stream->mode == BF_APPEND)) + { + /* write out any unwritten bits */ + if (stream->bitCount != 0) + { + (stream->bitBuffer) <<= 8 - (stream->bitCount); + fputc(stream->bitBuffer, stream->fp); /* handle error? */ + } + } + + /*********************************************************************** + * TO DO: Consider writing an additional byte indicating the number of + * valid bits (bitCount) in the previous byte. + ***********************************************************************/ + + /* close file */ + returnValue = fclose(stream->fp); + + /* free memory allocated for bit file */ + free(stream); + + return(returnValue); +} + +/*************************************************************************** +* Function : BitFileToFILE +* Description: This function flushes and frees the bitfile structure, +* returning a pointer to a stdio file. +* Parameters : stream - pointer to bit file stream being closed +* Effects : The specified bitfile will be made usable as a stdio +* FILE. +* Returned : Pointer to FILE. NULL for failure. +***************************************************************************/ +FILE *BitFileToFILE(bit_file_t *stream) +{ + FILE *fp = NULL; + + if (stream == NULL) + { + return(NULL); + } + + if ((stream->mode == BF_WRITE) || (stream->mode == BF_APPEND)) + { + /* write out any unwritten bits */ + if (stream->bitCount != 0) + { + (stream->bitBuffer) <<= 8 - (stream->bitCount); + fputc(stream->bitBuffer, stream->fp); /* handle error? */ + } + } + + /*********************************************************************** + * TO DO: Consider writing an additional byte indicating the number of + * valid bits (bitCount) in the previous byte. + ***********************************************************************/ + + /* close file */ + fp = stream->fp; + + /* free memory allocated for bit file */ + free(stream); + + return(fp); +} + +/*************************************************************************** +* Function : BitFileByteAlign +* Description: This function aligns the bitfile to the nearest byte. For +* output files, this means writing out the bit buffer with +* extra bits set to 0. For input files, this means flushing +* the bit buffer. +* Parameters : stream - pointer to bit file stream to align +* Effects : Flushes out the bit buffer. +* Returned : EOF if stream is NULL. Otherwise, the contents of the +* bit buffer. +***************************************************************************/ +int BitFileByteAlign(bit_file_t *stream) +{ + int returnValue; + + if (stream == NULL) + { + return(EOF); + } + + returnValue = stream->bitBuffer; + + if ((stream->mode == BF_WRITE) || (stream->mode == BF_APPEND)) + { + /* write out any unwritten bits */ + if (stream->bitCount != 0) + { + (stream->bitBuffer) <<= 8 - (stream->bitCount); + fputc(stream->bitBuffer, stream->fp); /* handle error? */ + } + } + + stream->bitBuffer = 0; + stream->bitCount = 0; + + return (returnValue); +} + +/*************************************************************************** +* Function : BitFileGetChar +* Description: This function returns the next byte from the file passed as +* a parameter. +* Parameters : stream - pointer to bit file stream to read from +* Effects : Reads next byte from file and updates buffer accordingly. +* Returned : EOF if a whole byte cannot be obtained. Otherwise, +* the character read. +***************************************************************************/ +int BitFileGetChar(bit_file_t *stream) +{ + int returnValue; + unsigned char tmp; + + if (stream == NULL) + { + return(EOF); + } + + returnValue = fgetc(stream->fp); + + if (stream->bitCount == 0) + { + /* we can just get byte from file */ + return returnValue; + } + + /* we have some buffered bits to return too */ + if (returnValue != EOF) + { + /* figure out what to return */ + tmp = ((unsigned char)returnValue) >> (stream->bitCount); + tmp |= ((stream->bitBuffer) << (8 - (stream->bitCount))); + + /* put remaining in buffer. count shouldn't change. */ + stream->bitBuffer = returnValue; + + returnValue = tmp; + } + + return returnValue; +} + +/*************************************************************************** +* Function : BitFilePutChar +* Description: This function writes the byte passed as a parameter to the +* file passed a parameter. +* Parameters : c - the character to be written +* stream - pointer to bit file stream to write to +* Effects : Writes a byte to the file and updates buffer accordingly. +* Returned : On success, the character written, otherwise EOF. +***************************************************************************/ +int BitFilePutChar(const int c, bit_file_t *stream) +{ + unsigned char tmp; + + if (stream == NULL) + { + return(EOF); + } + + if (stream->bitCount == 0) + { + /* we can just put byte from file */ + return fputc(c, stream->fp); + } + + /* figure out what to write */ + tmp = ((unsigned char)c) >> (stream->bitCount); + tmp = tmp | ((stream->bitBuffer) << (8 - stream->bitCount)); + + if (fputc(tmp, stream->fp) != EOF) + { + /* put remaining in buffer. count shouldn't change. */ + stream->bitBuffer = c; + } + else + { + return EOF; + } + + return tmp; +} + +/*************************************************************************** +* Function : BitFileGetBit +* Description: This function returns the next bit from the file passed as +* a parameter. The bit value returned is the msb in the +* bit buffer. +* Parameters : stream - pointer to bit file stream to read from +* Effects : Reads next bit from bit buffer. If the buffer is empty, +* a new byte will be read from the file. +* Returned : 0 if bit == 0, 1 if bit == 1, and EOF if operation fails. +***************************************************************************/ +int BitFileGetBit(bit_file_t *stream) +{ + int returnValue; + + if (stream == NULL) + { + return(EOF); + } + + if (stream->bitCount == 0) + { + /* buffer is empty, read another character */ + if ((returnValue = fgetc(stream->fp)) == EOF) + { + return EOF; + } + else + { + stream->bitCount = 8; + stream->bitBuffer = returnValue; + } + } + + /* bit to return is msb in buffer */ + stream->bitCount--; + returnValue = (stream->bitBuffer) >> (stream->bitCount); + + return (returnValue & 0x01); +} + +/*************************************************************************** +* Function : BitFilePutBit +* Description: This function writes the bit passed as a parameter to the +* file passed a parameter. +* Parameters : c - the bit value to be written +* stream - pointer to bit file stream to write to +* Effects : Writes a bit to the bit buffer. If the buffer has a byte, +* the buffer is written to the file and cleared. +* Returned : On success, the bit value written, otherwise EOF. +***************************************************************************/ +int BitFilePutBit(const int c, bit_file_t *stream) +{ + int returnValue = c; + + if (stream == NULL) + { + return(EOF); + } + + stream->bitCount++; + stream->bitBuffer <<= 1; + + if (c != 0) + { + stream->bitBuffer |= 1; + } + + /* write bit buffer if we have 8 bits */ + if (stream->bitCount == 8) + { + if (fputc(stream->bitBuffer, stream->fp) == EOF) + { + returnValue = EOF; + } + + /* reset buffer */ + stream->bitCount = 0; + stream->bitBuffer = 0; + } + + return returnValue; +} + +/*************************************************************************** +* Function : BitFileGetBits +* Description: This function reads the specified number of bits from the +* file passed as a parameter and writes them to the +* requested memory location (msb to lsb). +* Parameters : stream - pointer to bit file stream to read from +* bits - address to store bits read +* count - number of bits to read +* Effects : Reads bits from the bit buffer and file stream. The bit +* buffer will be modified as necessary. +* Returned : EOF for failure, otherwise the number of bits read. If +* an EOF is reached before all the bits are read, bits +* will contain every bit through the last complete byte. +***************************************************************************/ +int BitFileGetBits(bit_file_t *stream, void *bits, const unsigned int count) +{ + unsigned char *bytes, shifts; + int offset, remaining, returnValue; + + bytes = (unsigned char *)bits; + + if ((stream == NULL) || (bits == NULL)) + { + return(EOF); + } + + offset = 0; + remaining = count; + + /* read whole bytes */ + while (remaining >= 8) + { + returnValue = BitFileGetChar(stream); + + if (returnValue == EOF) + { + return EOF; + } + + bytes[offset] = (unsigned char)returnValue; + remaining -= 8; + offset++; + } + + if (remaining != 0) + { + /* read remaining bits */ + shifts = 8 - remaining; + + while (remaining > 0) + { + returnValue = BitFileGetBit(stream); + + if (returnValue == EOF) + { + return EOF; + } + + bytes[offset] <<= 1; + bytes[offset] |= (returnValue & 0x01); + remaining--; + } + + /* shift last bits into position */ + bytes[offset] <<= shifts; + } + + return count; +} + +/*************************************************************************** +* Function : BitFilePutBits +* Description: This function writes the specified number of bits from the +* memory location passed as a parameter to the file passed +* as a parameter. Bits are written msb to lsb. +* Parameters : stream - pointer to bit file stream to write to +* bits - pointer to bits to write +* count - number of bits to write +* Effects : Writes bits to the bit buffer and file stream. The bit +* buffer will be modified as necessary. +* Returned : EOF for failure, otherwise the number of bits written. If +* an error occurs after a partial write, the partially +* written bits will not be unwritten. +***************************************************************************/ +int BitFilePutBits(bit_file_t *stream, void *bits, const unsigned int count) +{ + unsigned char *bytes, tmp; + int offset, remaining, returnValue; + + bytes = (unsigned char *)bits; + + if ((stream == NULL) || (bits == NULL)) + { + return(EOF); + } + + offset = 0; + remaining = count; + + /* write whole bytes */ + while (remaining >= 8) + { + returnValue = BitFilePutChar(bytes[offset], stream); + + if (returnValue == EOF) + { + return EOF; + } + + remaining -= 8; + offset++; + } + + if (remaining != 0) + { + /* write remaining bits */ + tmp = bytes[offset]; + + while (remaining > 0) + { + returnValue = BitFilePutBit((tmp & 0x80), stream); + + if (returnValue == EOF) + { + return EOF; + } + + tmp <<= 1; + remaining--; + } + } + + return count; +} + +/*************************************************************************** +* Function : BitFileGetBitsInt +* Description: This function provides a machine independent layer that +* allows a single function call to stuff an arbitrary number +* of bits into an integer type variable. +* Parameters : stream - pointer to bit file stream to read from +* bits - address to store bits read +* count - number of bits to read +* size - sizeof type containing "bits" +* Effects : Calls a function that reads bits from the bit buffer and +* file stream. The bit buffer will be modified as necessary. +* the bits will be written to "bits" from least significant +* byte to most significant byte. +* Returned : EOF for failure, otherwise the number of bits read by the +* called function. +***************************************************************************/ +int BitFileGetBitsInt(bit_file_t *stream, void *bits, const unsigned int count, + const size_t size) +{ + int returnValue; + + if ((stream == NULL) || (bits == NULL)) + { + return(EOF); + } + + if (stream->endian == BF_LITTLE_ENDIAN) + { + returnValue = BitFileGetBitsLE(stream, bits, count); + } + else if (stream->endian == BF_BIG_ENDIAN) + { + returnValue = BitFileGetBitsBE(stream, bits, count, size); + } + else + { + returnValue = EOF; + } + + return returnValue; +} + +/*************************************************************************** +* Function : BitFileGetBitsLE (Little Endian) +* Description: This function reads the specified number of bits from the +* file passed as a parameter and writes them to the +* requested memory location (LSB to MSB). +* Parameters : stream - pointer to bit file stream to read from +* bits - address to store bits read +* count - number of bits to read +* Effects : Reads bits from the bit buffer and file stream. The bit +* buffer will be modified as necessary. bits is treated as +* a little endian integer of length >= (count/8) + 1. +* Returned : EOF for failure, otherwise the number of bits read. If +* an EOF is reached before all the bits are read, bits +* will contain every bit through the last successful read. +***************************************************************************/ +int BitFileGetBitsLE(bit_file_t *stream, void *bits, const unsigned int count) +{ + unsigned char *bytes, shifts; + int offset, remaining, returnValue; + + bytes = (unsigned char *)bits; + + offset = 0; + remaining = count; + + /* read whole bytes */ + while (remaining >= 8) + { + returnValue = BitFileGetChar(stream); + + if (returnValue == EOF) + { + return EOF; + } + + bytes[offset] = (unsigned char)returnValue; + remaining -= 8; + offset++; + } + + if (remaining != 0) + { + /* read remaining bits */ + shifts = 8 - remaining; + + while (remaining > 0) + { + returnValue = BitFileGetBit(stream); + + if (returnValue == EOF) + { + return EOF; + } + + bytes[offset] <<= 1; + bytes[offset] |= (returnValue & 0x01); + remaining--; + } + + } + + return count; +} + +/*************************************************************************** +* Function : BitFileGetBitsBE (Big Endian) +* Description: This function reads the specified number of bits from the +* file passed as a parameter and writes them to the +* requested memory location (LSB to MSB). +* Parameters : stream - pointer to bit file stream to read from +* bits - address to store bits read +* count - number of bits to read +* size - sizeof type containing "bits" +* Effects : Reads bits from the bit buffer and file stream. The bit +* buffer will be modified as necessary. bits is treated as +* a big endian integer of length size. +* Returned : EOF for failure, otherwise the number of bits read. If +* an EOF is reached before all the bits are read, bits +* will contain every bit through the last successful read. +***************************************************************************/ +int BitFileGetBitsBE(bit_file_t *stream, void *bits, const unsigned int count, + const size_t size) +{ + unsigned char *bytes, shifts; + int offset, remaining, returnValue; + + if (count > (size * 8)) + { + /* too many bits to read */ + return EOF; + } + + bytes = (unsigned char *)bits; + + offset = size - 1; + remaining = count; + + /* read whole bytes */ + while (remaining >= 8) + { + returnValue = BitFileGetChar(stream); + + if (returnValue == EOF) + { + return EOF; + } + + bytes[offset] = (unsigned char)returnValue; + remaining -= 8; + offset--; + } + + if (remaining != 0) + { + /* read remaining bits */ + shifts = 8 - remaining; + + while (remaining > 0) + { + returnValue = BitFileGetBit(stream); + + if (returnValue == EOF) + { + return EOF; + } + + bytes[offset] <<= 1; + bytes[offset] |= (returnValue & 0x01); + remaining--; + } + + } + + return count; +} + +/*************************************************************************** +* Function : BitFilePutBitsInt +* Description: This function provides a machine independent layer that +* allows a single function call to write an arbitrary number +* of bits from an integer type variable into a file. +* Parameters : stream - pointer to bit file stream to write to +* bits - pointer to bits to write +* count - number of bits to write +* size - sizeof type containing "bits" +* Effects : Calls a function that writes bits to the bit buffer and +* file stream. The bit buffer will be modified as necessary. +* the bits will be written to the file stream from least +* significant byte to most significant byte. +* Returned : EOF for failure, otherwise the number of bits written. If +* an error occurs after a partial write, the partially +* written bits will not be unwritten. +***************************************************************************/ +int BitFilePutBitsInt(bit_file_t *stream, void *bits, const unsigned int count, + const size_t size) +{ + int returnValue; + + if ((stream == NULL) || (bits == NULL)) + { + return(EOF); + } + + if (stream->endian == BF_LITTLE_ENDIAN) + { + returnValue = BitFilePutBitsLE(stream, bits, count); + } + else if (stream->endian == BF_BIG_ENDIAN) + { + returnValue = BitFilePutBitsBE(stream, bits, count, size); + } + else + { + returnValue = EOF; + } + + return returnValue; +} + +/*************************************************************************** +* Function : BitFilePutBitsLE (Little Endian) +* Description: This function writes the specified number of bits from the +* memory location passed as a parameter to the file passed +* as a parameter. Bits are written LSB to MSB. +* Parameters : stream - pointer to bit file stream to write to +* bits - pointer to bits to write +* count - number of bits to write +* Effects : Writes bits to the bit buffer and file stream. The bit +* buffer will be modified as necessary. bits is treated as +* a little endian integer of length >= (count/8) + 1. +* Returned : EOF for failure, otherwise the number of bits written. If +* an error occurs after a partial write, the partially +* written bits will not be unwritten. +***************************************************************************/ +int BitFilePutBitsLE(bit_file_t *stream, void *bits, const unsigned int count) +{ + unsigned char *bytes, tmp; + int offset, remaining, returnValue; + + bytes = (unsigned char *)bits; + offset = 0; + remaining = count; + + /* write whole bytes */ + while (remaining >= 8) + { + returnValue = BitFilePutChar(bytes[offset], stream); + + if (returnValue == EOF) + { + return EOF; + } + + remaining -= 8; + offset++; + } + + if (remaining != 0) + { + /* write remaining bits */ + tmp = bytes[offset]; + tmp <<= (8 - remaining); + + while (remaining > 0) + { + returnValue = BitFilePutBit((tmp & 0x80), stream); + + if (returnValue == EOF) + { + return EOF; + } + + tmp <<= 1; + remaining--; + } + } + + return count; +} + +/*************************************************************************** +* Function : BitFilePutBitsBE (Big Endian) +* Description: This function writes the specified number of bits from the +* memory location passed as a parameter to the file passed +* as a parameter. Bits are written LSB to MSB. +* Parameters : stream - pointer to bit file stream to write to +* bits - pointer to bits to write +* count - number of bits to write +* Effects : Writes bits to the bit buffer and file stream. The bit +* buffer will be modified as necessary. bits is treated as +* a big endian integer of length size. +* Returned : EOF for failure, otherwise the number of bits written. If +* an error occurs after a partial write, the partially +* written bits will not be unwritten. +***************************************************************************/ +int BitFilePutBitsBE(bit_file_t *stream, void *bits, const unsigned int count, + const size_t size) +{ + unsigned char *bytes, tmp; + int offset, remaining, returnValue; + + if (count > (size * 8)) + { + /* too many bits to write */ + return EOF; + } + + bytes = (unsigned char *)bits; + offset = size - 1; + remaining = count; + + /* write whole bytes */ + while (remaining >= 8) + { + returnValue = BitFilePutChar(bytes[offset], stream); + + if (returnValue == EOF) + { + return EOF; + } + + remaining -= 8; + offset--; + } + + if (remaining != 0) + { + /* write remaining bits */ + tmp = bytes[offset]; + tmp <<= (8 - remaining); + + while (remaining > 0) + { + returnValue = BitFilePutBit((tmp & 0x80), stream); + + if (returnValue == EOF) + { + return EOF; + } + + tmp <<= 1; + remaining--; + } + } + + return count; +} -- cgit