mirror of
https://github.com/libretro/mame2003-libretro.git
synced 2025-02-17 09:08:08 +00:00
Remove libflac and zlib parts that we don't need
This commit is contained in:
parent
04b1f85aa5
commit
67288881c0
@ -2604,9 +2604,7 @@ SOURCES_C += \
|
||||
$(CORE_DIR)/lib/mame-chd/mame_sha1.c
|
||||
|
||||
SOURCES_C += \
|
||||
$(CORE_DIR)/libretro-deps/libFLAC/bitmath.c \
|
||||
$(CORE_DIR)/libretro-deps/libFLAC/bitreader.c \
|
||||
$(CORE_DIR)/libretro-deps/libFLAC/bitwriter.c \
|
||||
$(CORE_DIR)/libretro-deps/libFLAC/cpu.c \
|
||||
$(CORE_DIR)/libretro-deps/libFLAC/crc.c \
|
||||
$(CORE_DIR)/libretro-deps/libFLAC/fixed.c \
|
||||
@ -2616,8 +2614,6 @@ SOURCES_C += \
|
||||
$(CORE_DIR)/libretro-deps/libFLAC/md5.c \
|
||||
$(CORE_DIR)/libretro-deps/libFLAC/memory.c \
|
||||
$(CORE_DIR)/libretro-deps/libFLAC/stream_decoder.c \
|
||||
$(CORE_DIR)/libretro-deps/libFLAC/stream_encoder.c \
|
||||
$(CORE_DIR)/libretro-deps/libFLAC/stream_encoder_framing.c \
|
||||
$(CORE_DIR)/libretro-deps/libFLAC/window.c
|
||||
|
||||
ifeq ($(STATIC_LINKING),1)
|
||||
@ -2637,13 +2633,8 @@ SOURCES_C += \
|
||||
$(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.c \
|
||||
$(LIBRETRO_COMM_DIR)/time/rtime.c \
|
||||
$(CORE_DIR)/lib/zlib/adler32.c \
|
||||
$(CORE_DIR)/lib/zlib/compress.c \
|
||||
$(CORE_DIR)/lib/zlib/crc32.c \
|
||||
$(CORE_DIR)/lib/zlib/deflate.c \
|
||||
$(CORE_DIR)/lib/zlib/gzclose.c \
|
||||
$(CORE_DIR)/lib/zlib/gzlib.c \
|
||||
$(CORE_DIR)/lib/zlib/gzread.c \
|
||||
$(CORE_DIR)/lib/zlib/gzwrite.c \
|
||||
$(CORE_DIR)/lib/zlib/inffast.c \
|
||||
$(CORE_DIR)/lib/zlib/inflate.c \
|
||||
$(CORE_DIR)/lib/zlib/inftrees.c \
|
||||
|
@ -1,70 +0,0 @@
|
||||
/* compress.c -- compress a memory buffer
|
||||
* Copyright (C) 1995-2005 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include <zlib.h>
|
||||
|
||||
/* ===========================================================================
|
||||
Compresses the source buffer into the destination buffer. The level
|
||||
parameter has the same meaning as in deflateInit. sourceLen is the byte
|
||||
length of the source buffer. Upon entry, destLen is the total size of the
|
||||
destination buffer, which must be at least 0.1% larger than sourceLen plus
|
||||
12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
|
||||
|
||||
compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
||||
memory, Z_BUF_ERROR if there was not enough room in the output buffer,
|
||||
Z_STREAM_ERROR if the level parameter is invalid.
|
||||
*/
|
||||
int ZEXPORT compress2 (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level)
|
||||
{
|
||||
z_stream stream;
|
||||
int err;
|
||||
|
||||
stream.next_in = (Bytef *)source;
|
||||
stream.avail_in = (uInt)sourceLen;
|
||||
#ifdef MAXSEG_64K
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
|
||||
#endif
|
||||
stream.next_out = dest;
|
||||
stream.avail_out = (uInt)*destLen;
|
||||
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
|
||||
|
||||
stream.zalloc = Z_NULL;
|
||||
stream.zfree = Z_NULL;
|
||||
stream.opaque = (voidpf)0;
|
||||
|
||||
err = deflateInit(&stream, level);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
err = deflate(&stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
deflateEnd(&stream);
|
||||
return err == Z_OK ? Z_BUF_ERROR : err;
|
||||
}
|
||||
*destLen = stream.total_out;
|
||||
|
||||
err = deflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
*/
|
||||
int ZEXPORT compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)
|
||||
{
|
||||
return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
If the default memLevel or windowBits for deflateInit() is changed, then
|
||||
this function needs to be updated.
|
||||
*/
|
||||
uLong ZEXPORT compressBound (uLong sourceLen)
|
||||
{
|
||||
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
|
||||
(sourceLen >> 25) + 13;
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/* gzclose.c -- zlib gzclose() function
|
||||
* Copyright (C) 2004, 2010 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
extern int gzclose_w(gzFile file);
|
||||
extern int gzclose_r(gzFile file);
|
||||
|
||||
/* gzclose() is in a separate file so that it is linked in only if it is used.
|
||||
That way the other gzclose functions can be used instead to avoid linking in
|
||||
unneeded compression or decompression routines. */
|
||||
int gzclose(gzFile file)
|
||||
{
|
||||
#ifndef NO_GZCOMPRESS
|
||||
gz_statep state;
|
||||
|
||||
if (file == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (gz_statep)file;
|
||||
|
||||
return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file);
|
||||
#else
|
||||
return gzclose_r(file);
|
||||
#endif
|
||||
}
|
@ -1,604 +0,0 @@
|
||||
/* gzlib.c -- zlib functions common to reading and writing gzip files
|
||||
* Copyright (C) 2004, 2010, 2011, 2012, 2013 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
#if defined(_WIN32) && !defined(__BORLANDC__)
|
||||
# define LSEEK _lseeki64
|
||||
#else
|
||||
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
|
||||
# define LSEEK lseek64
|
||||
#else
|
||||
# define LSEEK lseek
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
z_off_t ZEXPORT gzoffset(gzFile file);
|
||||
int ZEXPORT gzbuffer(gzFile file, unsigned size);
|
||||
|
||||
/* Local functions */
|
||||
local void gz_reset OF((gz_statep));
|
||||
local gzFile gz_open OF((const void *, int, const char *));
|
||||
|
||||
#if defined UNDER_CE
|
||||
|
||||
/* Map the Windows error number in ERROR to a locale-dependent error message
|
||||
string and return a pointer to it. Typically, the values for ERROR come
|
||||
from GetLastError.
|
||||
|
||||
The string pointed to shall not be modified by the application, but may be
|
||||
overwritten by a subsequent call to gz_strwinerror
|
||||
|
||||
The gz_strwinerror function does not change the current setting of
|
||||
GetLastError. */
|
||||
char ZLIB_INTERNAL *gz_strwinerror (error)
|
||||
DWORD error;
|
||||
{
|
||||
static char buf[1024];
|
||||
|
||||
wchar_t *msgbuf;
|
||||
DWORD lasterr = GetLastError();
|
||||
DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
|
||||
| FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
||||
NULL,
|
||||
error,
|
||||
0, /* Default language */
|
||||
(LPVOID)&msgbuf,
|
||||
0,
|
||||
NULL);
|
||||
if (chars != 0) {
|
||||
/* If there is an \r\n appended, zap it. */
|
||||
if (chars >= 2
|
||||
&& msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
|
||||
chars -= 2;
|
||||
msgbuf[chars] = 0;
|
||||
}
|
||||
|
||||
if (chars > sizeof (buf) - 1) {
|
||||
chars = sizeof (buf) - 1;
|
||||
msgbuf[chars] = 0;
|
||||
}
|
||||
|
||||
wcstombs(buf, msgbuf, chars + 1);
|
||||
LocalFree(msgbuf);
|
||||
}
|
||||
else {
|
||||
sprintf(buf, "unknown win32 error (%ld)", error);
|
||||
}
|
||||
|
||||
SetLastError(lasterr);
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif /* UNDER_CE */
|
||||
|
||||
/* Reset gzip file state */
|
||||
local void gz_reset(gz_statep state)
|
||||
{
|
||||
state->x.have = 0; /* no output data available */
|
||||
if (state->mode == GZ_READ) { /* for reading ... */
|
||||
state->eof = 0; /* not at end of file */
|
||||
state->past = 0; /* have not read past end yet */
|
||||
state->how = LOOK; /* look for gzip header */
|
||||
}
|
||||
state->seek = 0; /* no seek request pending */
|
||||
gz_error(state, Z_OK, NULL); /* clear error */
|
||||
state->x.pos = 0; /* no uncompressed data yet */
|
||||
state->strm.avail_in = 0; /* no input data yet */
|
||||
}
|
||||
|
||||
/* Open a gzip file either by name or file descriptor. */
|
||||
local gzFile gz_open(const void *path, int fd, const char *mode)
|
||||
{
|
||||
gz_statep state;
|
||||
size_t len;
|
||||
int oflag;
|
||||
#ifdef O_CLOEXEC
|
||||
int cloexec = 0;
|
||||
#endif
|
||||
#ifdef O_EXCL
|
||||
int exclusive = 0;
|
||||
#endif
|
||||
|
||||
/* check input */
|
||||
if (path == NULL)
|
||||
return NULL;
|
||||
|
||||
/* allocate gzFile structure to return */
|
||||
state = (gz_statep)malloc(sizeof(gz_state));
|
||||
if (state == NULL)
|
||||
return NULL;
|
||||
state->size = 0; /* no buffers allocated yet */
|
||||
state->want = GZBUFSIZE; /* requested buffer size */
|
||||
state->msg = NULL; /* no error message yet */
|
||||
|
||||
/* interpret mode */
|
||||
state->mode = GZ_NONE;
|
||||
state->level = Z_DEFAULT_COMPRESSION;
|
||||
state->strategy = Z_DEFAULT_STRATEGY;
|
||||
state->direct = 0;
|
||||
while (*mode) {
|
||||
if (*mode >= '0' && *mode <= '9')
|
||||
state->level = *mode - '0';
|
||||
else
|
||||
switch (*mode) {
|
||||
case 'r':
|
||||
state->mode = GZ_READ;
|
||||
break;
|
||||
#ifndef NO_GZCOMPRESS
|
||||
case 'w':
|
||||
state->mode = GZ_WRITE;
|
||||
break;
|
||||
case 'a':
|
||||
state->mode = GZ_APPEND;
|
||||
break;
|
||||
#endif
|
||||
case '+': /* can't read and write at the same time */
|
||||
free(state);
|
||||
return NULL;
|
||||
case 'b': /* ignore -- will request binary anyway */
|
||||
break;
|
||||
#ifdef O_CLOEXEC
|
||||
case 'e':
|
||||
cloexec = 1;
|
||||
break;
|
||||
#endif
|
||||
#ifdef O_EXCL
|
||||
case 'x':
|
||||
exclusive = 1;
|
||||
break;
|
||||
#endif
|
||||
case 'f':
|
||||
state->strategy = Z_FILTERED;
|
||||
break;
|
||||
case 'h':
|
||||
state->strategy = Z_HUFFMAN_ONLY;
|
||||
break;
|
||||
case 'R':
|
||||
state->strategy = Z_RLE;
|
||||
break;
|
||||
case 'F':
|
||||
state->strategy = Z_FIXED;
|
||||
break;
|
||||
case 'T':
|
||||
state->direct = 1;
|
||||
break;
|
||||
default: /* could consider as an error, but just ignore */
|
||||
;
|
||||
}
|
||||
mode++;
|
||||
}
|
||||
|
||||
/* must provide an "r", "w", or "a" */
|
||||
if (state->mode == GZ_NONE) {
|
||||
free(state);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* can't force transparent read */
|
||||
if (state->mode == GZ_READ) {
|
||||
if (state->direct) {
|
||||
free(state);
|
||||
return NULL;
|
||||
}
|
||||
state->direct = 1; /* for empty file */
|
||||
}
|
||||
|
||||
/* save the path name for error messages */
|
||||
#ifdef _WIN32
|
||||
if (fd == -2) {
|
||||
len = wcstombs(NULL, (const wchar_t*)path, 0);
|
||||
if (len == (size_t)-1)
|
||||
len = 0;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
len = strlen((const char *)path);
|
||||
state->path = (char *)malloc(len + 1);
|
||||
if (state->path == NULL) {
|
||||
free(state);
|
||||
return NULL;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
if (fd == -2)
|
||||
if (len)
|
||||
wcstombs(state->path, (const wchar_t*)path, len + 1);
|
||||
else
|
||||
*(state->path) = 0;
|
||||
else
|
||||
#endif
|
||||
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
|
||||
snprintf(state->path, len + 1, "%s", (const char *)path);
|
||||
#else
|
||||
strlcpy(state->path, path, sizeof(state->path));
|
||||
#endif
|
||||
|
||||
/* compute the flags for open() */
|
||||
oflag =
|
||||
#ifdef O_LARGEFILE
|
||||
O_LARGEFILE |
|
||||
#endif
|
||||
#ifdef O_BINARY
|
||||
O_BINARY |
|
||||
#endif
|
||||
#ifdef O_CLOEXEC
|
||||
(cloexec ? O_CLOEXEC : 0) |
|
||||
#endif
|
||||
(state->mode == GZ_READ ?
|
||||
O_RDONLY :
|
||||
(O_WRONLY | O_CREAT |
|
||||
#ifdef O_EXCL
|
||||
(exclusive ? O_EXCL : 0) |
|
||||
#endif
|
||||
(state->mode == GZ_WRITE ?
|
||||
O_TRUNC :
|
||||
O_APPEND)));
|
||||
|
||||
/* open the file with the appropriate flags (or just use fd) */
|
||||
state->fd = fd > -1 ? fd : (
|
||||
#ifdef _WIN32
|
||||
fd == -2 ? _wopen((const wchar_t*)path, oflag, 0666) :
|
||||
#endif
|
||||
open((const char *)path, oflag, 0666));
|
||||
if (state->fd == -1) {
|
||||
free(state->path);
|
||||
free(state);
|
||||
return NULL;
|
||||
}
|
||||
if (state->mode == GZ_APPEND)
|
||||
state->mode = GZ_WRITE; /* simplify later checks */
|
||||
|
||||
/* save the current position for rewinding (only if reading) */
|
||||
if (state->mode == GZ_READ) {
|
||||
state->start = LSEEK(state->fd, 0, SEEK_CUR);
|
||||
if (state->start == -1) state->start = 0;
|
||||
}
|
||||
|
||||
/* initialize stream */
|
||||
gz_reset(state);
|
||||
|
||||
/* return stream */
|
||||
return (gzFile)state;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
gzFile ZEXPORT gzopen(const char *path, const char *mode)
|
||||
{
|
||||
return gz_open(path, -1, mode);
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
gzFile ZEXPORT gzopen64(const char *path, const char *mode)
|
||||
{
|
||||
return gz_open(path, -1, mode);
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
gzFile ZEXPORT gzdopen(int fd, const char *mode)
|
||||
{
|
||||
char *path; /* identifier for error messages */
|
||||
gzFile gz;
|
||||
|
||||
if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
|
||||
return NULL;
|
||||
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
|
||||
snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */
|
||||
#else
|
||||
sprintf(path, "<fd:%d>", fd); /* for debugging */
|
||||
#endif
|
||||
gz = gz_open(path, fd, mode);
|
||||
free(path);
|
||||
return gz;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
#ifdef _WIN32
|
||||
gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode)
|
||||
{
|
||||
return gz_open(path, -2, mode);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzbuffer(gzFile file, unsigned size)
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
||||
return -1;
|
||||
|
||||
/* make sure we haven't already allocated memory */
|
||||
if (state->size != 0)
|
||||
return -1;
|
||||
|
||||
/* check and set requested size */
|
||||
if (size < 2)
|
||||
size = 2; /* need two bytes to check magic header */
|
||||
state->want = size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzrewind(gzFile file)
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're reading and that there's no error */
|
||||
if (state->mode != GZ_READ ||
|
||||
(state->err != Z_OK && state->err != Z_BUF_ERROR))
|
||||
return -1;
|
||||
|
||||
/* back up and start over */
|
||||
if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
|
||||
return -1;
|
||||
gz_reset(state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence)
|
||||
{
|
||||
unsigned n;
|
||||
z_off64_t ret;
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
||||
return -1;
|
||||
|
||||
/* check that there's no error */
|
||||
if (state->err != Z_OK && state->err != Z_BUF_ERROR)
|
||||
return -1;
|
||||
|
||||
/* can only seek from start or relative to current position */
|
||||
if (whence != SEEK_SET && whence != SEEK_CUR)
|
||||
return -1;
|
||||
|
||||
/* normalize offset to a SEEK_CUR specification */
|
||||
if (whence == SEEK_SET)
|
||||
offset -= state->x.pos;
|
||||
else if (state->seek)
|
||||
offset += state->skip;
|
||||
state->seek = 0;
|
||||
|
||||
/* if within raw area while reading, just go there */
|
||||
if (state->mode == GZ_READ && state->how == MODE_COPY &&
|
||||
state->x.pos + offset >= 0) {
|
||||
ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
|
||||
if (ret == -1)
|
||||
return -1;
|
||||
state->x.have = 0;
|
||||
state->eof = 0;
|
||||
state->past = 0;
|
||||
state->seek = 0;
|
||||
gz_error(state, Z_OK, NULL);
|
||||
state->strm.avail_in = 0;
|
||||
state->x.pos += offset;
|
||||
return state->x.pos;
|
||||
}
|
||||
|
||||
/* calculate skip amount, rewinding if needed for back seek when reading */
|
||||
if (offset < 0) {
|
||||
if (state->mode != GZ_READ) /* writing -- can't go backwards */
|
||||
return -1;
|
||||
offset += state->x.pos;
|
||||
if (offset < 0) /* before start of file! */
|
||||
return -1;
|
||||
if (gzrewind(file) == -1) /* rewind, then skip to offset */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* if reading, skip what's in output buffer (one less gzgetc() check) */
|
||||
if (state->mode == GZ_READ) {
|
||||
n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
|
||||
(unsigned)offset : state->x.have;
|
||||
state->x.have -= n;
|
||||
state->x.next += n;
|
||||
state->x.pos += n;
|
||||
offset -= n;
|
||||
}
|
||||
|
||||
/* request skip (if not zero) */
|
||||
if (offset) {
|
||||
state->seek = 1;
|
||||
state->skip = offset;
|
||||
}
|
||||
return state->x.pos + offset;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence)
|
||||
{
|
||||
z_off64_t ret;
|
||||
|
||||
ret = gzseek64(file, (z_off64_t)offset, whence);
|
||||
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off64_t ZEXPORT gztell64(gzFile file)
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
||||
return -1;
|
||||
|
||||
/* return position */
|
||||
return state->x.pos + (state->seek ? state->skip : 0);
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off_t ZEXPORT gztell(gzFile file)
|
||||
{
|
||||
z_off64_t ret;
|
||||
|
||||
ret = gztell64(file);
|
||||
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off64_t ZEXPORT gzoffset64(gzFile file)
|
||||
{
|
||||
z_off64_t offset;
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
||||
return -1;
|
||||
|
||||
/* compute and return effective offset in file */
|
||||
offset = LSEEK(state->fd, 0, SEEK_CUR);
|
||||
if (offset == -1)
|
||||
return -1;
|
||||
if (state->mode == GZ_READ) /* reading */
|
||||
offset -= state->strm.avail_in; /* don't count buffered input */
|
||||
return offset;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off_t ZEXPORT gzoffset(gzFile file)
|
||||
{
|
||||
z_off64_t ret = gzoffset64(file);
|
||||
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzeof(gzFile file)
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return 0;
|
||||
state = (gz_statep)file;
|
||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
||||
return 0;
|
||||
|
||||
/* return end-of-file state */
|
||||
return state->mode == GZ_READ ? state->past : 0;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
const char * ZEXPORT gzerror(gzFile file, int *errnum)
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return NULL;
|
||||
state = (gz_statep)file;
|
||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
||||
return NULL;
|
||||
|
||||
/* return error information */
|
||||
if (errnum != NULL)
|
||||
*errnum = state->err;
|
||||
return state->err == Z_MEM_ERROR ? "out of memory" :
|
||||
(state->msg == NULL ? "" : state->msg);
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
void ZEXPORT gzclearerr(gzFile file)
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return;
|
||||
state = (gz_statep)file;
|
||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
||||
return;
|
||||
|
||||
/* clear error and end-of-file */
|
||||
if (state->mode == GZ_READ) {
|
||||
state->eof = 0;
|
||||
state->past = 0;
|
||||
}
|
||||
gz_error(state, Z_OK, NULL);
|
||||
}
|
||||
|
||||
/* Create an error message in allocated memory and set state->err and
|
||||
state->msg accordingly. Free any previous error message already there. Do
|
||||
not try to free or allocate space if the error is Z_MEM_ERROR (out of
|
||||
memory). Simply save the error message as a static string. If there is an
|
||||
allocation failure constructing the error message, then convert the error to
|
||||
out of memory. */
|
||||
void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg)
|
||||
{
|
||||
/* free previously allocated message and clear */
|
||||
if (state->msg != NULL) {
|
||||
if (state->err != Z_MEM_ERROR)
|
||||
free(state->msg);
|
||||
state->msg = NULL;
|
||||
}
|
||||
|
||||
/* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
|
||||
if (err != Z_OK && err != Z_BUF_ERROR)
|
||||
state->x.have = 0;
|
||||
|
||||
/* set error code, and if no message, then done */
|
||||
state->err = err;
|
||||
if (msg == NULL)
|
||||
return;
|
||||
|
||||
/* for an out of memory error, return literal string when requested */
|
||||
if (err == Z_MEM_ERROR)
|
||||
return;
|
||||
|
||||
/* construct error message with path */
|
||||
if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
|
||||
NULL) {
|
||||
state->err = Z_MEM_ERROR;
|
||||
return;
|
||||
}
|
||||
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
|
||||
snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
|
||||
"%s%s%s", state->path, ": ", msg);
|
||||
#else
|
||||
strlcpy(state->msg, state->path, sizeof(state->msg));
|
||||
strlcat(state->msg, ": ", sizeof(state->msg));
|
||||
strlcat(state->msg, msg, sizeof(state->msg));
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef INT_MAX
|
||||
/* portably return maximum value for an int (when limits.h presumed not
|
||||
available) -- we need to do this to cover cases where 2's complement not
|
||||
used, since C standard permits 1's complement and sign-bit representations,
|
||||
otherwise we could just use ((unsigned)-1) >> 1 */
|
||||
unsigned ZLIB_INTERNAL gz_intmax()
|
||||
{
|
||||
unsigned p, q;
|
||||
|
||||
p = 1;
|
||||
do {
|
||||
q = p;
|
||||
p <<= 1;
|
||||
p++;
|
||||
} while (p > q);
|
||||
return q >> 1;
|
||||
}
|
||||
#endif
|
@ -1,575 +0,0 @@
|
||||
/* gzread.c -- zlib functions for reading gzip files
|
||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
/* Local functions */
|
||||
local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
|
||||
local int gz_avail OF((gz_statep));
|
||||
local int gz_look OF((gz_statep));
|
||||
local int gz_decomp OF((gz_statep));
|
||||
local int gz_fetch OF((gz_statep));
|
||||
local int gz_skip OF((gz_statep, z_off64_t));
|
||||
|
||||
int ZEXPORT gzgetc_(gzFile file);
|
||||
|
||||
/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
|
||||
state->fd, and update state->eof, state->err, and state->msg as appropriate.
|
||||
This function needs to loop on read(), since read() is not guaranteed to
|
||||
read the number of bytes requested, depending on the type of descriptor. */
|
||||
local int gz_load(gz_statep state, unsigned char *buf, unsigned len, unsigned *have)
|
||||
{
|
||||
int ret;
|
||||
|
||||
*have = 0;
|
||||
do {
|
||||
ret = read(state->fd, buf + *have, len - *have);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
*have += ret;
|
||||
} while (*have < len);
|
||||
if (ret < 0) {
|
||||
gz_error(state, Z_ERRNO, zstrerror());
|
||||
return -1;
|
||||
}
|
||||
if (ret == 0)
|
||||
state->eof = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Load up input buffer and set eof flag if last data loaded -- return -1 on
|
||||
error, 0 otherwise. Note that the eof flag is set when the end of the input
|
||||
file is reached, even though there may be unused data in the buffer. Once
|
||||
that data has been used, no more attempts will be made to read the file.
|
||||
If strm->avail_in != 0, then the current data is moved to the beginning of
|
||||
the input buffer, and then the remainder of the buffer is loaded with the
|
||||
available data from the input file. */
|
||||
local int gz_avail(gz_statep state)
|
||||
{
|
||||
unsigned got;
|
||||
z_streamp strm = &(state->strm);
|
||||
|
||||
if (state->err != Z_OK && state->err != Z_BUF_ERROR)
|
||||
return -1;
|
||||
if (state->eof == 0) {
|
||||
if (strm->avail_in) { /* copy what's there to the start */
|
||||
unsigned char *p = state->in;
|
||||
unsigned const char *q = strm->next_in;
|
||||
unsigned n = strm->avail_in;
|
||||
do {
|
||||
*p++ = *q++;
|
||||
} while (--n);
|
||||
}
|
||||
if (gz_load(state, state->in + strm->avail_in,
|
||||
state->size - strm->avail_in, &got) == -1)
|
||||
return -1;
|
||||
strm->avail_in += got;
|
||||
strm->next_in = state->in;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Look for gzip header, set up for inflate or copy. state->x.have must be 0.
|
||||
If this is the first time in, allocate required memory. state->how will be
|
||||
left unchanged if there is no more input data available, will be set to COPY
|
||||
if there is no gzip header and direct copying will be performed, or it will
|
||||
be set to GZIP for decompression. If direct copying, then leftover input
|
||||
data from the input buffer will be copied to the output buffer. In that
|
||||
case, all further file reads will be directly to either the output buffer or
|
||||
a user buffer. If decompressing, the inflate state will be initialized.
|
||||
gz_look() will return 0 on success or -1 on failure. */
|
||||
local int gz_look(gz_statep state)
|
||||
{
|
||||
z_streamp strm = &(state->strm);
|
||||
|
||||
/* allocate read buffers and inflate memory */
|
||||
if (state->size == 0) {
|
||||
/* allocate buffers */
|
||||
state->in = (unsigned char *)malloc(state->want);
|
||||
state->out = (unsigned char *)malloc(state->want << 1);
|
||||
if (state->in == NULL || state->out == NULL) {
|
||||
if (state->out != NULL)
|
||||
free(state->out);
|
||||
if (state->in != NULL)
|
||||
free(state->in);
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
state->size = state->want;
|
||||
|
||||
/* allocate inflate memory */
|
||||
state->strm.zalloc = Z_NULL;
|
||||
state->strm.zfree = Z_NULL;
|
||||
state->strm.opaque = Z_NULL;
|
||||
state->strm.avail_in = 0;
|
||||
state->strm.next_in = Z_NULL;
|
||||
if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */
|
||||
free(state->out);
|
||||
free(state->in);
|
||||
state->size = 0;
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* get at least the magic bytes in the input buffer */
|
||||
if (strm->avail_in < 2) {
|
||||
if (gz_avail(state) == -1)
|
||||
return -1;
|
||||
if (strm->avail_in == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* look for gzip magic bytes -- if there, do gzip decoding (note: there is
|
||||
a logical dilemma here when considering the case of a partially written
|
||||
gzip file, to wit, if a single 31 byte is written, then we cannot tell
|
||||
whether this is a single-byte file, or just a partially written gzip
|
||||
file -- for here we assume that if a gzip file is being written, then
|
||||
the header will be written in a single operation, so that reading a
|
||||
single byte is sufficient indication that it is not a gzip file) */
|
||||
if (strm->avail_in > 1 &&
|
||||
strm->next_in[0] == 31 && strm->next_in[1] == 139) {
|
||||
inflateReset(strm);
|
||||
state->how = MODE_GZIP;
|
||||
state->direct = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* no gzip header -- if we were decoding gzip before, then this is trailing
|
||||
garbage. Ignore the trailing garbage and finish. */
|
||||
if (state->direct == 0) {
|
||||
strm->avail_in = 0;
|
||||
state->eof = 1;
|
||||
state->x.have = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* doing raw i/o, copy any leftover input to output -- this assumes that
|
||||
the output buffer is larger than the input buffer, which also assures
|
||||
space for gzungetc() */
|
||||
state->x.next = state->out;
|
||||
if (strm->avail_in) {
|
||||
memcpy(state->x.next, strm->next_in, strm->avail_in);
|
||||
state->x.have = strm->avail_in;
|
||||
strm->avail_in = 0;
|
||||
}
|
||||
state->how = MODE_COPY;
|
||||
state->direct = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Decompress from input to the provided next_out and avail_out in the state.
|
||||
On return, state->x.have and state->x.next point to the just decompressed
|
||||
data. If the gzip stream completes, state->how is reset to LOOK to look for
|
||||
the next gzip stream or raw data, once state->x.have is depleted. Returns 0
|
||||
on success, -1 on failure. */
|
||||
local int gz_decomp(gz_statep state)
|
||||
{
|
||||
int ret = Z_OK;
|
||||
unsigned had;
|
||||
z_streamp strm = &(state->strm);
|
||||
|
||||
/* fill output buffer up to end of deflate stream */
|
||||
had = strm->avail_out;
|
||||
do {
|
||||
/* get more input for inflate() */
|
||||
if (strm->avail_in == 0 && gz_avail(state) == -1)
|
||||
return -1;
|
||||
if (strm->avail_in == 0) {
|
||||
gz_error(state, Z_BUF_ERROR, "unexpected end of file");
|
||||
break;
|
||||
}
|
||||
|
||||
/* decompress and handle errors */
|
||||
ret = inflate(strm, Z_NO_FLUSH);
|
||||
if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
|
||||
gz_error(state, Z_STREAM_ERROR,
|
||||
"internal error: inflate stream corrupt");
|
||||
return -1;
|
||||
}
|
||||
if (ret == Z_MEM_ERROR) {
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
|
||||
gz_error(state, Z_DATA_ERROR,
|
||||
strm->msg == NULL ? "compressed data error" : strm->msg);
|
||||
return -1;
|
||||
}
|
||||
} while (strm->avail_out && ret != Z_STREAM_END);
|
||||
|
||||
/* update available output */
|
||||
state->x.have = had - strm->avail_out;
|
||||
state->x.next = strm->next_out - state->x.have;
|
||||
|
||||
/* if the gzip stream completed successfully, look for another */
|
||||
if (ret == Z_STREAM_END)
|
||||
state->how = LOOK;
|
||||
|
||||
/* good decompression */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fetch data and put it in the output buffer. Assumes state->x.have is 0.
|
||||
Data is either copied from the input file or decompressed from the input
|
||||
file depending on state->how. If state->how is LOOK, then a gzip header is
|
||||
looked for to determine whether to copy or decompress. Returns -1 on error,
|
||||
otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the
|
||||
end of the input file has been reached and all data has been processed. */
|
||||
local int gz_fetch(gz_statep state)
|
||||
{
|
||||
z_streamp strm = &(state->strm);
|
||||
|
||||
do {
|
||||
switch(state->how) {
|
||||
case LOOK: /* -> LOOK, MODE_COPY (only if never GZIP), or MODE_GZIP */
|
||||
if (gz_look(state) == -1)
|
||||
return -1;
|
||||
if (state->how == LOOK)
|
||||
return 0;
|
||||
break;
|
||||
case MODE_COPY: /* -> MODE_COPY */
|
||||
if (gz_load(state, state->out, state->size << 1, &(state->x.have))
|
||||
== -1)
|
||||
return -1;
|
||||
state->x.next = state->out;
|
||||
return 0;
|
||||
case MODE_GZIP: /* -> GZIP or LOOK (if end of gzip stream) */
|
||||
strm->avail_out = state->size << 1;
|
||||
strm->next_out = state->out;
|
||||
if (gz_decomp(state) == -1)
|
||||
return -1;
|
||||
}
|
||||
} while (state->x.have == 0 && (!state->eof || strm->avail_in));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */
|
||||
local int gz_skip(gz_statep state, z_off64_t len)
|
||||
{
|
||||
unsigned n;
|
||||
|
||||
/* skip over len bytes or reach end-of-file, whichever comes first */
|
||||
while (len)
|
||||
/* skip over whatever is in output buffer */
|
||||
if (state->x.have) {
|
||||
n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
|
||||
(unsigned)len : state->x.have;
|
||||
state->x.have -= n;
|
||||
state->x.next += n;
|
||||
state->x.pos += n;
|
||||
len -= n;
|
||||
}
|
||||
|
||||
/* output buffer empty -- return if we're at the end of the input */
|
||||
else if (state->eof && state->strm.avail_in == 0)
|
||||
break;
|
||||
|
||||
/* need more data to skip -- load up output buffer */
|
||||
else {
|
||||
/* get more output, looking for header if required */
|
||||
if (gz_fetch(state) == -1)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzread(gzFile file, voidp buf, unsigned len)
|
||||
{
|
||||
unsigned got, n;
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
strm = &(state->strm);
|
||||
|
||||
/* check that we're reading and that there's no (serious) error */
|
||||
if (state->mode != GZ_READ ||
|
||||
(state->err != Z_OK && state->err != Z_BUF_ERROR))
|
||||
return -1;
|
||||
|
||||
/* since an int is returned, make sure len fits in one, otherwise return
|
||||
with an error (this avoids the flaw in the interface) */
|
||||
if ((int)len < 0) {
|
||||
gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* if len is zero, avoid unnecessary operations */
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
/* process a skip request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_skip(state, state->skip) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* get len bytes to buf, or less than len if at the end */
|
||||
got = 0;
|
||||
n = 0;
|
||||
do {
|
||||
/* first just try copying data from the output buffer */
|
||||
if (state->x.have) {
|
||||
n = state->x.have > len ? len : state->x.have;
|
||||
memcpy(buf, state->x.next, n);
|
||||
state->x.next += n;
|
||||
state->x.have -= n;
|
||||
}
|
||||
|
||||
/* output buffer empty -- return if we're at the end of the input */
|
||||
else if (state->eof && strm->avail_in == 0) {
|
||||
state->past = 1; /* tried to read past end */
|
||||
break;
|
||||
}
|
||||
|
||||
/* need output data -- for small len or new stream load up our output
|
||||
buffer */
|
||||
else if (state->how == LOOK || len < (state->size << 1)) {
|
||||
/* get more output, looking for header if required */
|
||||
if (gz_fetch(state) == -1)
|
||||
return -1;
|
||||
continue; /* no progress yet -- go back to copy above */
|
||||
/* the copy above assures that we will leave with space in the
|
||||
output buffer, allowing at least one gzungetc() to succeed */
|
||||
}
|
||||
|
||||
/* large len -- read directly into user buffer */
|
||||
else if (state->how == MODE_COPY) { /* read directly */
|
||||
if (gz_load(state, (unsigned char *)buf, len, &n) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* large len -- decompress directly into user buffer */
|
||||
else { /* state->how == GZIP */
|
||||
strm->avail_out = len;
|
||||
strm->next_out = (unsigned char *)buf;
|
||||
if (gz_decomp(state) == -1)
|
||||
return -1;
|
||||
n = state->x.have;
|
||||
state->x.have = 0;
|
||||
}
|
||||
|
||||
/* update progress */
|
||||
len -= n;
|
||||
buf = (char *)buf + n;
|
||||
got += n;
|
||||
state->x.pos += n;
|
||||
} while (len);
|
||||
|
||||
/* return number of bytes read into user buffer (will fit in int) */
|
||||
return (int)got;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
#ifdef Z_PREFIX_SET
|
||||
# undef z_gzgetc
|
||||
#else
|
||||
# undef gzgetc
|
||||
#endif
|
||||
int ZEXPORT gzgetc(gzFile file)
|
||||
{
|
||||
int ret;
|
||||
unsigned char buf[1];
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're reading and that there's no (serious) error */
|
||||
if (state->mode != GZ_READ ||
|
||||
(state->err != Z_OK && state->err != Z_BUF_ERROR))
|
||||
return -1;
|
||||
|
||||
/* try output buffer (no need to check for skip request) */
|
||||
if (state->x.have) {
|
||||
state->x.have--;
|
||||
state->x.pos++;
|
||||
return *(state->x.next)++;
|
||||
}
|
||||
|
||||
/* nothing there -- try gzread() */
|
||||
ret = gzread(file, buf, 1);
|
||||
return ret < 1 ? -1 : buf[0];
|
||||
}
|
||||
|
||||
int ZEXPORT gzgetc_(gzFile file)
|
||||
{
|
||||
return gzgetc(file);
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzungetc(int c, gzFile file)
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're reading and that there's no (serious) error */
|
||||
if (state->mode != GZ_READ ||
|
||||
(state->err != Z_OK && state->err != Z_BUF_ERROR))
|
||||
return -1;
|
||||
|
||||
/* process a skip request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_skip(state, state->skip) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* can't push EOF */
|
||||
if (c < 0)
|
||||
return -1;
|
||||
|
||||
/* if output buffer empty, put byte at end (allows more pushing) */
|
||||
if (state->x.have == 0) {
|
||||
state->x.have = 1;
|
||||
state->x.next = state->out + (state->size << 1) - 1;
|
||||
state->x.next[0] = c;
|
||||
state->x.pos--;
|
||||
state->past = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
/* if no room, give up (must have already done a gzungetc()) */
|
||||
if (state->x.have == (state->size << 1)) {
|
||||
gz_error(state, Z_DATA_ERROR, "out of room to push characters");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* slide output data if needed and insert byte before existing data */
|
||||
if (state->x.next == state->out) {
|
||||
unsigned char *src = state->out + state->x.have;
|
||||
unsigned char *dest = state->out + (state->size << 1);
|
||||
while (src > state->out)
|
||||
*--dest = *--src;
|
||||
state->x.next = dest;
|
||||
}
|
||||
state->x.have++;
|
||||
state->x.next--;
|
||||
state->x.next[0] = c;
|
||||
state->x.pos--;
|
||||
state->past = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
char * ZEXPORT gzgets(gzFile file, char *buf, int len)
|
||||
{
|
||||
unsigned left, n;
|
||||
char *str;
|
||||
unsigned char *eol;
|
||||
gz_statep state;
|
||||
|
||||
/* check parameters and get internal structure */
|
||||
if (file == NULL || buf == NULL || len < 1)
|
||||
return NULL;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're reading and that there's no (serious) error */
|
||||
if (state->mode != GZ_READ ||
|
||||
(state->err != Z_OK && state->err != Z_BUF_ERROR))
|
||||
return NULL;
|
||||
|
||||
/* process a skip request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_skip(state, state->skip) == -1)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* copy output bytes up to new line or len - 1, whichever comes first --
|
||||
append a terminating zero to the string (we don't check for a zero in
|
||||
the contents, let the user worry about that) */
|
||||
str = buf;
|
||||
left = (unsigned)len - 1;
|
||||
if (left) do {
|
||||
/* assure that something is in the output buffer */
|
||||
if (state->x.have == 0 && gz_fetch(state) == -1)
|
||||
return NULL; /* error */
|
||||
if (state->x.have == 0) { /* end of file */
|
||||
state->past = 1; /* read past end */
|
||||
break; /* return what we have */
|
||||
}
|
||||
|
||||
/* look for end-of-line in current output buffer */
|
||||
n = state->x.have > left ? left : state->x.have;
|
||||
eol = (unsigned char *)memchr(state->x.next, '\n', n);
|
||||
if (eol != NULL)
|
||||
n = (unsigned)(eol - state->x.next) + 1;
|
||||
|
||||
/* copy through end-of-line, or remainder if not found */
|
||||
memcpy(buf, state->x.next, n);
|
||||
state->x.have -= n;
|
||||
state->x.next += n;
|
||||
state->x.pos += n;
|
||||
left -= n;
|
||||
buf += n;
|
||||
} while (left && eol == NULL);
|
||||
|
||||
/* return terminated string, or if nothing, end of file */
|
||||
if (buf == str)
|
||||
return NULL;
|
||||
buf[0] = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzdirect(gzFile file)
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return 0;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* if the state is not known, but we can find out, then do so (this is
|
||||
mainly for right after a gzopen() or gzdopen()) */
|
||||
if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
|
||||
(void)gz_look(state);
|
||||
|
||||
/* return 1 if transparent, 0 if processing a gzip stream */
|
||||
return state->direct;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int gzclose_r(gzFile file)
|
||||
{
|
||||
int ret, err;
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're reading */
|
||||
if (state->mode != GZ_READ)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
/* free memory and close file */
|
||||
if (state->size) {
|
||||
inflateEnd(&(state->strm));
|
||||
free(state->out);
|
||||
free(state->in);
|
||||
}
|
||||
err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
|
||||
gz_error(state, Z_OK, NULL);
|
||||
free(state->path);
|
||||
ret = close(state->fd);
|
||||
free(state);
|
||||
return ret ? Z_ERRNO : err;
|
||||
}
|
@ -1,557 +0,0 @@
|
||||
/* gzwrite.c -- zlib functions for writing gzip files
|
||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
/* Local functions */
|
||||
local int gz_init OF((gz_statep));
|
||||
local int gz_comp OF((gz_statep, int));
|
||||
local int gz_zero OF((gz_statep, z_off64_t));
|
||||
|
||||
int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va);
|
||||
|
||||
/* Initialize state for writing a gzip file. Mark initialization by setting
|
||||
state->size to non-zero. Return -1 on failure or 0 on success. */
|
||||
local int gz_init(gz_statep state)
|
||||
{
|
||||
int ret;
|
||||
z_streamp strm = &(state->strm);
|
||||
|
||||
/* allocate input buffer */
|
||||
state->in = (unsigned char *)malloc(state->want);
|
||||
if (state->in == NULL) {
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* only need output buffer and deflate state if compressing */
|
||||
if (!state->direct) {
|
||||
/* allocate output buffer */
|
||||
state->out = (unsigned char *)malloc(state->want);
|
||||
if (state->out == NULL) {
|
||||
free(state->in);
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* allocate deflate memory, set up for gzip compression */
|
||||
strm->zalloc = Z_NULL;
|
||||
strm->zfree = Z_NULL;
|
||||
strm->opaque = Z_NULL;
|
||||
ret = deflateInit2(strm, state->level, Z_DEFLATED,
|
||||
MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
|
||||
if (ret != Z_OK) {
|
||||
free(state->out);
|
||||
free(state->in);
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* mark state as initialized */
|
||||
state->size = state->want;
|
||||
|
||||
/* initialize write buffer if compressing */
|
||||
if (!state->direct) {
|
||||
strm->avail_out = state->size;
|
||||
strm->next_out = state->out;
|
||||
state->x.next = strm->next_out;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compress whatever is at avail_in and next_in and write to the output file.
|
||||
Return -1 if there is an error writing to the output file, otherwise 0.
|
||||
flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
|
||||
then the deflate() state is reset to start a new gzip stream. If gz->direct
|
||||
is true, then simply write to the output file without compressing, and
|
||||
ignore flush. */
|
||||
local int gz_comp(gz_statep state, int flush)
|
||||
{
|
||||
int ret, got;
|
||||
unsigned have;
|
||||
z_streamp strm = &(state->strm);
|
||||
|
||||
/* allocate memory if this is the first time through */
|
||||
if (state->size == 0 && gz_init(state) == -1)
|
||||
return -1;
|
||||
|
||||
/* write directly if requested */
|
||||
if (state->direct) {
|
||||
got = write(state->fd, strm->next_in, strm->avail_in);
|
||||
if (got < 0 || (unsigned)got != strm->avail_in) {
|
||||
gz_error(state, Z_ERRNO, zstrerror());
|
||||
return -1;
|
||||
}
|
||||
strm->avail_in = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* run deflate() on provided input until it produces no more output */
|
||||
ret = Z_OK;
|
||||
do {
|
||||
/* write out current buffer contents if full, or if flushing, but if
|
||||
doing Z_FINISH then don't write until we get to Z_STREAM_END */
|
||||
if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
|
||||
(flush != Z_FINISH || ret == Z_STREAM_END))) {
|
||||
have = (unsigned)(strm->next_out - state->x.next);
|
||||
if (have && ((got = write(state->fd, state->x.next, have)) < 0 ||
|
||||
(unsigned)got != have)) {
|
||||
gz_error(state, Z_ERRNO, zstrerror());
|
||||
return -1;
|
||||
}
|
||||
if (strm->avail_out == 0) {
|
||||
strm->avail_out = state->size;
|
||||
strm->next_out = state->out;
|
||||
}
|
||||
state->x.next = strm->next_out;
|
||||
}
|
||||
|
||||
/* compress */
|
||||
have = strm->avail_out;
|
||||
ret = deflate(strm, flush);
|
||||
if (ret == Z_STREAM_ERROR) {
|
||||
gz_error(state, Z_STREAM_ERROR,
|
||||
"internal error: deflate stream corrupt");
|
||||
return -1;
|
||||
}
|
||||
have -= strm->avail_out;
|
||||
} while (have);
|
||||
|
||||
/* if that completed a deflate stream, allow another to start */
|
||||
if (flush == Z_FINISH)
|
||||
deflateReset(strm);
|
||||
|
||||
/* all done, no errors */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compress len zeros to output. Return -1 on error, 0 on success. */
|
||||
local int gz_zero(gz_statep state, z_off64_t len)
|
||||
{
|
||||
int first;
|
||||
unsigned n;
|
||||
z_streamp strm = &(state->strm);
|
||||
|
||||
/* consume whatever's left in the input buffer */
|
||||
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return -1;
|
||||
|
||||
/* compress len zeros (len guaranteed > 0) */
|
||||
first = 1;
|
||||
while (len) {
|
||||
n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
|
||||
(unsigned)len : state->size;
|
||||
if (first) {
|
||||
memset(state->in, 0, n);
|
||||
first = 0;
|
||||
}
|
||||
strm->avail_in = n;
|
||||
strm->next_in = state->in;
|
||||
state->x.pos += n;
|
||||
if (gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return -1;
|
||||
len -= n;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len)
|
||||
{
|
||||
unsigned put = len;
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return 0;
|
||||
state = (gz_statep)file;
|
||||
strm = &(state->strm);
|
||||
|
||||
/* check that we're writing and that there's no error */
|
||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
||||
return 0;
|
||||
|
||||
/* since an int is returned, make sure len fits in one, otherwise return
|
||||
with an error (this avoids the flaw in the interface) */
|
||||
if ((int)len < 0) {
|
||||
gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if len is zero, avoid unnecessary operations */
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
/* allocate memory if this is the first time through */
|
||||
if (state->size == 0 && gz_init(state) == -1)
|
||||
return 0;
|
||||
|
||||
/* check for seek request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_zero(state, state->skip) == -1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* for small len, copy to input buffer, otherwise compress directly */
|
||||
if (len < state->size) {
|
||||
/* copy to input buffer, compress when full */
|
||||
do {
|
||||
unsigned have, copy;
|
||||
|
||||
if (strm->avail_in == 0)
|
||||
strm->next_in = state->in;
|
||||
have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
|
||||
copy = state->size - have;
|
||||
if (copy > len)
|
||||
copy = len;
|
||||
memcpy(state->in + have, buf, copy);
|
||||
strm->avail_in += copy;
|
||||
state->x.pos += copy;
|
||||
buf = (const char *)buf + copy;
|
||||
len -= copy;
|
||||
if (len && gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return 0;
|
||||
} while (len);
|
||||
}
|
||||
else {
|
||||
/* consume whatever's left in the input buffer */
|
||||
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return 0;
|
||||
|
||||
/* directly compress user buffer to file */
|
||||
strm->avail_in = len;
|
||||
strm->next_in = (Bytef *)buf;
|
||||
state->x.pos += len;
|
||||
if (gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* input was all buffered or compressed (put will fit in int) */
|
||||
return (int)put;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzputc(gzFile file, int c)
|
||||
{
|
||||
unsigned have;
|
||||
unsigned char buf[1];
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
strm = &(state->strm);
|
||||
|
||||
/* check that we're writing and that there's no error */
|
||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
||||
return -1;
|
||||
|
||||
/* check for seek request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_zero(state, state->skip) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* try writing to input buffer for speed (state->size == 0 if buffer not
|
||||
initialized) */
|
||||
if (state->size) {
|
||||
if (strm->avail_in == 0)
|
||||
strm->next_in = state->in;
|
||||
have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
|
||||
if (have < state->size) {
|
||||
state->in[have] = c;
|
||||
strm->avail_in++;
|
||||
state->x.pos++;
|
||||
return c & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
/* no room in buffer or not initialized, use gz_write() */
|
||||
buf[0] = c;
|
||||
if (gzwrite(file, buf, 1) != 1)
|
||||
return -1;
|
||||
return c & 0xff;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzputs(gzFile file, const char *str)
|
||||
{
|
||||
int ret;
|
||||
unsigned len;
|
||||
|
||||
/* write string */
|
||||
len = (unsigned)strlen(str);
|
||||
ret = gzwrite(file, str, len);
|
||||
return ret == 0 && len != 0 ? -1 : ret;
|
||||
}
|
||||
|
||||
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
|
||||
#include <stdarg.h>
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
|
||||
{
|
||||
int size, len;
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
strm = &(state->strm);
|
||||
|
||||
/* check that we're writing and that there's no error */
|
||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
||||
return 0;
|
||||
|
||||
/* make sure we have some buffer space */
|
||||
if (state->size == 0 && gz_init(state) == -1)
|
||||
return 0;
|
||||
|
||||
/* check for seek request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_zero(state, state->skip) == -1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* consume whatever's left in the input buffer */
|
||||
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return 0;
|
||||
|
||||
/* do the printf() into the input buffer, put length in len */
|
||||
size = (int)(state->size);
|
||||
state->in[size - 1] = 0;
|
||||
#ifdef NO_vsnprintf
|
||||
# ifdef HAS_vsprintf_void
|
||||
(void)vsprintf((char *)(state->in), format, va);
|
||||
for (len = 0; len < size; len++)
|
||||
if (state->in[len] == 0) break;
|
||||
# else
|
||||
len = vsprintf((char *)(state->in), format, va);
|
||||
# endif
|
||||
#else
|
||||
# ifdef HAS_vsnprintf_void
|
||||
(void)vsnprintf((char *)(state->in), size, format, va);
|
||||
len = strlen((char *)(state->in));
|
||||
# else
|
||||
len = vsnprintf((char *)(state->in), size, format, va);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* check that printf() results fit in buffer */
|
||||
if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
|
||||
return 0;
|
||||
|
||||
/* update buffer and position, defer compression until needed */
|
||||
strm->avail_in = (unsigned)len;
|
||||
strm->next_in = state->in;
|
||||
state->x.pos += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
|
||||
{
|
||||
va_list va;
|
||||
int ret;
|
||||
|
||||
va_start(va, format);
|
||||
ret = gzvprintf(file, format, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else /* !STDC && !Z_HAVE_STDARG_H */
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORTVA gzprintf (gzFile file, const char *format, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10,
|
||||
int a11, int a12, int a13, int a14, int a15, int a16, int a17, int a18, int a19, int a20)
|
||||
{
|
||||
int size, len;
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
strm = &(state->strm);
|
||||
|
||||
/* check that can really pass pointer in ints */
|
||||
if (sizeof(int) != sizeof(void *))
|
||||
return 0;
|
||||
|
||||
/* check that we're writing and that there's no error */
|
||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
||||
return 0;
|
||||
|
||||
/* make sure we have some buffer space */
|
||||
if (state->size == 0 && gz_init(state) == -1)
|
||||
return 0;
|
||||
|
||||
/* check for seek request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_zero(state, state->skip) == -1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* consume whatever's left in the input buffer */
|
||||
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return 0;
|
||||
|
||||
/* do the printf() into the input buffer, put length in len */
|
||||
size = (int)(state->size);
|
||||
state->in[size - 1] = 0;
|
||||
#ifdef NO_snprintf
|
||||
# ifdef HAS_sprintf_void
|
||||
sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
|
||||
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
|
||||
for (len = 0; len < size; len++)
|
||||
if (state->in[len] == 0) break;
|
||||
# else
|
||||
len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
|
||||
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
|
||||
# endif
|
||||
#else
|
||||
# ifdef HAS_snprintf_void
|
||||
snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8,
|
||||
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
|
||||
len = strlen((char *)(state->in));
|
||||
# else
|
||||
len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6,
|
||||
a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18,
|
||||
a19, a20);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* check that printf() results fit in buffer */
|
||||
if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
|
||||
return 0;
|
||||
|
||||
/* update buffer and position, defer compression until needed */
|
||||
strm->avail_in = (unsigned)len;
|
||||
strm->next_in = state->in;
|
||||
state->x.pos += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzflush(gzFile file, int flush)
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're writing and that there's no error */
|
||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
/* check flush parameter */
|
||||
if (flush < 0 || flush > Z_FINISH)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
/* check for seek request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_zero(state, state->skip) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* compress remaining data with requested flush */
|
||||
gz_comp(state, flush);
|
||||
return state->err;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzsetparams(gzFile file, int level, int strategy)
|
||||
{
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (gz_statep)file;
|
||||
strm = &(state->strm);
|
||||
|
||||
/* check that we're writing and that there's no error */
|
||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
/* if no change is requested, then do nothing */
|
||||
if (level == state->level && strategy == state->strategy)
|
||||
return Z_OK;
|
||||
|
||||
/* check for seek request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_zero(state, state->skip) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* change compression parameters for subsequent input */
|
||||
if (state->size) {
|
||||
/* flush previous input with previous parameters before changing */
|
||||
if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
|
||||
return state->err;
|
||||
deflateParams(strm, level, strategy);
|
||||
}
|
||||
state->level = level;
|
||||
state->strategy = strategy;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int gzclose_w(gzFile file)
|
||||
{
|
||||
int ret = Z_OK;
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're writing */
|
||||
if (state->mode != GZ_WRITE)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
/* check for seek request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_zero(state, state->skip) == -1)
|
||||
ret = state->err;
|
||||
}
|
||||
|
||||
/* flush, free memory, and close file */
|
||||
if (gz_comp(state, Z_FINISH) == -1)
|
||||
ret = state->err;
|
||||
if (state->size) {
|
||||
if (!state->direct) {
|
||||
(void)deflateEnd(&(state->strm));
|
||||
free(state->out);
|
||||
}
|
||||
free(state->in);
|
||||
}
|
||||
gz_error(state, Z_OK, NULL);
|
||||
free(state->path);
|
||||
if (close(state->fd) == -1)
|
||||
ret = Z_ERRNO;
|
||||
free(state);
|
||||
return ret;
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2013 Xiph.Org Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "private/bitmath.h"
|
||||
#include "FLAC/assert.h"
|
||||
|
||||
/* An example of what FLAC__bitmath_silog2() computes:
|
||||
*
|
||||
* silog2(-10) = 5
|
||||
* silog2(- 9) = 5
|
||||
* silog2(- 8) = 4
|
||||
* silog2(- 7) = 4
|
||||
* silog2(- 6) = 4
|
||||
* silog2(- 5) = 4
|
||||
* silog2(- 4) = 3
|
||||
* silog2(- 3) = 3
|
||||
* silog2(- 2) = 2
|
||||
* silog2(- 1) = 2
|
||||
* silog2( 0) = 0
|
||||
* silog2( 1) = 2
|
||||
* silog2( 2) = 3
|
||||
* silog2( 3) = 3
|
||||
* silog2( 4) = 4
|
||||
* silog2( 5) = 4
|
||||
* silog2( 6) = 4
|
||||
* silog2( 7) = 4
|
||||
* silog2( 8) = 5
|
||||
* silog2( 9) = 5
|
||||
* silog2( 10) = 5
|
||||
*/
|
||||
unsigned FLAC__bitmath_silog2(int v)
|
||||
{
|
||||
while(1) {
|
||||
if(v == 0) {
|
||||
return 0;
|
||||
}
|
||||
else if(v > 0) {
|
||||
unsigned l = 0;
|
||||
while(v) {
|
||||
l++;
|
||||
v >>= 1;
|
||||
}
|
||||
return l+1;
|
||||
}
|
||||
else if(v == -1) {
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
v++;
|
||||
v = -v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned FLAC__bitmath_silog2_wide(FLAC__int64 v)
|
||||
{
|
||||
while(1) {
|
||||
if(v == 0) {
|
||||
return 0;
|
||||
}
|
||||
else if(v > 0) {
|
||||
unsigned l = 0;
|
||||
while(v) {
|
||||
l++;
|
||||
v >>= 1;
|
||||
}
|
||||
return l+1;
|
||||
}
|
||||
else if(v == -1) {
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
v++;
|
||||
v = -v;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,846 +0,0 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2013 Xiph.Org Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "private/bitwriter.h"
|
||||
#include "private/crc.h"
|
||||
#include "private/macros.h"
|
||||
#include "FLAC/assert.h"
|
||||
#include "share/alloc.h"
|
||||
#include "share/compat.h"
|
||||
#include "share/endswap.h"
|
||||
|
||||
#include <retro_inline.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
|
||||
/* Things should be fastest when this matches the machine word size */
|
||||
/* WATCHOUT: if you change this you must also change the following #defines down to SWAP_BE_WORD_TO_HOST below to match */
|
||||
/* WATCHOUT: there are a few places where the code will not work unless uint32_t is >= 32 bits wide */
|
||||
#define FLAC__BYTES_PER_WORD 4
|
||||
#define FLAC__BITS_PER_WORD 32
|
||||
#define FLAC__WORD_ALL_ONES ((FLAC__uint32)0xffffffff)
|
||||
/* SWAP_BE_WORD_TO_HOST swaps bytes in a uint32_t (which is always big-endian) if necessary to match host byte order */
|
||||
#ifdef MSB_FIRST
|
||||
#define SWAP_BE_WORD_TO_HOST(x) (x)
|
||||
#else
|
||||
#define SWAP_BE_WORD_TO_HOST(x) ENDSWAP_32(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The default capacity here doesn't matter too much. The buffer always grows
|
||||
* to hold whatever is written to it. Usually the encoder will stop adding at
|
||||
* a frame or metadata block, then write that out and clear the buffer for the
|
||||
* next one.
|
||||
*/
|
||||
static const unsigned FLAC__BITWRITER_DEFAULT_CAPACITY = 32768u / sizeof(uint32_t); /* size in words */
|
||||
/* When growing, increment 4K at a time */
|
||||
static const unsigned FLAC__BITWRITER_DEFAULT_INCREMENT = 4096u / sizeof(uint32_t); /* size in words */
|
||||
|
||||
#define FLAC__WORDS_TO_BITS(words) ((words) * FLAC__BITS_PER_WORD)
|
||||
#define FLAC__TOTAL_BITS(bw) (FLAC__WORDS_TO_BITS((bw)->words) + (bw)->bits)
|
||||
|
||||
struct FLAC__BitWriter {
|
||||
uint32_t *buffer;
|
||||
uint32_t accum; /* accumulator; bits are right-justified; when full, accum is appended to buffer */
|
||||
unsigned capacity; /* capacity of buffer in words */
|
||||
unsigned words; /* # of complete words in buffer */
|
||||
unsigned bits; /* # of used bits in accum */
|
||||
};
|
||||
|
||||
/* * WATCHOUT: The current implementation only grows the buffer. */
|
||||
#ifndef __SUNPRO_C
|
||||
static
|
||||
#endif
|
||||
FLAC__bool bitwriter_grow_(FLAC__BitWriter *bw, unsigned bits_to_add)
|
||||
{
|
||||
unsigned new_capacity;
|
||||
uint32_t *new_buffer;
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
|
||||
/* calculate total words needed to store 'bits_to_add' additional bits */
|
||||
new_capacity = bw->words + ((bw->bits + bits_to_add + FLAC__BITS_PER_WORD - 1) / FLAC__BITS_PER_WORD);
|
||||
|
||||
/* it's possible (due to pessimism in the growth estimation that
|
||||
* leads to this call) that we don't actually need to grow
|
||||
*/
|
||||
if(bw->capacity >= new_capacity)
|
||||
return true;
|
||||
|
||||
/* round up capacity increase to the nearest FLAC__BITWRITER_DEFAULT_INCREMENT */
|
||||
if((new_capacity - bw->capacity) % FLAC__BITWRITER_DEFAULT_INCREMENT)
|
||||
new_capacity += FLAC__BITWRITER_DEFAULT_INCREMENT - ((new_capacity - bw->capacity) % FLAC__BITWRITER_DEFAULT_INCREMENT);
|
||||
/* make sure we got everything right */
|
||||
FLAC__ASSERT(0 == (new_capacity - bw->capacity) % FLAC__BITWRITER_DEFAULT_INCREMENT);
|
||||
FLAC__ASSERT(new_capacity > bw->capacity);
|
||||
FLAC__ASSERT(new_capacity >= bw->words + ((bw->bits + bits_to_add + FLAC__BITS_PER_WORD - 1) / FLAC__BITS_PER_WORD));
|
||||
|
||||
new_buffer = (uint32_t*)safe_realloc_mul_2op_(bw->buffer, sizeof(uint32_t), /*times*/new_capacity);
|
||||
if(new_buffer == 0)
|
||||
return false;
|
||||
bw->buffer = new_buffer;
|
||||
bw->capacity = new_capacity;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Class constructor/destructor
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
FLAC__BitWriter *FLAC__bitwriter_new(void)
|
||||
{
|
||||
FLAC__BitWriter *bw = (FLAC__BitWriter*)calloc(1, sizeof(FLAC__BitWriter));
|
||||
/* note that calloc() sets all members to 0 for us */
|
||||
return bw;
|
||||
}
|
||||
|
||||
void FLAC__bitwriter_delete(FLAC__BitWriter *bw)
|
||||
{
|
||||
FLAC__ASSERT(0 != bw);
|
||||
|
||||
FLAC__bitwriter_free(bw);
|
||||
free(bw);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Public class methods
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
FLAC__bool FLAC__bitwriter_init(FLAC__BitWriter *bw)
|
||||
{
|
||||
FLAC__ASSERT(0 != bw);
|
||||
|
||||
bw->words = bw->bits = 0;
|
||||
bw->capacity = FLAC__BITWRITER_DEFAULT_CAPACITY;
|
||||
bw->buffer = (uint32_t*)malloc(sizeof(uint32_t) * bw->capacity);
|
||||
if(bw->buffer == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FLAC__bitwriter_free(FLAC__BitWriter *bw)
|
||||
{
|
||||
FLAC__ASSERT(0 != bw);
|
||||
|
||||
if(0 != bw->buffer)
|
||||
free(bw->buffer);
|
||||
bw->buffer = 0;
|
||||
bw->capacity = 0;
|
||||
bw->words = bw->bits = 0;
|
||||
}
|
||||
|
||||
void FLAC__bitwriter_clear(FLAC__BitWriter *bw)
|
||||
{
|
||||
bw->words = bw->bits = 0;
|
||||
}
|
||||
|
||||
void FLAC__bitwriter_dump(const FLAC__BitWriter *bw, FILE *out)
|
||||
{
|
||||
unsigned i, j;
|
||||
if(bw == 0) {
|
||||
fprintf(out, "bitwriter is NULL\n");
|
||||
}
|
||||
else {
|
||||
fprintf(out, "bitwriter: capacity=%u words=%u bits=%u total_bits=%u\n", bw->capacity, bw->words, bw->bits, FLAC__TOTAL_BITS(bw));
|
||||
|
||||
for(i = 0; i < bw->words; i++) {
|
||||
fprintf(out, "%08X: ", i);
|
||||
for(j = 0; j < FLAC__BITS_PER_WORD; j++)
|
||||
fprintf(out, "%01u", bw->buffer[i] & (1 << (FLAC__BITS_PER_WORD-j-1)) ? 1:0);
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
if(bw->bits > 0) {
|
||||
fprintf(out, "%08X: ", i);
|
||||
for(j = 0; j < bw->bits; j++)
|
||||
fprintf(out, "%01u", bw->accum & (1 << (bw->bits-j-1)) ? 1:0);
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_get_write_crc16(FLAC__BitWriter *bw, FLAC__uint16 *crc)
|
||||
{
|
||||
const FLAC__byte *buffer;
|
||||
size_t bytes;
|
||||
|
||||
FLAC__ASSERT((bw->bits & 7) == 0); /* assert that we're byte-aligned */
|
||||
|
||||
if(!FLAC__bitwriter_get_buffer(bw, &buffer, &bytes))
|
||||
return false;
|
||||
|
||||
*crc = (FLAC__uint16)FLAC__crc16(buffer, bytes);
|
||||
FLAC__bitwriter_release_buffer(bw);
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_get_write_crc8(FLAC__BitWriter *bw, FLAC__byte *crc)
|
||||
{
|
||||
const FLAC__byte *buffer;
|
||||
size_t bytes;
|
||||
|
||||
FLAC__ASSERT((bw->bits & 7) == 0); /* assert that we're byte-aligned */
|
||||
|
||||
if(!FLAC__bitwriter_get_buffer(bw, &buffer, &bytes))
|
||||
return false;
|
||||
|
||||
*crc = FLAC__crc8(buffer, bytes);
|
||||
FLAC__bitwriter_release_buffer(bw);
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_is_byte_aligned(const FLAC__BitWriter *bw)
|
||||
{
|
||||
return ((bw->bits & 7) == 0);
|
||||
}
|
||||
|
||||
unsigned FLAC__bitwriter_get_input_bits_unconsumed(const FLAC__BitWriter *bw)
|
||||
{
|
||||
return FLAC__TOTAL_BITS(bw);
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_get_buffer(FLAC__BitWriter *bw, const FLAC__byte **buffer, size_t *bytes)
|
||||
{
|
||||
FLAC__ASSERT((bw->bits & 7) == 0);
|
||||
/* double protection */
|
||||
if(bw->bits & 7)
|
||||
return false;
|
||||
/* if we have bits in the accumulator we have to flush those to the buffer first */
|
||||
if(bw->bits) {
|
||||
FLAC__ASSERT(bw->words <= bw->capacity);
|
||||
if(bw->words == bw->capacity && !bitwriter_grow_(bw, FLAC__BITS_PER_WORD))
|
||||
return false;
|
||||
/* append bits as complete word to buffer, but don't change bw->accum or bw->bits */
|
||||
bw->buffer[bw->words] = SWAP_BE_WORD_TO_HOST(bw->accum << (FLAC__BITS_PER_WORD-bw->bits));
|
||||
}
|
||||
/* now we can just return what we have */
|
||||
*buffer = (FLAC__byte*)bw->buffer;
|
||||
*bytes = (FLAC__BYTES_PER_WORD * bw->words) + (bw->bits >> 3);
|
||||
return true;
|
||||
}
|
||||
|
||||
void FLAC__bitwriter_release_buffer(FLAC__BitWriter *bw)
|
||||
{
|
||||
/* nothing to do. in the future, strict checking of a 'writer-is-in-
|
||||
* get-mode' flag could be added everywhere and then cleared here
|
||||
*/
|
||||
(void)bw;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_write_zeroes(FLAC__BitWriter *bw, unsigned bits)
|
||||
{
|
||||
unsigned n;
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
|
||||
if(bits == 0)
|
||||
return true;
|
||||
/* slightly pessimistic size check but faster than "<= bw->words + (bw->bits+bits+FLAC__BITS_PER_WORD-1)/FLAC__BITS_PER_WORD" */
|
||||
if(bw->capacity <= bw->words + bits && !bitwriter_grow_(bw, bits))
|
||||
return false;
|
||||
/* first part gets to word alignment */
|
||||
if(bw->bits) {
|
||||
n = MIN(FLAC__BITS_PER_WORD - bw->bits, bits);
|
||||
bw->accum <<= n;
|
||||
bits -= n;
|
||||
bw->bits += n;
|
||||
if(bw->bits == FLAC__BITS_PER_WORD) {
|
||||
bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum);
|
||||
bw->bits = 0;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
/* do whole words */
|
||||
while(bits >= FLAC__BITS_PER_WORD) {
|
||||
bw->buffer[bw->words++] = 0;
|
||||
bits -= FLAC__BITS_PER_WORD;
|
||||
}
|
||||
/* do any leftovers */
|
||||
if(bits > 0) {
|
||||
bw->accum = 0;
|
||||
bw->bits = bits;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_write_raw_uint32(FLAC__BitWriter *bw, FLAC__uint32 val, unsigned bits)
|
||||
{
|
||||
register unsigned left;
|
||||
|
||||
/* WATCHOUT: code does not work with <32bit words; we can make things much faster with this assertion */
|
||||
FLAC__ASSERT(FLAC__BITS_PER_WORD >= 32);
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
|
||||
FLAC__ASSERT(bits <= 32);
|
||||
if(bits == 0)
|
||||
return true;
|
||||
|
||||
/* slightly pessimistic size check but faster than "<= bw->words + (bw->bits+bits+FLAC__BITS_PER_WORD-1)/FLAC__BITS_PER_WORD" */
|
||||
if(bw->capacity <= bw->words + bits && !bitwriter_grow_(bw, bits))
|
||||
return false;
|
||||
|
||||
left = FLAC__BITS_PER_WORD - bw->bits;
|
||||
if(bits < left) {
|
||||
bw->accum <<= bits;
|
||||
bw->accum |= val;
|
||||
bw->bits += bits;
|
||||
}
|
||||
else if(bw->bits) { /* WATCHOUT: if bw->bits == 0, left==FLAC__BITS_PER_WORD and bw->accum<<=left is a NOP instead of setting to 0 */
|
||||
bw->accum <<= left;
|
||||
bw->accum |= val >> (bw->bits = bits - left);
|
||||
bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum);
|
||||
bw->accum = val;
|
||||
}
|
||||
else {
|
||||
bw->accum = val;
|
||||
bw->bits = 0;
|
||||
bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(val);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_write_raw_int32(FLAC__BitWriter *bw, FLAC__int32 val, unsigned bits)
|
||||
{
|
||||
/* zero-out unused bits */
|
||||
if(bits < 32)
|
||||
val &= (~(0xffffffff << bits));
|
||||
|
||||
return FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)val, bits);
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_write_raw_uint64(FLAC__BitWriter *bw, FLAC__uint64 val, unsigned bits)
|
||||
{
|
||||
/* this could be a little faster but it's not used for much */
|
||||
if(bits > 32) {
|
||||
return
|
||||
FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)(val>>32), bits-32) &&
|
||||
FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)val, 32);
|
||||
}
|
||||
else
|
||||
return FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)val, bits);
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_write_raw_uint32_little_endian(FLAC__BitWriter *bw, FLAC__uint32 val)
|
||||
{
|
||||
/* this doesn't need to be that fast as currently it is only used for vorbis comments */
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, val & 0xff, 8))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, (val>>8) & 0xff, 8))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, (val>>16) & 0xff, 8))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, val>>24, 8))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_write_byte_block(FLAC__BitWriter *bw, const FLAC__byte vals[], unsigned nvals)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
/* this could be faster but currently we don't need it to be since it's only used for writing metadata */
|
||||
for(i = 0; i < nvals; i++) {
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)(vals[i]), 8))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_write_unary_unsigned(FLAC__BitWriter *bw, unsigned val)
|
||||
{
|
||||
if(val < 32)
|
||||
return FLAC__bitwriter_write_raw_uint32(bw, 1, ++val);
|
||||
else
|
||||
return
|
||||
FLAC__bitwriter_write_zeroes(bw, val) &&
|
||||
FLAC__bitwriter_write_raw_uint32(bw, 1, 1);
|
||||
}
|
||||
|
||||
unsigned FLAC__bitwriter_rice_bits(FLAC__int32 val, unsigned parameter)
|
||||
{
|
||||
FLAC__uint32 uval;
|
||||
|
||||
FLAC__ASSERT(parameter < sizeof(unsigned)*8);
|
||||
|
||||
/* fold signed to unsigned; actual formula is: negative(v)? -2v-1 : 2v */
|
||||
uval = (val<<1) ^ (val>>31);
|
||||
|
||||
return 1 + parameter + (uval >> parameter);
|
||||
}
|
||||
|
||||
#if 0 /* UNUSED */
|
||||
unsigned FLAC__bitwriter_golomb_bits_signed(int val, unsigned parameter)
|
||||
{
|
||||
unsigned bits, msbs, uval;
|
||||
unsigned k;
|
||||
|
||||
FLAC__ASSERT(parameter > 0);
|
||||
|
||||
/* fold signed to unsigned */
|
||||
if(val < 0)
|
||||
uval = (unsigned)(((-(++val)) << 1) + 1);
|
||||
else
|
||||
uval = (unsigned)(val << 1);
|
||||
|
||||
k = FLAC__bitmath_ilog2(parameter);
|
||||
if(parameter == 1u<<k) {
|
||||
FLAC__ASSERT(k <= 30);
|
||||
|
||||
msbs = uval >> 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__bitwriter_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) {
|
||||
FLAC__ASSERT(k <= 30);
|
||||
|
||||
msbs = uval >> 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 */
|
||||
|
||||
FLAC__bool FLAC__bitwriter_write_rice_signed(FLAC__BitWriter *bw, FLAC__int32 val, unsigned parameter)
|
||||
{
|
||||
unsigned total_bits, interesting_bits, msbs;
|
||||
FLAC__uint32 uval, pattern;
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
FLAC__ASSERT(parameter < 8*sizeof(uval));
|
||||
|
||||
/* fold signed to unsigned; actual formula is: negative(v)? -2v-1 : 2v */
|
||||
uval = (val<<1) ^ (val>>31);
|
||||
|
||||
msbs = uval >> parameter;
|
||||
interesting_bits = 1 + parameter;
|
||||
total_bits = interesting_bits + msbs;
|
||||
pattern = 1 << parameter; /* the unary end bit */
|
||||
pattern |= (uval & ((1<<parameter)-1)); /* the binary LSBs */
|
||||
|
||||
if(total_bits <= 32)
|
||||
return FLAC__bitwriter_write_raw_uint32(bw, pattern, total_bits);
|
||||
else
|
||||
return
|
||||
FLAC__bitwriter_write_zeroes(bw, msbs) && /* write the unary MSBs */
|
||||
FLAC__bitwriter_write_raw_uint32(bw, pattern, interesting_bits); /* write the unary end bit and binary LSBs */
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_write_rice_signed_block(FLAC__BitWriter *bw, const FLAC__int32 *vals, unsigned nvals, unsigned parameter)
|
||||
{
|
||||
const FLAC__uint32 mask1 = FLAC__WORD_ALL_ONES << parameter; /* we val|=mask1 to set the stop bit above it... */
|
||||
const FLAC__uint32 mask2 = FLAC__WORD_ALL_ONES >> (31-parameter); /* ...then mask off the bits above the stop bit with val&=mask2*/
|
||||
FLAC__uint32 uval;
|
||||
unsigned left;
|
||||
const unsigned lsbits = 1 + parameter;
|
||||
unsigned msbits;
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
FLAC__ASSERT(parameter < 8*sizeof(uint32_t)-1);
|
||||
/* WATCHOUT: code does not work with <32bit words; we can make things much faster with this assertion */
|
||||
FLAC__ASSERT(FLAC__BITS_PER_WORD >= 32);
|
||||
|
||||
while(nvals) {
|
||||
/* fold signed to unsigned; actual formula is: negative(v)? -2v-1 : 2v */
|
||||
uval = (*vals<<1) ^ (*vals>>31);
|
||||
|
||||
msbits = uval >> parameter;
|
||||
|
||||
if(bw->bits && bw->bits + msbits + lsbits < FLAC__BITS_PER_WORD) { /* i.e. if the whole thing fits in the current uint32_t */
|
||||
/* ^^^ if bw->bits is 0 then we may have filled the buffer and have no free uint32_t to work in */
|
||||
bw->bits = bw->bits + msbits + lsbits;
|
||||
uval |= mask1; /* set stop bit */
|
||||
uval &= mask2; /* mask off unused top bits */
|
||||
bw->accum <<= msbits + lsbits;
|
||||
bw->accum |= uval;
|
||||
}
|
||||
else {
|
||||
/* slightly pessimistic size check but faster than "<= bw->words + (bw->bits+msbits+lsbits+FLAC__BITS_PER_WORD-1)/FLAC__BITS_PER_WORD" */
|
||||
/* OPT: pessimism may cause flurry of false calls to grow_ which eat up all savings before it */
|
||||
if(bw->capacity <= bw->words + bw->bits + msbits + 1/*lsbits always fit in 1 uint32_t*/ && !bitwriter_grow_(bw, msbits+lsbits))
|
||||
return false;
|
||||
|
||||
if(msbits) {
|
||||
/* first part gets to word alignment */
|
||||
if(bw->bits) {
|
||||
left = FLAC__BITS_PER_WORD - bw->bits;
|
||||
if(msbits < left) {
|
||||
bw->accum <<= msbits;
|
||||
bw->bits += msbits;
|
||||
goto break1;
|
||||
}
|
||||
else {
|
||||
bw->accum <<= left;
|
||||
msbits -= left;
|
||||
bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum);
|
||||
bw->bits = 0;
|
||||
}
|
||||
}
|
||||
/* do whole words */
|
||||
while(msbits >= FLAC__BITS_PER_WORD) {
|
||||
bw->buffer[bw->words++] = 0;
|
||||
msbits -= FLAC__BITS_PER_WORD;
|
||||
}
|
||||
/* do any leftovers */
|
||||
if(msbits > 0) {
|
||||
bw->accum = 0;
|
||||
bw->bits = msbits;
|
||||
}
|
||||
}
|
||||
break1:
|
||||
uval |= mask1; /* set stop bit */
|
||||
uval &= mask2; /* mask off unused top bits */
|
||||
|
||||
left = FLAC__BITS_PER_WORD - bw->bits;
|
||||
if(lsbits < left) {
|
||||
bw->accum <<= lsbits;
|
||||
bw->accum |= uval;
|
||||
bw->bits += lsbits;
|
||||
}
|
||||
else {
|
||||
/* if bw->bits == 0, left==FLAC__BITS_PER_WORD which will always
|
||||
* be > lsbits (because of previous assertions) so it would have
|
||||
* triggered the (lsbits<left) case above.
|
||||
*/
|
||||
FLAC__ASSERT(bw->bits);
|
||||
FLAC__ASSERT(left < FLAC__BITS_PER_WORD);
|
||||
bw->accum <<= left;
|
||||
bw->accum |= uval >> (bw->bits = lsbits - left);
|
||||
bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum);
|
||||
bw->accum = uval;
|
||||
}
|
||||
}
|
||||
vals++;
|
||||
nvals--;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0 /* UNUSED */
|
||||
FLAC__bool FLAC__bitwriter_write_golomb_signed(FLAC__BitWriter *bw, int val, unsigned parameter)
|
||||
{
|
||||
unsigned total_bits, msbs, uval;
|
||||
unsigned k;
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
FLAC__ASSERT(parameter > 0);
|
||||
|
||||
/* fold signed to unsigned */
|
||||
if(val < 0)
|
||||
uval = (unsigned)(((-(++val)) << 1) + 1);
|
||||
else
|
||||
uval = (unsigned)(val << 1);
|
||||
|
||||
k = FLAC__bitmath_ilog2(parameter);
|
||||
if(parameter == 1u<<k) {
|
||||
unsigned pattern;
|
||||
|
||||
FLAC__ASSERT(k <= 30);
|
||||
|
||||
msbs = uval >> k;
|
||||
total_bits = 1 + k + msbs;
|
||||
pattern = 1 << k; /* the unary end bit */
|
||||
pattern |= (uval & ((1u<<k)-1)); /* the binary LSBs */
|
||||
|
||||
if(total_bits <= 32) {
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, pattern, total_bits))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
/* write the unary MSBs */
|
||||
if(!FLAC__bitwriter_write_zeroes(bw, msbs))
|
||||
return false;
|
||||
/* write the unary end bit and binary LSBs */
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, pattern, k+1))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
unsigned q, r, d;
|
||||
|
||||
d = (1 << (k+1)) - parameter;
|
||||
q = uval / parameter;
|
||||
r = uval - (q * parameter);
|
||||
/* write the unary MSBs */
|
||||
if(!FLAC__bitwriter_write_zeroes(bw, q))
|
||||
return false;
|
||||
/* write the unary end bit */
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, 1, 1))
|
||||
return false;
|
||||
/* write the binary LSBs */
|
||||
if(r >= d) {
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, r+d, k+1))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, r, k))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_write_golomb_unsigned(FLAC__BitWriter *bw, unsigned uval, unsigned parameter)
|
||||
{
|
||||
unsigned total_bits, msbs;
|
||||
unsigned k;
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
FLAC__ASSERT(parameter > 0);
|
||||
|
||||
k = FLAC__bitmath_ilog2(parameter);
|
||||
if(parameter == 1u<<k) {
|
||||
unsigned pattern;
|
||||
|
||||
FLAC__ASSERT(k <= 30);
|
||||
|
||||
msbs = uval >> k;
|
||||
total_bits = 1 + k + msbs;
|
||||
pattern = 1 << k; /* the unary end bit */
|
||||
pattern |= (uval & ((1u<<k)-1)); /* the binary LSBs */
|
||||
|
||||
if(total_bits <= 32) {
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, pattern, total_bits))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
/* write the unary MSBs */
|
||||
if(!FLAC__bitwriter_write_zeroes(bw, msbs))
|
||||
return false;
|
||||
/* write the unary end bit and binary LSBs */
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, pattern, k+1))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
unsigned q, r, d;
|
||||
|
||||
d = (1 << (k+1)) - parameter;
|
||||
q = uval / parameter;
|
||||
r = uval - (q * parameter);
|
||||
/* write the unary MSBs */
|
||||
if(!FLAC__bitwriter_write_zeroes(bw, q))
|
||||
return false;
|
||||
/* write the unary end bit */
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, 1, 1))
|
||||
return false;
|
||||
/* write the binary LSBs */
|
||||
if(r >= d) {
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, r+d, k+1))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, r, k))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif /* UNUSED */
|
||||
|
||||
FLAC__bool FLAC__bitwriter_write_utf8_uint32(FLAC__BitWriter *bw, FLAC__uint32 val)
|
||||
{
|
||||
FLAC__bool ok = 1;
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
|
||||
FLAC__ASSERT(!(val & 0x80000000)); /* this version only handles 31 bits */
|
||||
|
||||
if(val < 0x80) {
|
||||
return FLAC__bitwriter_write_raw_uint32(bw, val, 8);
|
||||
}
|
||||
else if(val < 0x800) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xC0 | (val>>6), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x10000) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xE0 | (val>>12), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x200000) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xF0 | (val>>18), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x4000000) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xF8 | (val>>24), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>18)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (val&0x3F), 8);
|
||||
}
|
||||
else {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xFC | (val>>30), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>24)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>18)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (val&0x3F), 8);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_write_utf8_uint64(FLAC__BitWriter *bw, FLAC__uint64 val)
|
||||
{
|
||||
FLAC__bool ok = 1;
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
|
||||
FLAC__ASSERT(!(val & FLAC__U64L(0xFFFFFFF000000000))); /* this version only handles 36 bits */
|
||||
|
||||
if(val < 0x80) {
|
||||
return FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)val, 8);
|
||||
}
|
||||
else if(val < 0x800) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xC0 | (FLAC__uint32)(val>>6), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x10000) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xE0 | (FLAC__uint32)(val>>12), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x200000) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xF0 | (FLAC__uint32)(val>>18), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x4000000) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xF8 | (FLAC__uint32)(val>>24), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x80000000) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xFC | (FLAC__uint32)(val>>30), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>24)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
|
||||
}
|
||||
else {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xFE, 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>30)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>24)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_zero_pad_to_byte_boundary(FLAC__BitWriter *bw)
|
||||
{
|
||||
/* 0-pad to byte boundary */
|
||||
if(bw->bits & 7u)
|
||||
return FLAC__bitwriter_write_zeroes(bw, 8 - (bw->bits & 7u));
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
/* These functions are declared inline in this file but are also callable as
|
||||
* externs from elsewhere.
|
||||
* According to the C99 spec, section 6.7.4, simply providing a function
|
||||
* prototype in a header file without 'inline' and making the function inline
|
||||
* in this file should be sufficient.
|
||||
* Unfortunately, the Microsoft VS compiler doesn't pick them up externally. To
|
||||
* fix that we add extern declarations here.
|
||||
*/
|
||||
extern FLAC__bool FLAC__bitwriter_write_zeroes(FLAC__BitWriter *bw, unsigned bits);
|
||||
extern FLAC__bool FLAC__bitwriter_write_raw_int32(FLAC__BitWriter *bw, FLAC__int32 val, unsigned bits);
|
||||
extern FLAC__bool FLAC__bitwriter_write_raw_uint64(FLAC__BitWriter *bw, FLAC__uint64 val, unsigned bits);
|
||||
extern FLAC__bool FLAC__bitwriter_write_raw_uint32_little_endian(FLAC__BitWriter *bw, FLAC__uint32 val);
|
||||
extern FLAC__bool FLAC__bitwriter_write_byte_block(FLAC__BitWriter *bw, const FLAC__byte vals[], unsigned nvals);
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,210 +0,0 @@
|
||||
/* libFLAC - Free Lossless Audio Codec
|
||||
* Copyright (C) 2004-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2013 Xiph.Org Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h> /* for malloc() */
|
||||
#include <string.h> /* for memcmp(), memcpy() */
|
||||
#include "FLAC/assert.h"
|
||||
#include "share/alloc.h"
|
||||
#include "private/ogg_helper.h"
|
||||
#include "protected/stream_encoder.h"
|
||||
|
||||
|
||||
static FLAC__bool full_read_(FLAC__StreamEncoder *encoder, FLAC__byte *buffer, size_t bytes, FLAC__StreamEncoderReadCallback read_callback, void *client_data)
|
||||
{
|
||||
while(bytes > 0) {
|
||||
size_t bytes_read = bytes;
|
||||
switch(read_callback(encoder, buffer, &bytes_read, client_data)) {
|
||||
case FLAC__STREAM_ENCODER_READ_STATUS_CONTINUE:
|
||||
bytes -= bytes_read;
|
||||
buffer += bytes_read;
|
||||
break;
|
||||
case FLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM:
|
||||
if(bytes_read == 0) {
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR;
|
||||
return false;
|
||||
}
|
||||
bytes -= bytes_read;
|
||||
buffer += bytes_read;
|
||||
break;
|
||||
case FLAC__STREAM_ENCODER_READ_STATUS_ABORT:
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
|
||||
return false;
|
||||
case FLAC__STREAM_ENCODER_READ_STATUS_UNSUPPORTED:
|
||||
return false;
|
||||
default:
|
||||
/* double protection: */
|
||||
FLAC__ASSERT(0);
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void simple_ogg_page__init(ogg_page *page)
|
||||
{
|
||||
page->header = 0;
|
||||
page->header_len = 0;
|
||||
page->body = 0;
|
||||
page->body_len = 0;
|
||||
}
|
||||
|
||||
void simple_ogg_page__clear(ogg_page *page)
|
||||
{
|
||||
if(page->header)
|
||||
free(page->header);
|
||||
if(page->body)
|
||||
free(page->body);
|
||||
simple_ogg_page__init(page);
|
||||
}
|
||||
|
||||
FLAC__bool simple_ogg_page__get_at(FLAC__StreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderReadCallback read_callback, void *client_data)
|
||||
{
|
||||
static const unsigned OGG_HEADER_FIXED_PORTION_LEN = 27;
|
||||
static const unsigned OGG_MAX_HEADER_LEN = 27/*OGG_HEADER_FIXED_PORTION_LEN*/ + 255;
|
||||
FLAC__byte crc[4];
|
||||
FLAC__StreamEncoderSeekStatus seek_status;
|
||||
|
||||
FLAC__ASSERT(page->header == 0);
|
||||
FLAC__ASSERT(page->header_len == 0);
|
||||
FLAC__ASSERT(page->body == 0);
|
||||
FLAC__ASSERT(page->body_len == 0);
|
||||
|
||||
/* move the stream pointer to the supposed beginning of the page */
|
||||
if(0 == seek_callback)
|
||||
return false;
|
||||
if((seek_status = seek_callback((FLAC__StreamEncoder*)encoder, position, client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) {
|
||||
if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR)
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* allocate space for the page header */
|
||||
if(0 == (page->header = safe_malloc_(OGG_MAX_HEADER_LEN))) {
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* read in the fixed part of the page header (up to but not including
|
||||
* the segment table */
|
||||
if(!full_read_(encoder, page->header, OGG_HEADER_FIXED_PORTION_LEN, read_callback, client_data))
|
||||
return false;
|
||||
|
||||
page->header_len = OGG_HEADER_FIXED_PORTION_LEN + page->header[26];
|
||||
|
||||
/* check to see if it's a correct, "simple" page (one packet only) */
|
||||
if(
|
||||
memcmp(page->header, "OggS", 4) || /* doesn't start with OggS */
|
||||
(page->header[5] & 0x01) || /* continued packet */
|
||||
memcmp(page->header+6, "\0\0\0\0\0\0\0\0", 8) || /* granulepos is non-zero */
|
||||
page->header[26] == 0 /* packet is 0-size */
|
||||
) {
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* read in the segment table */
|
||||
if(!full_read_(encoder, page->header + OGG_HEADER_FIXED_PORTION_LEN, page->header[26], read_callback, client_data))
|
||||
return false;
|
||||
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
/* check to see that it specifies a single packet */
|
||||
for(i = 0; i < (unsigned)page->header[26] - 1; i++) {
|
||||
if(page->header[i + OGG_HEADER_FIXED_PORTION_LEN] != 255) {
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
page->body_len = 255 * i + page->header[i + OGG_HEADER_FIXED_PORTION_LEN];
|
||||
}
|
||||
|
||||
/* allocate space for the page body */
|
||||
if(0 == (page->body = safe_malloc_(page->body_len))) {
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* read in the page body */
|
||||
if(!full_read_(encoder, page->body, page->body_len, read_callback, client_data))
|
||||
return false;
|
||||
|
||||
/* check the CRC */
|
||||
memcpy(crc, page->header+22, 4);
|
||||
ogg_page_checksum_set(page);
|
||||
if(memcmp(crc, page->header+22, 4)) {
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool simple_ogg_page__set_at(FLAC__StreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, FLAC__StreamEncoderSeekCallback seek_callback, FLAC__StreamEncoderWriteCallback write_callback, void *client_data)
|
||||
{
|
||||
FLAC__StreamEncoderSeekStatus seek_status;
|
||||
|
||||
FLAC__ASSERT(page->header != 0);
|
||||
FLAC__ASSERT(page->header_len != 0);
|
||||
FLAC__ASSERT(page->body != 0);
|
||||
FLAC__ASSERT(page->body_len != 0);
|
||||
|
||||
/* move the stream pointer to the supposed beginning of the page */
|
||||
if(0 == seek_callback)
|
||||
return false;
|
||||
if((seek_status = seek_callback((FLAC__StreamEncoder*)encoder, position, client_data)) != FLAC__STREAM_ENCODER_SEEK_STATUS_OK) {
|
||||
if(seek_status == FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR)
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
ogg_page_checksum_set(page);
|
||||
|
||||
/* re-write the page */
|
||||
if(write_callback((FLAC__StreamEncoder*)encoder, page->header, page->header_len, 0, 0, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
|
||||
return false;
|
||||
}
|
||||
if(write_callback((FLAC__StreamEncoder*)encoder, page->body, page->body_len, 0, 0, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
|
||||
encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,549 +0,0 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2013 Xiph.Org Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h> /* for strlen() */
|
||||
#include "private/stream_encoder_framing.h"
|
||||
#include "private/crc.h"
|
||||
#include "FLAC/assert.h"
|
||||
|
||||
static FLAC__bool add_entropy_coding_method_(FLAC__BitWriter *bw, const FLAC__EntropyCodingMethod *method);
|
||||
static FLAC__bool add_residual_partitioned_rice_(FLAC__BitWriter *bw, const FLAC__int32 residual[], const unsigned residual_samples, const unsigned predictor_order, const unsigned rice_parameters[], const unsigned raw_bits[], const unsigned partition_order, const FLAC__bool is_extended);
|
||||
|
||||
FLAC__bool FLAC__add_metadata_block(const FLAC__StreamMetadata *metadata, FLAC__BitWriter *bw)
|
||||
{
|
||||
unsigned i, j;
|
||||
const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->is_last, FLAC__STREAM_METADATA_IS_LAST_LEN))
|
||||
return false;
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->type, FLAC__STREAM_METADATA_TYPE_LEN))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* First, for VORBIS_COMMENTs, adjust the length to reflect our vendor string
|
||||
*/
|
||||
i = metadata->length;
|
||||
if(metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
|
||||
FLAC__ASSERT(metadata->data.vorbis_comment.vendor_string.length == 0 || 0 != metadata->data.vorbis_comment.vendor_string.entry);
|
||||
i -= metadata->data.vorbis_comment.vendor_string.length;
|
||||
i += vendor_string_length;
|
||||
}
|
||||
FLAC__ASSERT(i < (1u << FLAC__STREAM_METADATA_LENGTH_LEN));
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, i, FLAC__STREAM_METADATA_LENGTH_LEN))
|
||||
return false;
|
||||
|
||||
switch(metadata->type) {
|
||||
case FLAC__METADATA_TYPE_STREAMINFO:
|
||||
FLAC__ASSERT(metadata->data.stream_info.min_blocksize < (1u << FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN));
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.min_blocksize, FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN))
|
||||
return false;
|
||||
FLAC__ASSERT(metadata->data.stream_info.max_blocksize < (1u << FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN));
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.max_blocksize, FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN))
|
||||
return false;
|
||||
FLAC__ASSERT(metadata->data.stream_info.min_framesize < (1u << FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN));
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.min_framesize, FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN))
|
||||
return false;
|
||||
FLAC__ASSERT(metadata->data.stream_info.max_framesize < (1u << FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN));
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.max_framesize, FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN))
|
||||
return false;
|
||||
FLAC__ASSERT(FLAC__format_sample_rate_is_valid(metadata->data.stream_info.sample_rate));
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.sample_rate, FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN))
|
||||
return false;
|
||||
FLAC__ASSERT(metadata->data.stream_info.channels > 0);
|
||||
FLAC__ASSERT(metadata->data.stream_info.channels <= (1u << FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN));
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.channels-1, FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN))
|
||||
return false;
|
||||
FLAC__ASSERT(metadata->data.stream_info.bits_per_sample > 0);
|
||||
FLAC__ASSERT(metadata->data.stream_info.bits_per_sample <= (1u << FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN));
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.bits_per_sample-1, FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint64(bw, metadata->data.stream_info.total_samples, FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.stream_info.md5sum, 16))
|
||||
return false;
|
||||
break;
|
||||
case FLAC__METADATA_TYPE_PADDING:
|
||||
if(!FLAC__bitwriter_write_zeroes(bw, metadata->length * 8))
|
||||
return false;
|
||||
break;
|
||||
case FLAC__METADATA_TYPE_APPLICATION:
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.application.id, FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.application.data, metadata->length - (FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8)))
|
||||
return false;
|
||||
break;
|
||||
case FLAC__METADATA_TYPE_SEEKTABLE:
|
||||
for(i = 0; i < metadata->data.seek_table.num_points; i++) {
|
||||
if(!FLAC__bitwriter_write_raw_uint64(bw, metadata->data.seek_table.points[i].sample_number, FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint64(bw, metadata->data.seek_table.points[i].stream_offset, FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.seek_table.points[i].frame_samples, FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case FLAC__METADATA_TYPE_VORBIS_COMMENT:
|
||||
if(!FLAC__bitwriter_write_raw_uint32_little_endian(bw, vendor_string_length))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, (const FLAC__byte*)FLAC__VENDOR_STRING, vendor_string_length))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32_little_endian(bw, metadata->data.vorbis_comment.num_comments))
|
||||
return false;
|
||||
for(i = 0; i < metadata->data.vorbis_comment.num_comments; i++) {
|
||||
if(!FLAC__bitwriter_write_raw_uint32_little_endian(bw, metadata->data.vorbis_comment.comments[i].length))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.vorbis_comment.comments[i].entry, metadata->data.vorbis_comment.comments[i].length))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case FLAC__METADATA_TYPE_CUESHEET:
|
||||
FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN % 8 == 0);
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, (const FLAC__byte*)metadata->data.cue_sheet.media_catalog_number, FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN/8))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint64(bw, metadata->data.cue_sheet.lead_in, FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.cue_sheet.is_cd? 1 : 0, FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_zeroes(bw, FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.cue_sheet.num_tracks, FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN))
|
||||
return false;
|
||||
for(i = 0; i < metadata->data.cue_sheet.num_tracks; i++) {
|
||||
const FLAC__StreamMetadata_CueSheet_Track *track = metadata->data.cue_sheet.tracks + i;
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint64(bw, track->offset, FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, track->number, FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN))
|
||||
return false;
|
||||
FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN % 8 == 0);
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, (const FLAC__byte*)track->isrc, FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN/8))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, track->type, FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, track->pre_emphasis, FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_zeroes(bw, FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, track->num_indices, FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN))
|
||||
return false;
|
||||
for(j = 0; j < track->num_indices; j++) {
|
||||
const FLAC__StreamMetadata_CueSheet_Index *indx = track->indices + j;
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint64(bw, indx->offset, FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, indx->number, FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_zeroes(bw, FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FLAC__METADATA_TYPE_PICTURE:
|
||||
{
|
||||
size_t len;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.type, FLAC__STREAM_METADATA_PICTURE_TYPE_LEN))
|
||||
return false;
|
||||
len = strlen(metadata->data.picture.mime_type);
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, len, FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, (const FLAC__byte*)metadata->data.picture.mime_type, len))
|
||||
return false;
|
||||
len = strlen((const char *)metadata->data.picture.description);
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, len, FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.picture.description, len))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.width, FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.height, FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.depth, FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.colors, FLAC__STREAM_METADATA_PICTURE_COLORS_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.data_length, FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.picture.data, metadata->data.picture.data_length))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.unknown.data, metadata->length))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
FLAC__ASSERT(FLAC__bitwriter_is_byte_aligned(bw));
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__frame_add_header(const FLAC__FrameHeader *header, FLAC__BitWriter *bw)
|
||||
{
|
||||
unsigned u, blocksize_hint, sample_rate_hint;
|
||||
FLAC__byte crc;
|
||||
|
||||
FLAC__ASSERT(FLAC__bitwriter_is_byte_aligned(bw));
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, FLAC__FRAME_HEADER_SYNC, FLAC__FRAME_HEADER_SYNC_LEN))
|
||||
return false;
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, 0, FLAC__FRAME_HEADER_RESERVED_LEN))
|
||||
return false;
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, (header->number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER)? 0 : 1, FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN))
|
||||
return false;
|
||||
|
||||
FLAC__ASSERT(header->blocksize > 0 && header->blocksize <= FLAC__MAX_BLOCK_SIZE);
|
||||
/* when this assertion holds true, any legal blocksize can be expressed in the frame header */
|
||||
FLAC__ASSERT(FLAC__MAX_BLOCK_SIZE <= 65535u);
|
||||
blocksize_hint = 0;
|
||||
switch(header->blocksize) {
|
||||
case 192: u = 1; break;
|
||||
case 576: u = 2; break;
|
||||
case 1152: u = 3; break;
|
||||
case 2304: u = 4; break;
|
||||
case 4608: u = 5; break;
|
||||
case 256: u = 8; break;
|
||||
case 512: u = 9; break;
|
||||
case 1024: u = 10; break;
|
||||
case 2048: u = 11; break;
|
||||
case 4096: u = 12; break;
|
||||
case 8192: u = 13; break;
|
||||
case 16384: u = 14; break;
|
||||
case 32768: u = 15; break;
|
||||
default:
|
||||
if(header->blocksize <= 0x100)
|
||||
blocksize_hint = u = 6;
|
||||
else
|
||||
blocksize_hint = u = 7;
|
||||
break;
|
||||
}
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, u, FLAC__FRAME_HEADER_BLOCK_SIZE_LEN))
|
||||
return false;
|
||||
|
||||
FLAC__ASSERT(FLAC__format_sample_rate_is_valid(header->sample_rate));
|
||||
sample_rate_hint = 0;
|
||||
switch(header->sample_rate) {
|
||||
case 88200: u = 1; break;
|
||||
case 176400: u = 2; break;
|
||||
case 192000: u = 3; break;
|
||||
case 8000: u = 4; break;
|
||||
case 16000: u = 5; break;
|
||||
case 22050: u = 6; break;
|
||||
case 24000: u = 7; break;
|
||||
case 32000: u = 8; break;
|
||||
case 44100: u = 9; break;
|
||||
case 48000: u = 10; break;
|
||||
case 96000: u = 11; break;
|
||||
default:
|
||||
if(header->sample_rate <= 255000 && header->sample_rate % 1000 == 0)
|
||||
sample_rate_hint = u = 12;
|
||||
else if(header->sample_rate % 10 == 0)
|
||||
sample_rate_hint = u = 14;
|
||||
else if(header->sample_rate <= 0xffff)
|
||||
sample_rate_hint = u = 13;
|
||||
else
|
||||
u = 0;
|
||||
break;
|
||||
}
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, u, FLAC__FRAME_HEADER_SAMPLE_RATE_LEN))
|
||||
return false;
|
||||
|
||||
FLAC__ASSERT(header->channels > 0 && header->channels <= (1u << FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN) && header->channels <= FLAC__MAX_CHANNELS);
|
||||
switch(header->channel_assignment) {
|
||||
case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
|
||||
u = header->channels - 1;
|
||||
break;
|
||||
case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
|
||||
FLAC__ASSERT(header->channels == 2);
|
||||
u = 8;
|
||||
break;
|
||||
case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
|
||||
FLAC__ASSERT(header->channels == 2);
|
||||
u = 9;
|
||||
break;
|
||||
case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
|
||||
FLAC__ASSERT(header->channels == 2);
|
||||
u = 10;
|
||||
break;
|
||||
default:
|
||||
FLAC__ASSERT(0);
|
||||
}
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, u, FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN))
|
||||
return false;
|
||||
|
||||
FLAC__ASSERT(header->bits_per_sample > 0 && header->bits_per_sample <= (1u << FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN));
|
||||
switch(header->bits_per_sample) {
|
||||
case 8 : u = 1; break;
|
||||
case 12: u = 2; break;
|
||||
case 16: u = 4; break;
|
||||
case 20: u = 5; break;
|
||||
case 24: u = 6; break;
|
||||
default: u = 0; break;
|
||||
}
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, u, FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN))
|
||||
return false;
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, 0, FLAC__FRAME_HEADER_ZERO_PAD_LEN))
|
||||
return false;
|
||||
|
||||
if(header->number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER) {
|
||||
if(!FLAC__bitwriter_write_utf8_uint32(bw, header->number.frame_number))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if(!FLAC__bitwriter_write_utf8_uint64(bw, header->number.sample_number))
|
||||
return false;
|
||||
}
|
||||
|
||||
if(blocksize_hint)
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, header->blocksize-1, (blocksize_hint==6)? 8:16))
|
||||
return false;
|
||||
|
||||
switch(sample_rate_hint) {
|
||||
case 12:
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, header->sample_rate / 1000, 8))
|
||||
return false;
|
||||
break;
|
||||
case 13:
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, header->sample_rate, 16))
|
||||
return false;
|
||||
break;
|
||||
case 14:
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, header->sample_rate / 10, 16))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
/* write the CRC */
|
||||
if(!FLAC__bitwriter_get_write_crc8(bw, &crc))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, crc, FLAC__FRAME_HEADER_CRC_LEN))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__subframe_add_constant(const FLAC__Subframe_Constant *subframe, unsigned subframe_bps, unsigned wasted_bits, FLAC__BitWriter *bw)
|
||||
{
|
||||
FLAC__bool ok;
|
||||
|
||||
ok =
|
||||
FLAC__bitwriter_write_raw_uint32(bw, FLAC__SUBFRAME_TYPE_CONSTANT_BYTE_ALIGNED_MASK | (wasted_bits? 1:0), FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN) &&
|
||||
(wasted_bits? FLAC__bitwriter_write_unary_unsigned(bw, wasted_bits-1) : true) &&
|
||||
FLAC__bitwriter_write_raw_int32(bw, subframe->value, subframe_bps)
|
||||
;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__subframe_add_fixed(const FLAC__Subframe_Fixed *subframe, unsigned residual_samples, unsigned subframe_bps, unsigned wasted_bits, FLAC__BitWriter *bw)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, FLAC__SUBFRAME_TYPE_FIXED_BYTE_ALIGNED_MASK | (subframe->order<<1) | (wasted_bits? 1:0), FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN))
|
||||
return false;
|
||||
if(wasted_bits)
|
||||
if(!FLAC__bitwriter_write_unary_unsigned(bw, wasted_bits-1))
|
||||
return false;
|
||||
|
||||
for(i = 0; i < subframe->order; i++)
|
||||
if(!FLAC__bitwriter_write_raw_int32(bw, subframe->warmup[i], subframe_bps))
|
||||
return false;
|
||||
|
||||
if(!add_entropy_coding_method_(bw, &subframe->entropy_coding_method))
|
||||
return false;
|
||||
switch(subframe->entropy_coding_method.type) {
|
||||
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE:
|
||||
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2:
|
||||
if(!add_residual_partitioned_rice_(
|
||||
bw,
|
||||
subframe->residual,
|
||||
residual_samples,
|
||||
subframe->order,
|
||||
subframe->entropy_coding_method.data.partitioned_rice.contents->parameters,
|
||||
subframe->entropy_coding_method.data.partitioned_rice.contents->raw_bits,
|
||||
subframe->entropy_coding_method.data.partitioned_rice.order,
|
||||
/*is_extended=*/subframe->entropy_coding_method.type == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2
|
||||
))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
FLAC__ASSERT(0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__subframe_add_lpc(const FLAC__Subframe_LPC *subframe, unsigned residual_samples, unsigned subframe_bps, unsigned wasted_bits, FLAC__BitWriter *bw)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, FLAC__SUBFRAME_TYPE_LPC_BYTE_ALIGNED_MASK | ((subframe->order-1)<<1) | (wasted_bits? 1:0), FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN))
|
||||
return false;
|
||||
if(wasted_bits)
|
||||
if(!FLAC__bitwriter_write_unary_unsigned(bw, wasted_bits-1))
|
||||
return false;
|
||||
|
||||
for(i = 0; i < subframe->order; i++)
|
||||
if(!FLAC__bitwriter_write_raw_int32(bw, subframe->warmup[i], subframe_bps))
|
||||
return false;
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, subframe->qlp_coeff_precision-1, FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_int32(bw, subframe->quantization_level, FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN))
|
||||
return false;
|
||||
for(i = 0; i < subframe->order; i++)
|
||||
if(!FLAC__bitwriter_write_raw_int32(bw, subframe->qlp_coeff[i], subframe->qlp_coeff_precision))
|
||||
return false;
|
||||
|
||||
if(!add_entropy_coding_method_(bw, &subframe->entropy_coding_method))
|
||||
return false;
|
||||
switch(subframe->entropy_coding_method.type) {
|
||||
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE:
|
||||
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2:
|
||||
if(!add_residual_partitioned_rice_(
|
||||
bw,
|
||||
subframe->residual,
|
||||
residual_samples,
|
||||
subframe->order,
|
||||
subframe->entropy_coding_method.data.partitioned_rice.contents->parameters,
|
||||
subframe->entropy_coding_method.data.partitioned_rice.contents->raw_bits,
|
||||
subframe->entropy_coding_method.data.partitioned_rice.order,
|
||||
/*is_extended=*/subframe->entropy_coding_method.type == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2
|
||||
))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
FLAC__ASSERT(0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__subframe_add_verbatim(const FLAC__Subframe_Verbatim *subframe, unsigned samples, unsigned subframe_bps, unsigned wasted_bits, FLAC__BitWriter *bw)
|
||||
{
|
||||
unsigned i;
|
||||
const FLAC__int32 *signal = subframe->data;
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, FLAC__SUBFRAME_TYPE_VERBATIM_BYTE_ALIGNED_MASK | (wasted_bits? 1:0), FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN))
|
||||
return false;
|
||||
if(wasted_bits)
|
||||
if(!FLAC__bitwriter_write_unary_unsigned(bw, wasted_bits-1))
|
||||
return false;
|
||||
|
||||
for(i = 0; i < samples; i++)
|
||||
if(!FLAC__bitwriter_write_raw_int32(bw, signal[i], subframe_bps))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool add_entropy_coding_method_(FLAC__BitWriter *bw, const FLAC__EntropyCodingMethod *method)
|
||||
{
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, method->type, FLAC__ENTROPY_CODING_METHOD_TYPE_LEN))
|
||||
return false;
|
||||
switch(method->type) {
|
||||
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE:
|
||||
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2:
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, method->data.partitioned_rice.order, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
FLAC__ASSERT(0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool add_residual_partitioned_rice_(FLAC__BitWriter *bw, const FLAC__int32 residual[], const unsigned residual_samples, const unsigned predictor_order, const unsigned rice_parameters[], const unsigned raw_bits[], const unsigned partition_order, const FLAC__bool is_extended)
|
||||
{
|
||||
const unsigned plen = is_extended? FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN : FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
|
||||
const unsigned pesc = is_extended? FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER : FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER;
|
||||
|
||||
if(partition_order == 0) {
|
||||
unsigned i;
|
||||
|
||||
if(raw_bits[0] == 0) {
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, rice_parameters[0], plen))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_rice_signed_block(bw, residual, residual_samples, rice_parameters[0]))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
FLAC__ASSERT(rice_parameters[0] == 0);
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, pesc, plen))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, raw_bits[0], FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN))
|
||||
return false;
|
||||
for(i = 0; i < residual_samples; i++) {
|
||||
if(!FLAC__bitwriter_write_raw_int32(bw, residual[i], raw_bits[0]))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
unsigned i, j, k = 0, k_last = 0;
|
||||
unsigned partition_samples;
|
||||
const unsigned default_partition_samples = (residual_samples+predictor_order) >> partition_order;
|
||||
for(i = 0; i < (1u<<partition_order); i++) {
|
||||
partition_samples = default_partition_samples;
|
||||
if(i == 0)
|
||||
partition_samples -= predictor_order;
|
||||
k += partition_samples;
|
||||
if(raw_bits[i] == 0) {
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, rice_parameters[i], plen))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_rice_signed_block(bw, residual+k_last, k-k_last, rice_parameters[i]))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, pesc, plen))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, raw_bits[i], FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN))
|
||||
return false;
|
||||
for(j = k_last; j < k; j++) {
|
||||
if(!FLAC__bitwriter_write_raw_int32(bw, residual[j], raw_bits[i]))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
k_last = k;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,158 +0,0 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2013 Xiph.Org Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifndef FLAC__NO_ASM
|
||||
#if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && defined FLAC__HAS_X86INTRIN
|
||||
#include "private/stream_encoder.h"
|
||||
#ifdef FLAC__SSE2_SUPPORTED
|
||||
|
||||
#include <stdlib.h> /* for abs() */
|
||||
#include <emmintrin.h> /* SSE2 */
|
||||
#include "FLAC/assert.h"
|
||||
|
||||
FLAC__SSE_TARGET("sse2")
|
||||
void FLAC__precompute_partition_info_sums_intrin_sse2(const FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[],
|
||||
unsigned residual_samples, unsigned predictor_order, unsigned min_partition_order, unsigned max_partition_order, unsigned bps)
|
||||
{
|
||||
const unsigned default_partition_samples = (residual_samples + predictor_order) >> max_partition_order;
|
||||
unsigned partitions = 1u << max_partition_order;
|
||||
|
||||
FLAC__ASSERT(default_partition_samples > predictor_order);
|
||||
|
||||
/* first do max_partition_order */
|
||||
{
|
||||
unsigned partition, residual_sample, end = (unsigned)(-(int)predictor_order);
|
||||
unsigned e1, e3;
|
||||
__m128i mm_res, mm_sum, mm_mask;
|
||||
|
||||
if(bps <= 16) {
|
||||
for(partition = residual_sample = 0; partition < partitions; partition++) {
|
||||
end += default_partition_samples;
|
||||
mm_sum = _mm_setzero_si128();
|
||||
|
||||
e1 = (residual_sample + 3) & ~3; e3 = end & ~3;
|
||||
if(e1 > end)
|
||||
e1 = end; /* try flac -l 1 -b 16 and you'll be here */
|
||||
|
||||
/* assumption: residual[] is properly aligned so (residual + e1) is properly aligned too and _mm_loadu_si128() is fast */
|
||||
for( ; residual_sample < e1; residual_sample++) {
|
||||
mm_res = _mm_cvtsi32_si128(residual[residual_sample]);
|
||||
mm_mask = _mm_srai_epi32(mm_res, 31);
|
||||
mm_res = _mm_xor_si128(mm_res, mm_mask);
|
||||
mm_res = _mm_sub_epi32(mm_res, mm_mask); /* abs(INT_MIN) is undefined, but if the residual is INT_MIN we have bigger problems */
|
||||
mm_sum = _mm_add_epi32(mm_sum, mm_res);
|
||||
}
|
||||
|
||||
for( ; residual_sample < e3; residual_sample+=4) {
|
||||
mm_res = _mm_loadu_si128((const __m128i*)(residual+residual_sample));
|
||||
mm_mask = _mm_srai_epi32(mm_res, 31);
|
||||
mm_res = _mm_xor_si128(mm_res, mm_mask);
|
||||
mm_res = _mm_sub_epi32(mm_res, mm_mask);
|
||||
mm_sum = _mm_add_epi32(mm_sum, mm_res);
|
||||
}
|
||||
|
||||
for( ; residual_sample < end; residual_sample++) {
|
||||
mm_res = _mm_cvtsi32_si128(residual[residual_sample]);
|
||||
mm_mask = _mm_srai_epi32(mm_res, 31);
|
||||
mm_res = _mm_xor_si128(mm_res, mm_mask);
|
||||
mm_res = _mm_sub_epi32(mm_res, mm_mask);
|
||||
mm_sum = _mm_add_epi32(mm_sum, mm_res);
|
||||
}
|
||||
|
||||
mm_sum = _mm_add_epi32(mm_sum, _mm_srli_si128(mm_sum, 8));
|
||||
mm_sum = _mm_add_epi32(mm_sum, _mm_srli_si128(mm_sum, 4));
|
||||
abs_residual_partition_sums[partition] = _mm_cvtsi128_si32(mm_sum);
|
||||
}
|
||||
}
|
||||
else { /* have to pessimistically use 64 bits for accumulator */
|
||||
for(partition = residual_sample = 0; partition < partitions; partition++) {
|
||||
end += default_partition_samples;
|
||||
mm_sum = _mm_setzero_si128();
|
||||
|
||||
e1 = (residual_sample + 1) & ~1; e3 = end & ~1;
|
||||
FLAC__ASSERT(e1 <= end);
|
||||
|
||||
for( ; residual_sample < e1; residual_sample++) {
|
||||
mm_res = _mm_cvtsi32_si128(residual[residual_sample]); /* 0 0 0 r0 */
|
||||
mm_mask = _mm_srai_epi32(mm_res, 31);
|
||||
mm_res = _mm_xor_si128(mm_res, mm_mask);
|
||||
mm_res = _mm_sub_epi32(mm_res, mm_mask); /* 0 0 0 |r0| == 00 |r0_64| */
|
||||
mm_sum = _mm_add_epi64(mm_sum, mm_res);
|
||||
}
|
||||
|
||||
for( ; residual_sample < e3; residual_sample+=2) {
|
||||
mm_res = _mm_loadl_epi64((const __m128i*)(residual+residual_sample)); /* 0 0 r1 r0 */
|
||||
mm_mask = _mm_srai_epi32(mm_res, 31);
|
||||
mm_res = _mm_xor_si128(mm_res, mm_mask);
|
||||
mm_res = _mm_sub_epi32(mm_res, mm_mask); /* 0 0 |r1| |r0| */
|
||||
mm_res = _mm_shuffle_epi32(mm_res, _MM_SHUFFLE(3,1,2,0)); /* 0 |r1| 0 |r0| == |r1_64| |r0_64| */
|
||||
mm_sum = _mm_add_epi64(mm_sum, mm_res);
|
||||
}
|
||||
|
||||
for( ; residual_sample < end; residual_sample++) {
|
||||
mm_res = _mm_cvtsi32_si128(residual[residual_sample]);
|
||||
mm_mask = _mm_srai_epi32(mm_res, 31);
|
||||
mm_res = _mm_xor_si128(mm_res, mm_mask);
|
||||
mm_res = _mm_sub_epi32(mm_res, mm_mask);
|
||||
mm_sum = _mm_add_epi64(mm_sum, mm_res);
|
||||
}
|
||||
|
||||
mm_sum = _mm_add_epi64(mm_sum, _mm_srli_si128(mm_sum, 8));
|
||||
_mm_storel_epi64((__m128i*)(abs_residual_partition_sums+partition), mm_sum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* now merge partitions for lower orders */
|
||||
{
|
||||
unsigned from_partition = 0, to_partition = partitions;
|
||||
int partition_order;
|
||||
for(partition_order = (int)max_partition_order - 1; partition_order >= (int)min_partition_order; partition_order--) {
|
||||
unsigned i;
|
||||
partitions >>= 1;
|
||||
for(i = 0; i < partitions; i++) {
|
||||
abs_residual_partition_sums[to_partition++] =
|
||||
abs_residual_partition_sums[from_partition ] +
|
||||
abs_residual_partition_sums[from_partition+1];
|
||||
from_partition += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* FLAC__SSE2_SUPPORTED */
|
||||
#endif /* (FLAC__CPU_IA32 || FLAC__CPU_X86_64) && FLAC__HAS_X86INTRIN */
|
||||
#endif /* FLAC__NO_ASM */
|
@ -1,146 +0,0 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2013 Xiph.Org Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifndef FLAC__NO_ASM
|
||||
#if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && defined FLAC__HAS_X86INTRIN
|
||||
#include "private/stream_encoder.h"
|
||||
#ifdef FLAC__SSSE3_SUPPORTED
|
||||
|
||||
#include <stdlib.h> /* for abs() */
|
||||
#include <tmmintrin.h> /* SSSE3 */
|
||||
#include "FLAC/assert.h"
|
||||
|
||||
FLAC__SSE_TARGET("ssse3")
|
||||
void FLAC__precompute_partition_info_sums_intrin_ssse3(const FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[],
|
||||
unsigned residual_samples, unsigned predictor_order, unsigned min_partition_order, unsigned max_partition_order, unsigned bps)
|
||||
{
|
||||
const unsigned default_partition_samples = (residual_samples + predictor_order) >> max_partition_order;
|
||||
unsigned partitions = 1u << max_partition_order;
|
||||
|
||||
FLAC__ASSERT(default_partition_samples > predictor_order);
|
||||
|
||||
/* first do max_partition_order */
|
||||
{
|
||||
unsigned partition, residual_sample, end = (unsigned)(-(int)predictor_order);
|
||||
unsigned e1, e3;
|
||||
__m128i mm_res, mm_sum;
|
||||
|
||||
if(bps <= 16) {
|
||||
for(partition = residual_sample = 0; partition < partitions; partition++) {
|
||||
end += default_partition_samples;
|
||||
mm_sum = _mm_setzero_si128();
|
||||
|
||||
e1 = (residual_sample + 3) & ~3; e3 = end & ~3;
|
||||
if(e1 > end)
|
||||
e1 = end; /* try flac -l 1 -b 16 and you'll be here */
|
||||
|
||||
/* assumption: residual[] is properly aligned so (residual + e1) is properly aligned too and _mm_loadu_si128() is fast */
|
||||
for( ; residual_sample < e1; residual_sample++) {
|
||||
mm_res = _mm_cvtsi32_si128(residual[residual_sample]);
|
||||
mm_res = _mm_abs_epi32(mm_res); /* abs(INT_MIN) is undefined, but if the residual is INT_MIN we have bigger problems */
|
||||
mm_sum = _mm_add_epi32(mm_sum, mm_res);
|
||||
}
|
||||
|
||||
for( ; residual_sample < e3; residual_sample+=4) {
|
||||
mm_res = _mm_loadu_si128((const __m128i*)(residual+residual_sample));
|
||||
mm_res = _mm_abs_epi32(mm_res);
|
||||
mm_sum = _mm_add_epi32(mm_sum, mm_res);
|
||||
}
|
||||
|
||||
for( ; residual_sample < end; residual_sample++) {
|
||||
mm_res = _mm_cvtsi32_si128(residual[residual_sample]);
|
||||
mm_res = _mm_abs_epi32(mm_res);
|
||||
mm_sum = _mm_add_epi32(mm_sum, mm_res);
|
||||
}
|
||||
|
||||
mm_sum = _mm_hadd_epi32(mm_sum, mm_sum);
|
||||
mm_sum = _mm_hadd_epi32(mm_sum, mm_sum);
|
||||
abs_residual_partition_sums[partition] = _mm_cvtsi128_si32(mm_sum);
|
||||
}
|
||||
}
|
||||
else { /* have to pessimistically use 64 bits for accumulator */
|
||||
for(partition = residual_sample = 0; partition < partitions; partition++) {
|
||||
end += default_partition_samples;
|
||||
mm_sum = _mm_setzero_si128();
|
||||
|
||||
e1 = (residual_sample + 1) & ~1; e3 = end & ~1;
|
||||
FLAC__ASSERT(e1 <= end);
|
||||
|
||||
for( ; residual_sample < e1; residual_sample++) {
|
||||
mm_res = _mm_cvtsi32_si128(residual[residual_sample]); /* 0 0 0 r0 */
|
||||
mm_res = _mm_abs_epi32(mm_res); /* 0 0 0 |r0| == 00 |r0_64| */
|
||||
mm_sum = _mm_add_epi64(mm_sum, mm_res);
|
||||
}
|
||||
|
||||
for( ; residual_sample < e3; residual_sample+=2) {
|
||||
mm_res = _mm_loadl_epi64((const __m128i*)(residual+residual_sample)); /* 0 0 r1 r0 */
|
||||
mm_res = _mm_abs_epi32(mm_res); /* 0 0 |r1| |r0| */
|
||||
mm_res = _mm_shuffle_epi32(mm_res, _MM_SHUFFLE(3,1,2,0)); /* 0 |r1| 0 |r0| == |r1_64| |r0_64| */
|
||||
mm_sum = _mm_add_epi64(mm_sum, mm_res);
|
||||
}
|
||||
|
||||
for( ; residual_sample < end; residual_sample++) {
|
||||
mm_res = _mm_cvtsi32_si128(residual[residual_sample]);
|
||||
mm_res = _mm_abs_epi32(mm_res);
|
||||
mm_sum = _mm_add_epi64(mm_sum, mm_res);
|
||||
}
|
||||
|
||||
mm_sum = _mm_add_epi64(mm_sum, _mm_srli_si128(mm_sum, 8));
|
||||
_mm_storel_epi64((__m128i*)(abs_residual_partition_sums+partition), mm_sum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* now merge partitions for lower orders */
|
||||
{
|
||||
unsigned from_partition = 0, to_partition = partitions;
|
||||
int partition_order;
|
||||
for(partition_order = (int)max_partition_order - 1; partition_order >= (int)min_partition_order; partition_order--) {
|
||||
unsigned i;
|
||||
partitions >>= 1;
|
||||
for(i = 0; i < partitions; i++) {
|
||||
abs_residual_partition_sums[to_partition++] =
|
||||
abs_residual_partition_sums[from_partition ] +
|
||||
abs_residual_partition_sums[from_partition+1];
|
||||
from_partition += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* FLAC__SSSE3_SUPPORTED */
|
||||
#endif /* (FLAC__CPU_IA32 || FLAC__CPU_X86_64) && FLAC__HAS_X86INTRIN */
|
||||
#endif /* FLAC__NO_ASM */
|
Loading…
x
Reference in New Issue
Block a user