Files
uc2/lib/include/uc2/libuc2.h
T
Eremey Valetov a30c8cf694 Add archive creation with SuperMaster compression
CLI: uc2 -w [-L level] archive.uc2 files...
Creates UC2 archives with long filename tags and the built-in 49KB
SuperMaster dictionary for improved compression via LZ77 prefix matching.

Library: uc2_compress_ex() accepts master data to pre-fill the sliding
window and hash chains. uc2_get_supermaster() decompresses the embedded
super.bin. uc2_compress() unchanged (backward compatible, NoMaster).

Tests: 5 SuperMaster roundtrip tests, CLI create/extract CTest script.
2026-03-12 02:04:13 -04:00

181 lines
4.7 KiB
C

#ifndef LIBUC2_H
#define LIBUC2_H
#ifndef UC2_API
# if defined(UC2_SHARED) && defined(_WIN32)
# ifdef UC2_BUILD
# define UC2_API __declspec(dllexport)
# else
# define UC2_API __declspec(dllimport)
# endif
# elif defined(UC2_SHARED) && defined(__GNUC__)
# define UC2_API __attribute__((visibility("default")))
# else
# define UC2_API
# endif
#endif
/* API
uc2_identify - check UC2 magic
uc2_open - initialize
uc2_read_cdir - read dir entry
uc2_get_tag - read tag
uc2_finish_cdir - get archive label
uc2_extract - decompress file
uc2_message - get error message
uc2_close - free resources
uc2_open
repeat {
uc2_read_cdir
if UC2_End
optionally uc2_finish_cdir
else while UC2_TaggedEntry
uc2_get_tag
}
uc2_close
*/
struct uc2_io; // User callbacks
struct uc2_xinfo; // Extraction info
struct uc2_entry; // CDir entry
struct uc2_context;
typedef struct uc2_context *uc2_handle;
UC2_API int uc2_identify(void *magic, unsigned magic_size /* 4..21 */);
UC2_API uc2_handle uc2_open(struct uc2_io *io, void *io_ctx);
UC2_API uc2_handle uc2_close(uc2_handle);
/* Get cdir entry. Pass NULL to skip the rest. Returns:
UC2_End: The end, entry not filled,
UC2_BareEntry: New entry filled, no tags,
UC2_TaggedEntry: New entry filled, has tags (must call uc2_get_tag),
Negative value on error.
Directories come before content. Duplicates: older first. */
UC2_API int uc2_read_cdir(
uc2_handle,
struct uc2_entry * // Entry to fill. Pass NULL to finish early.
);
/* Returns UC2_End, if final tag, UC2_TaggedEntry, if more, or negative on error */
UC2_API int uc2_get_tag(
uc2_handle,
struct uc2_entry *, // to fill name
char **tag, // char[16], pass NULL to skip tags
void **data,
unsigned *data_len
);
UC2_API int uc2_finish_cdir(
uc2_handle,
char label[12]
);
/* Allowed only after whole cdir has been read.
write() should return <0 on error. */
UC2_API int uc2_extract(
uc2_handle,
struct uc2_xinfo *,
unsigned size,
int (*write)(void *context, const void *ptr, unsigned len),
void *context
);
UC2_API const char *uc2_message(uc2_handle, int ret);
/* Compress raw data into a UC2 bitstream (no archive framing).
level: 2=Fast, 3=Normal, 4=Tight(default), 5=Ultra.
read() should return bytes read (0 at EOF, <0 on error).
write() should return <0 on error.
Returns 0 on success, negative UC2_* error code on failure. */
UC2_API int uc2_compress(
int level,
int (*read)(void *context, void *buf, unsigned len),
void *read_ctx,
int (*write)(void *context, const void *ptr, unsigned len),
void *write_ctx,
unsigned size,
unsigned short *checksum_out,
unsigned *compressed_size_out
);
/* Compress with a master-block dictionary prefix.
The master data pre-fills the LZ77 sliding window, allowing
back-references into the master for cross-file deduplication.
Set master=NULL, master_size=0 for no master (same as uc2_compress). */
UC2_API int uc2_compress_ex(
int level,
const void *master, unsigned master_size,
int (*read)(void *context, void *buf, unsigned len),
void *read_ctx,
int (*write)(void *context, const void *ptr, unsigned len),
void *write_ctx,
unsigned size,
unsigned short *checksum_out,
unsigned *compressed_size_out
);
/* Decompress the built-in SuperMaster (49152 bytes).
buf must be at least 49152 bytes.
Returns 49152 on success, negative UC2_* error code on failure. */
UC2_API int uc2_get_supermaster(void *buf, unsigned buf_size);
struct uc2_io {
/* Read len bytes from the archive at offset pos into buf.
Return number of bytes read, or less if eof.
Negative value indicates an error. */
int (*read)(void *io_ctx, unsigned pos, void *buf, unsigned len);
/* Allocate memory. Return NULL on error */
void *(*alloc)(void *io_ctx, unsigned size);
void (*free)(void *io_ctx, void *ptr);
/* Optional */
void (*warn)(void *io_ctx, char *fmt, ...);
};
enum {
UC2_UserFault = -2, // User callback refused to cooperate.
UC2_BadState = -3, // uc2_scan() should return 0 first.
UC2_Damaged = -4,
UC2_Truncated = -5,
UC2_Unimplemented = -6,
UC2_InternalError = -7
};
enum {
UC2_End = 0,
UC2_BareEntry = 1,
UC2_TaggedEntry = 3
};
struct uc2_xinfo {
unsigned offset, master;
unsigned short csum, method;
};
struct uc2_entry {
unsigned dirid; // Directory it belongs to. Root is 0.
unsigned id; // dir only
struct uc2_xinfo xi;
unsigned size; // file only
unsigned csize; // file only
unsigned dos_time;
unsigned char is_dir:1;
unsigned char has_tags:1;
unsigned char attr;
unsigned char dos_name[11]; // not terminated
unsigned short name_len;
char name[300]; // ready after tags have been read
};
enum {
UC2_Attr_R = 1,
UC2_Attr_H = 2,
UC2_Attr_S = 4,
UC2_Attr_D = 16,
UC2_Attr_A = 32
};
#endif // LIBUC2_H