<commit_before>/*
 *			GPAC - Multimedia Framework C SDK
 *
 *			Copyright (c) <NAME> 2000-2005 
 *					All rights reserved
 *
 *  This file is part of GPAC / common tools sub-project
 *
 *  GPAC is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *   
 *  GPAC is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *   
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *
 */

#include <gpac/bitstream.h>

/*the default size for new streams allocation...*/
#define BS_MEM_BLOCK_ALLOC_SIZE		250

/*private types*/
enum
{
	GF_BITSTREAM_FILE_READ = GF_BITSTREAM_WRITE + 1,
	GF_BITSTREAM_FILE_WRITE,
	/*private mode if we own the buffer*/
	GF_BITSTREAM_WRITE_DYN
};

struct __tag_bitstream
{
	/*original stream data*/
	FILE *stream;

	/*original data*/
	char *original;
	/*the size of our buffer in bytes*/
	u64 size;
	/*current position in BYTES*/
	u64 position;
	/*the byte readen/written*/
	u32 current;
	/*the number of bits in the current byte*/
	u32 nbBits;
	/*the bitstream mode*/
	u32 bsmode;

	void (*EndOfStream)(void *par);
	void *par;
};


GF_EXPORT
GF_BitStream *gf_bs_new(char *buffer, u64 BufferSize, u32 mode)
{
	GF_BitStream *tmp;
	if ( (buffer && ! BufferSize)) return NULL;

	tmp = (GF_BitStream *)gf_malloc(sizeof(GF_BitStream));
	if (!tmp) return NULL;
	memset(tmp, 0, sizeof(GF_BitStream));

	tmp->original = (char*)buffer;
	tmp->size = BufferSize;

	tmp->position = 0;
	tmp->current = 0;
	tmp->bsmode = mode;
	tmp->stream = NULL;

	switch (tmp->bsmode) {
	case GF_BITSTREAM_READ:
		tmp->nbBits = 8;
		tmp->current = 0;
		break;
	case GF_BITSTREAM_WRITE:
		tmp->nbBits = 0;
		if (! buffer) {
			/*if BufferSize is specified, use it. This is typically used when AvgSize of
			some buffers is known, but some exceed it.*/
			if (BufferSize) {
				tmp->size = BufferSize;
			} else {
				tmp->size = BS_MEM_BLOCK_ALLOC_SIZE;
			}
			tmp->original = (char *) gf_malloc(sizeof(char) * ((u32) tmp->size));
			if (! tmp->original) {
				gf_free(tmp);
				return NULL;
			}
			tmp->bsmode = GF_BITSTREAM_WRITE_DYN;
		} else {
			tmp->original = (char*)buffer;
			tmp->size = BufferSize;
		}
		break;
	default:
		/*the stream constructor is not the same...*/
		gf_free(tmp);
		return NULL;
	}
	return tmp;
}

GF_EXPORT
GF_BitStream *gf_bs_from_file(FILE *f, u32 mode)
{
	GF_BitStream *tmp;
	if (!f) return NULL;

	tmp = (GF_BitStream *)gf_malloc(sizeof(GF_BitStream));
	if (!tmp) return NULL;
	memset(tmp, 0, sizeof(GF_BitStream));
	/*switch to internal mode*/
	mode = (mode==GF_BITSTREAM_READ) ? GF_BITSTREAM_FILE_READ : GF_BITSTREAM_FILE_WRITE;
	tmp->bsmode = mode;
	tmp->current = 0;
	tmp->nbBits = (mode == GF_BITSTREAM_FILE_READ) ? 8 : 0;
	tmp->original = NULL;
	tmp->position = 0;
	tmp->stream = f;

	/*get the size of this file (for read streams)*/
	tmp->position = gf_f64_tell(f);
	gf_f64_seek(f, 0, SEEK_END);
	tmp->size = gf_f64_tell(f);
	gf_f64_seek(f, tmp->position, SEEK_SET);
	return tmp;
}

GF_EXPORT
void gf_bs_del(GF_BitStream *bs)
{
	if (!bs) return;
	/*if we are in dynamic mode (alloc done by the bitstream), free the buffer if still present*/
	if ((bs->bsmode == GF_BITSTREAM_WRITE_DYN) && bs->original) gf_free(bs->original);
	gf_free(bs);
}


/*returns 1 if aligned wrt current mode, 0 otherwise*/
static Bool BS_IsAlign(GF_BitStream *bs)
{
	switch (bs->bsmode) {
	case GF_BITSTREAM_READ:
	case GF_BITSTREAM_FILE_READ:
		return ( (8 == bs->nbBits) ? 1 : 0);
	default:
		return !bs->nbBits;
	}
}


/*fetch a new byte in the bitstream switch between packets*/
static u8 BS_ReadByte(GF_BitStream *bs)
{
	if (bs->bsmode == GF_BITSTREAM_READ) {
		if (bs->position >= bs->size) {
			if (bs->EndOfStream) bs->EndOfStream(bs->par);
			return 0;
		}
		return (u32) bs->original[bs->position++];
	}
	/*we are in FILE mode, test for end of file*/
	if (!feof(bs->stream)) {
		bs->position++;
		return (u32) fgetc(bs->stream);
	}
	if (bs->EndOfStream) bs->EndOfStream(bs->par);
	return 0;
}

#define NO_OPTS

#ifndef NO_OPTS
static u32 bit_mask[] = {0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1};
static u32 bits_mask[] = {0x0, 0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F};
#endif

GF_EXPORT
u8 gf_bs_read_bit(GF_BitStream *bs)
{
	if (bs->nbBits == 8) {	
		bs->current = BS_ReadByte(bs);
	 	bs->nbBits = 0;
	}
#ifdef NO_OPTS
	{
		s32 ret;
		bs->current <<= 1;
		bs->nbBits++;
		ret = (bs->current & 0x100) >> 8;
		return (u8) ret;
	}
#else
	return (u8) (bs->current & bit_mask[bs->nbBits++]) ? 1 : 0;
#endif

}

GF_EXPORT
u32 gf_bs_read_int(GF_BitStream *bs, u32 nBits)
{
	u32 ret;

#ifndef NO_OPTS
	if (nBits + bs->nbBits <= 8) {
		bs->nbBits += nBits;
        ret = (bs->current >> (8 - bs->nbBits) ) & bits_mask[nBits];
		return ret;
	}
#endif
	ret = 0;
	while (nBits-- > 0) {
		ret <<= 1;
		ret |= gf_bs_read_bit(bs);
	}
	return ret;
}

GF_EXPORT
u32 gf_bs_read_u8(GF_BitStream *bs)
{
	assert(bs->nbBits==8);
	return (u32) BS_ReadByte(bs);
}

GF_EXPORT
u32 gf_bs_read_u16(GF_BitStream *bs)
{
	u32 ret;
	assert(bs->nbBits==8);
	ret = BS_ReadByte(bs); ret<<=8;
	ret |= BS_ReadByte(bs);
	return ret;
}


GF_EXPORT
u32 gf_bs_read_u24(GF_BitStream *bs)
{
	u32 ret;
	assert(bs->nbBits==8);
	ret = BS_ReadByte(bs); ret<<=8;
	ret |= BS_ReadByte(bs); ret<<=8;
	ret |= BS_ReadByte(bs);
	return ret;
}

GF_EXPORT
u32 gf_bs_read_u32(GF_BitStream *bs)
{
	u32 ret;
	assert(bs->nbBits==8);
	ret = BS_ReadByte(bs); ret<<=8;
	ret |= BS_ReadByte(bs); ret<<=8;
	ret |= BS_ReadByte(bs); ret<<=8;
	ret |= BS_ReadByte(bs);
	return ret;
}

GF_EXPORT
u64 gf_bs_read_u64(GF_BitStream *bs)
{
	u64 ret;
	ret = gf_bs_read_u32(bs); ret<<=32;
	ret |= gf_bs_read_u32(bs);
	return ret;
}

GF_EXPORT
u64 gf_bs_read_long_int(GF_BitStream *bs, u32 nBits)
{
	u64 ret = 0;
	if (nBits>64) {
		gf_bs_read_long_int(bs, nBits-64);
		ret = gf_bs_read_long_int(bs, 64);
	} else {
		while (nBits-- > 0) {
			ret <<= 1;
			ret |= gf_bs_read_bit(bs);
		}
	}
	return ret;
}


GF_EXPORT
Float gf_bs_read_float(GF_BitStream *bs)
{	
	char buf [4] = "\0\0\0";
#ifdef NO_OPTS
	s32 i;
	for (i = 0; i < 32; i++)
		buf[3-i/8] |= gf_bs_read_bit(bs) << (7 - i%8);
#else
	buf[3] = gf_bs_read_int(bs, 8);
	buf[2] = gf_bs_read_int(bs, 8);
	buf[1] = gf_bs_read_int(bs, 8);
	buf[0] = gf_bs_read_int(bs, 8);
#endif
	return (* (Float *) buf);
}

GF_EXPORT
Double gf_bs_read_double(GF_BitStream *bs)
{
	char buf [8] = "\0\0\0\0\0\0\0";
	s32 i;
	for (i = 0; i < 64; i++)
		buf[7-i/8] |= gf_bs_read_bit(bs) << (7 - i%8);
	return (* (Double *) buf);
}

GF_EXPORT
u32 gf_bs_read_data(GF_BitStream *bs, char *data, u32 nbBytes)
{
	int readen;
	u64 orig = bs->position;

	if (bs->position+nbBytes > bs->size) return 0;

	if (BS_IsAlign(bs)) {
		switch (bs->bsmode) {
		case GF_BITSTREAM_READ:
			memcpy(data, bs->original + bs->position, nbBytes);
			bs->position += nbBytes;
			return nbBytes;
		case GF_BITSTREAM_FILE_READ:
		case GF_BITSTREAM_FILE_WRITE:
			readen = fread(data, nbBytes, 1, bs->stream);
			assert( nbBytes == readen );
			bs->position += nbBytes;
			return nbBytes;
		default:
			return 0;
		}
	}

	while (nbBytes-- > 0) {
		*data++ = gf_bs_read_int(bs, 8);
	}
	return (u32) (bs->position - orig);

}
<commit_msg>Fixed bug in last commit<commit_after>/*
 *			GPAC - Multimedia Framework C SDK
 *
 *			Copyright (c) <NAME> 2000-2005 
 *					All rights reserved
 *
 *  This file is part of GPAC / common tools sub-project
 *
 *  GPAC is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *   
 *  GPAC is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *   
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *
 */

#include <gpac/bitstream.h>

/*the default size for new streams allocation...*/
#define BS_MEM_BLOCK_ALLOC_SIZE		250

/*private types*/
enum
{
	GF_BITSTREAM_FILE_READ = GF_BITSTREAM_WRITE + 1,
	GF_BITSTREAM_FILE_WRITE,
	/*private mode if we own the buffer*/
	GF_BITSTREAM_WRITE_DYN
};

struct __tag_bitstream
{
	/*original stream data*/
	FILE *stream;

	/*original data*/
	char *original;
	/*the size of our buffer in bytes*/
	u64 size;
	/*current position in BYTES*/
	u64 position;
	/*the byte readen/written*/
	u32 current;
	/*the number of bits in the current byte*/
	u32 nbBits;
	/*the bitstream mode*/
	u32 bsmode;

	void (*EndOfStream)(void *par);
	void *par;
};


GF_EXPORT
GF_BitStream *gf_bs_new(char *buffer, u64 BufferSize, u32 mode)
{
	GF_BitStream *tmp;
	if ( (buffer && ! BufferSize)) return NULL;

	tmp = (GF_BitStream *)gf_malloc(sizeof(GF_BitStream));
	if (!tmp) return NULL;
	memset(tmp, 0, sizeof(GF_BitStream));

	tmp->original = (char*)buffer;
	tmp->size = BufferSize;

	tmp->position = 0;
	tmp->current = 0;
	tmp->bsmode = mode;
	tmp->stream = NULL;

	switch (tmp->bsmode) {
	case GF_BITSTREAM_READ:
		tmp->nbBits = 8;
		tmp->current = 0;
		break;
	case GF_BITSTREAM_WRITE:
		tmp->nbBits = 0;
		if (! buffer) {
			/*if BufferSize is specified, use it. This is typically used when AvgSize of
			some buffers is known, but some exceed it.*/
			if (BufferSize) {
				tmp->size = BufferSize;
			} else {
				tmp->size = BS_MEM_BLOCK_ALLOC_SIZE;
			}
			tmp->original = (char *) gf_malloc(sizeof(char) * ((u32) tmp->size));
			if (! tmp->original) {
				gf_free(tmp);
				return NULL;
			}
			tmp->bsmode = GF_BITSTREAM_WRITE_DYN;
		} else {
			tmp->original = (char*)buffer;
			tmp->size = BufferSize;
		}
		break;
	default:
		/*the stream constructor is not the same...*/
		gf_free(tmp);
		return NULL;
	}
	return tmp;
}

GF_EXPORT
GF_BitStream *gf_bs_from_file(FILE *f, u32 mode)
{
	GF_BitStream *tmp;
	if (!f) return NULL;

	tmp = (GF_BitStream *)gf_malloc(sizeof(GF_BitStream));
	if (!tmp) return NULL;
	memset(tmp, 0, sizeof(GF_BitStream));
	/*switch to internal mode*/
	mode = (mode==GF_BITSTREAM_READ) ? GF_BITSTREAM_FILE_READ : GF_BITSTREAM_FILE_WRITE;
	tmp->bsmode = mode;
	tmp->current = 0;
	tmp->nbBits = (mode == GF_BITSTREAM_FILE_READ) ? 8 : 0;
	tmp->original = NULL;
	tmp->position = 0;
	tmp->stream = f;

	/*get the size of this file (for read streams)*/
	tmp->position = gf_f64_tell(f);
	gf_f64_seek(f, 0, SEEK_END);
	tmp->size = gf_f64_tell(f);
	gf_f64_seek(f, tmp->position, SEEK_SET);
	return tmp;
}

GF_EXPORT
void gf_bs_del(GF_BitStream *bs)
{
	if (!bs) return;
	/*if we are in dynamic mode (alloc done by the bitstream), free the buffer if still present*/
	if ((bs->bsmode == GF_BITSTREAM_WRITE_DYN) && bs->original) gf_free(bs->original);
	gf_free(bs);
}


/*returns 1 if aligned wrt current mode, 0 otherwise*/
static Bool BS_IsAlign(GF_BitStream *bs)
{
	switch (bs->bsmode) {
	case GF_BITSTREAM_READ:
	case GF_BITSTREAM_FILE_READ:
		return ( (8 == bs->nbBits) ? 1 : 0);
	default:
		return !bs->nbBits;
	}
}


/*fetch a new byte in the bitstream switch between packets*/
static u8 BS_ReadByte(GF_BitStream *bs)
{
	if (bs->bsmode == GF_BITSTREAM_READ) {
		if (bs->position >= bs->size) {
			if (bs->EndOfStream) bs->EndOfStream(bs->par);
			return 0;
		}
		return (u32) bs->original[bs->position++];
	}
	/*we are in FILE mode, test for end of file*/
	if (!feof(bs->stream)) {
		bs->position++;
		return (u32) fgetc(bs->stream);
	}
	if (bs->EndOfStream) bs->EndOfStream(bs->par);
	return 0;
}

#define NO_OPTS

#ifndef NO_OPTS
static u32 bit_mask[] = {0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1};
static u32 bits_mask[] = {0x0, 0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F};
#endif

GF_EXPORT
u8 gf_bs_read_bit(GF_BitStream *bs)
{
	if (bs->nbBits == 8) {	
		bs->current = BS_ReadByte(bs);
	 	bs->nbBits = 0;
	}
#ifdef NO_OPTS
	{
		s32 ret;
		bs->current <<= 1;
		bs->nbBits++;
		ret = (bs->current & 0x100) >> 8;
		return (u8) ret;
	}
#else
	return (u8) (bs->current & bit_mask[bs->nbBits++]) ? 1 : 0;
#endif

}

GF_EXPORT
u32 gf_bs_read_int(GF_BitStream *bs, u32 nBits)
{
	u32 ret;

#ifndef NO_OPTS
	if (nBits + bs->nbBits <= 8) {
		bs->nbBits += nBits;
        ret = (bs->current >> (8 - bs->nbBits) ) & bits_mask[nBits];
		return ret;
	}
#endif
	ret = 0;
	while (nBits-- > 0) {
		ret <<= 1;
		ret |= gf_bs_read_bit(bs);
	}
	return ret;
}

GF_EXPORT
u32 gf_bs_read_u8(GF_BitStream *bs)
{
	assert(bs->nbBits==8);
	return (u32) BS_ReadByte(bs);
}

GF_EXPORT
u32 gf_bs_read_u16(GF_BitStream *bs)
{
	u32 ret;
	assert(bs->nbBits==8);
	ret = BS_ReadByte(bs); ret<<=8;
	ret |= BS_ReadByte(bs);
	return ret;
}


GF_EXPORT
u32 gf_bs_read_u24(GF_BitStream *bs)
{
	u32 ret;
	assert(bs->nbBits==8);
	ret = BS_ReadByte(bs); ret<<=8;
	ret |= BS_ReadByte(bs); ret<<=8;
	ret |= BS_ReadByte(bs);
	return ret;
}

GF_EXPORT
u32 gf_bs_read_u32(GF_BitStream *bs)
{
	u32 ret;
	assert(bs->nbBits==8);
	ret = BS_ReadByte(bs); ret<<=8;
	ret |= BS_ReadByte(bs); ret<<=8;
	ret |= BS_ReadByte(bs); ret<<=8;
	ret |= BS_ReadByte(bs);
	return ret;
}

GF_EXPORT
u64 gf_bs_read_u64(GF_BitStream *bs)
{
	u64 ret;
	ret = gf_bs_read_u32(bs); ret<<=32;
	ret |= gf_bs_read_u32(bs);
	return ret;
}

GF_EXPORT
u64 gf_bs_read_long_int(GF_BitStream *bs, u32 nBits)
{
	u64 ret = 0;
	if (nBits>64) {
		gf_bs_read_long_int(bs, nBits-64);
		ret = gf_bs_read_long_int(bs, 64);
	} else {
		while (nBits-- > 0) {
			ret <<= 1;
			ret |= gf_bs_read_bit(bs);
		}
	}
	return ret;
}


GF_EXPORT
Float gf_bs_read_float(GF_BitStream *bs)
{	
	char buf [4] = "\0\0\0";
#ifdef NO_OPTS
	s32 i;
	for (i = 0; i < 32; i++)
		buf[3-i/8] |= gf_bs_read_bit(bs) << (7 - i%8);
#else
	buf[3] = gf_bs_read_int(bs, 8);
	buf[2] = gf_bs_read_int(bs, 8);
	buf[1] = gf_bs_read_int(bs, 8);
	buf[0] = gf_bs_read_int(bs, 8);
#endif
	return (* (Float *) buf);
}

GF_EXPORT
Double gf_bs_read_double(GF_BitStream *bs)
{
	char buf [8] = "\0\0\0\0\0\0\0";
	s32 i;
	for (i = 0; i < 64; i++)
		buf[7-i/8] |= gf_bs_read_bit(bs) << (7 - i%8);
	return (* (Double *) buf);
}

GF_EXPORT
u32 gf_bs_read_data(GF_BitStream *bs, char *data, u32 nbBytes)
{
	u64 orig = bs->position;

	if (bs->position+nbBytes > bs->size) return 0;

	if (BS_IsAlign(bs)) {
		switch (bs->bsmode) {
		case GF_BITSTREAM_READ:
			memcpy(data, bs->original + bs->position, nbBytes);
			bs->position += nbBytes;
			return nbBytes;
		case GF_BITSTREAM_FILE_READ:
		case GF_BITSTREAM_FILE_WRITE:
			nbBytes = fread(data, 1, nbBytes, bs->stream);
			bs->position += nbBytes;
			return nbBytes;
		default:
			return 0;
		}
	}

	while (nbBytes-- > 0) {
		*data++ = gf_bs_read_int(bs, 8);
	}
	return (u32) (bs->position - orig);

}

{'fraction_non_alphanumeric': 0.14908875583919995, 'fraction_numerical': 0.03250213829857228, 'mean_word_length': 3.776869893148963, 'pattern_counts': {'":': 0, '<': 61, '<?xml version=': 0, '>': 173, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '772566', 'n_tokens_mistral': 6898, 'n_tokens_neox': 6295, 'n_words': 1621}