zupt/include/vaptvupt.h

260 lines
12 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* VaptVupt codec — originally Apache-2.0 by Cristian Cezar Moisés
* Integrated into Zupt — MIT License
* Copyright (c) 2026 Cristian Cezar Moisés
* SPDX-License-Identifier: MIT AND Apache-2.0
*/
/*
* VaptVupt Codec — Next-generation lossless compression
* Public API and data structures
*
* Zero dependencies. Pure C11.
*/
#ifndef VAPTVUPT_H
#define VAPTVUPT_H
#include <stdint.h>
#include <stddef.h>
/* VAPTVUPT: When integrated into Zupt, pull in zupt_xxh64 declaration */
#ifndef VV_STANDALONE
#include "zupt.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* ═══════════════════════════════════════════════════════════════
* VERSION & CONSTANTS
* ═══════════════════════════════════════════════════════════════ */
#define VV_VERSION_MAJOR 0
#define VV_VERSION_MINOR 1
#define VV_VERSION_PATCH 0
#define VV_VERSION_STRING "0.1.0"
#define VV_MAGIC 0x56560100u /* "VV\x01\x00" */
#define VV_MAX_BLOCK_SIZE (1u << 20) /* 1 MB per block */
#define VV_MIN_MATCH 4
#define VV_MAX_MATCH 65535
#define VV_MAX_LIT_RUN 65535
#define VV_MAX_OFFSET (1u << 24) /* 16 MB default window */
/* ═══════════════════════════════════════════════════════════════
* ERROR CODES
* ═══════════════════════════════════════════════════════════════ */
typedef enum {
VV_OK = 0,
VV_ERR_IO = -1,
VV_ERR_CORRUPT = -2,
VV_ERR_NOMEM = -3,
VV_ERR_OVERFLOW = -4,
VV_ERR_BAD_MAGIC = -5,
VV_ERR_PARAM = -6,
} vv_error_t;
/* ═══════════════════════════════════════════════════════════════
* COMPRESSION MODES
* ═══════════════════════════════════════════════════════════════ */
typedef enum {
VV_MODE_ULTRA_FAST = 0, /* Speed priority: greedy parse, no entropy */
VV_MODE_BALANCED = 1, /* Default: lazy parse + Huffman */
VV_MODE_EXTREME = 2, /* Ratio priority: optimal parse + Huffman */
} vv_mode_t;
/* ═══════════════════════════════════════════════════════════════
* BLOCK TYPES (2-bit field in block header)
* ═══════════════════════════════════════════════════════════════ */
typedef enum {
VV_BLOCK_RAW = 0, /* Uncompressed (stored) */
VV_BLOCK_COMPRESSED = 1, /* LZ + raw literals */
VV_BLOCK_RLE = 2, /* Run-length (single byte) */
VV_BLOCK_ENTROPY = 3, /* LZ + entropy-coded literals (ANS or Huffman) */
} vv_block_type_t;
/* Entropy sub-type tags (first byte of entropy section in type-3 blocks) */
#define VV_ENTROPY_HUFFMAN 0x48 /* 'H' — Huffman (v0.3-v0.4) */
#define VV_ENTROPY_ANS 0x41 /* 'A' — tANS single-stream (v0.5) */
#define VV_ENTROPY_ANS4 0x49 /* 'I' — tANS 4-way interleaved (v0.6+) */
#define VV_ENTROPY_CTX 0x43 /* 'C' — tANS order-1 context model (v0.7+) */
#define VV_ENTROPY_SEQ 0x53 /* 'S' — sequence coding: ANS on lits+ml+of (v0.8+) */
/* Block header accessors (2-bit type, 1-bit last, 21-bit size) */
static inline vv_block_type_t vv_bh_type(uint32_t h) { return (vv_block_type_t)(h & 3); }
static inline int vv_bh_last(uint32_t h) { return (h >> 2) & 1; }
static inline uint32_t vv_bh_size(uint32_t h) { return (h >> 3) & 0x1FFFFF; }
static inline uint32_t vv_bh_pack(vv_block_type_t t, int last, uint32_t sz) {
return (uint32_t)t | ((uint32_t)last << 2) | (sz << 3);
}
/* ═══════════════════════════════════════════════════════════════
* TOKEN TYPES (in the sequence stream)
*
* Each token is: [type:2][litlen:6] [optional litlen ext]
* [literal bytes]
* [matchlen ext] [offset bytes]
*
* The decoder reads a compact token byte, copies literals,
* then copies a match. This is LZ4-like for speed.
* ═══════════════════════════════════════════════════════════════ */
/* Token byte layout:
* Bits 7-4: literal_length (0-14, 15=extended)
* Bits 3-0: match_length - VV_MIN_MATCH (0-14, 15=extended)
*
* Followed by:
* [extended literal length varint, if litlen==15]
* [literal bytes]
* [offset: 2 bytes LE (or 3 bytes if high bit set)]
* [extended match length varint, if matchlen==15]
*/
/* ═══════════════════════════════════════════════════════════════
* ON-DISK STRUCTURES
* ═══════════════════════════════════════════════════════════════ */
#pragma pack(push, 1)
/* Frame header: 16 bytes */
typedef struct {
uint32_t magic; /* VV_MAGIC */
uint8_t version; /* Format version (1) */
uint8_t flags; /* bit0: has_checksum, bit1: has_dict */
uint8_t mode_hint; /* Compression mode used (informational) */
uint8_t window_log; /* Window size = 1 << window_log */
uint64_t content_size; /* Uncompressed size (0 = unknown) */
} vv_frame_header_t;
/* Block header: 4 bytes */
typedef struct {
/* Bits 0-1: block_type (vv_block_type_t) */
/* Bit 2: last_block flag */
/* Bits 3-23: decompressed_size (max 1 MB) */
/* Bits 24-31: reserved */
uint32_t packed;
} vv_block_header_t;
/* Frame footer: 12 bytes */
typedef struct {
uint64_t checksum; /* XXH64 of decompressed content */
uint32_t footer_magic; /* 0x56564E44 = "VVND" */
} vv_frame_footer_t;
#pragma pack(pop)
/* Block header accessors defined above with block type enum */
/* ═══════════════════════════════════════════════════════════════
* MATCHER STATE
* ═══════════════════════════════════════════════════════════════ */
#define VV_HC_BITS 18
#define VV_HC_SIZE (1u << VV_HC_BITS)
typedef struct {
int32_t table[VV_HC_SIZE]; /* Hash → most recent position */
int32_t *chain; /* Chain array (window_size entries) */
uint32_t window_size;
uint32_t chain_depth; /* Max chain traversal (level-dependent) */
} vv_matcher_t;
/* ═══════════════════════════════════════════════════════════════
* HUFFMAN TABLES (entropy coding)
*
* 256-symbol alphabet. Max code length 12 bits.
* Decode table: 4096 entries × 2 bytes = 8 KB (fits in L1).
* ═══════════════════════════════════════════════════════════════ */
#define VV_HUF_MAX_BITS 12
#define VV_HUF_TABLE_SIZE (1 << VV_HUF_MAX_BITS)
typedef struct {
uint8_t lengths[256]; /* Code lengths per symbol */
uint16_t codes[256]; /* Canonical codes (for encoding) */
/* Decode table: entry = (symbol << 8) | num_bits */
uint16_t decode[VV_HUF_TABLE_SIZE];
} vv_huffman_t;
/* ═══════════════════════════════════════════════════════════════
* ENCODER/DECODER OPTIONS
* ═══════════════════════════════════════════════════════════════ */
typedef struct {
vv_mode_t mode;
uint8_t window_log; /* 0 = auto (20 for balanced, 24 for extreme) */
int checksum; /* 1 = compute XXH64 */
int verbose;
} vv_options_t;
static inline void vv_default_options(vv_options_t *o) {
o->mode = VV_MODE_BALANCED;
o->window_log = 0;
o->checksum = 1;
o->verbose = 0;
}
/* ═══════════════════════════════════════════════════════════════
* PUBLIC API
* ═══════════════════════════════════════════════════════════════ */
/* Compress src[0..src_len-1] into dst[0..dst_cap-1].
* Returns compressed size, or negative error code. */
int64_t vv_compress(const uint8_t *src, size_t src_len,
uint8_t *dst, size_t dst_cap,
const vv_options_t *opts);
/* Decompress src[0..src_len-1] into dst[0..dst_cap-1].
* Returns decompressed size, or negative error code. */
int64_t vv_decompress(const uint8_t *src, size_t src_len,
uint8_t *dst, size_t dst_cap);
/* Compute upper bound on compressed size for src_len input bytes. */
size_t vv_compress_bound(size_t src_len);
/* ═══════════════════════════════════════════════════════════════
* INTERNAL HELPERS (shared across modules)
* ═══════════════════════════════════════════════════════════════ */
/* XXH64 hash (simplified, for checksum) */
/* VAPTVUPT: vv_xxh64 aliased to zupt_xxh64 (avoid duplicate symbol) */
#define vv_xxh64 zupt_xxh64
/* Hash function for matcher */
static inline uint32_t vv_hash4(const uint8_t *p) {
uint32_t v;
__builtin_memcpy(&v, p, 4);
return (v * 2654435761u) >> (32 - VV_HC_BITS);
}
/* Read/write little-endian helpers */
static inline uint16_t vv_read16(const uint8_t *p) {
uint16_t v; __builtin_memcpy(&v, p, 2); return v;
}
static inline uint32_t vv_read32(const uint8_t *p) {
uint32_t v; __builtin_memcpy(&v, p, 4); return v;
}
static inline void vv_write16(uint8_t *p, uint16_t v) {
__builtin_memcpy(p, &v, 2);
}
static inline void vv_write32(uint8_t *p, uint32_t v) {
__builtin_memcpy(p, &v, 4);
}
/* ═══════════════════════════════════════════════════════════════
* SIMD COPY HELPERS (declared here, defined in vv_simd.c)
* ═══════════════════════════════════════════════════════════════ */
/* Copy exactly n bytes, may over-read/write by up to 32 bytes.
* Caller must ensure sufficient slack in destination. */
void vv_copy_fast(uint8_t *dst, const uint8_t *src, size_t n);
/* Copy match with overlap handling (offset may be < copy length). */
void vv_copy_match(uint8_t *dst, uint32_t offset, size_t length);
#ifdef __cplusplus
}
#endif
#endif /* VAPTVUPT_H */