#ifndef WEBP_UTILS_BIT_WRITER_UTILS_H_
#define WEBP_UTILS_BIT_WRITER_UTILS_H_
#include <stddef.h>
#include "src/dsp/cpu.h"
#include "src/utils/bounds_safety.h"
#include "src/webp/types.h"
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
#ifdef __cplusplus
extern "C" {
#endif
typedef struct VP8BitWriter VP8BitWriter;
struct VP8BitWriter {
int32_t range; int32_t value;
int run; int nb_bits; uint8_t* WEBP_SIZED_BY_OR_NULL(max_pos) buf;
size_t pos;
size_t max_pos;
int error; };
int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size);
uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw);
void VP8BitWriterWipeOut(VP8BitWriter* const bw);
int VP8PutBit(VP8BitWriter* const bw, int bit, int prob);
int VP8PutBitUniform(VP8BitWriter* const bw, int bit);
void VP8PutBits(VP8BitWriter* const bw, uint32_t value, int nb_bits);
void VP8PutSignedBits(VP8BitWriter* const bw, int value, int nb_bits);
int VP8BitWriterAppend(VP8BitWriter* const bw, const uint8_t* data,
size_t size);
static WEBP_INLINE uint64_t VP8BitWriterPos(const VP8BitWriter* const bw) {
const uint64_t nb_bits = 8 + bw->nb_bits; return (bw->pos + bw->run) * 8 + nb_bits;
}
static WEBP_INLINE uint8_t* VP8BitWriterBuf(const VP8BitWriter* const bw) {
return bw->buf;
}
static WEBP_INLINE size_t VP8BitWriterSize(const VP8BitWriter* const bw) {
return bw->pos;
}
#if defined(__x86_64__) || defined(_M_X64) || WEBP_AARCH64 || defined(__wasm__)
typedef uint64_t vp8l_atype_t; typedef uint32_t vp8l_wtype_t; #define WSWAP HToLE32
#define VP8L_WRITER_BYTES 4
#define VP8L_WRITER_BITS 32
#define VP8L_WRITER_MAX_BITS 64
#else
typedef uint32_t vp8l_atype_t;
typedef uint16_t vp8l_wtype_t;
#define WSWAP HToLE16
#define VP8L_WRITER_BYTES 2
#define VP8L_WRITER_BITS 16
#define VP8L_WRITER_MAX_BITS 32
#endif
typedef struct {
vp8l_atype_t bits; int used; uint8_t* WEBP_ENDED_BY(end) buf; uint8_t* WEBP_UNSAFE_INDEXABLE cur; uint8_t* end;
int error;
} VP8LBitWriter;
static WEBP_INLINE size_t VP8LBitWriterNumBytes(const VP8LBitWriter* const bw) {
return (bw->cur - bw->buf) + ((bw->used + 7) >> 3);
}
int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size);
int VP8LBitWriterClone(const VP8LBitWriter* const src,
VP8LBitWriter* const dst);
uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw);
void VP8LBitWriterWipeOut(VP8LBitWriter* const bw);
void VP8LBitWriterReset(const VP8LBitWriter* const bw_init,
VP8LBitWriter* const bw);
void VP8LBitWriterSwap(VP8LBitWriter* const src, VP8LBitWriter* const dst);
void VP8LPutBitsFlushBits(VP8LBitWriter* const bw, int* used,
vp8l_atype_t* bits);
#if VP8L_WRITER_BITS == 16
void VP8LPutBitsInternal(VP8LBitWriter* const bw, uint32_t bits, int n_bits);
#endif
static WEBP_INLINE void VP8LPutBits(VP8LBitWriter* const bw, uint32_t bits,
int n_bits) {
#if VP8L_WRITER_BYTES == 4
if (n_bits == 0) return;
if (bw->used >= VP8L_WRITER_BITS) {
VP8LPutBitsFlushBits(bw, &bw->used, &bw->bits);
}
bw->bits |= (vp8l_atype_t)bits << bw->used;
bw->used += n_bits;
#else
VP8LPutBitsInternal(bw, bits, n_bits);
#endif
}
#ifdef __cplusplus
} #endif
#endif