The C binding wraps honzo-core and honzo-io into a plain C API using Diplomat. Two modes are provided: the in-memory parser (HonzoHandle) and the file-backed streaming reader (HonzoFileReader). Building is not yet available.
Usage
#include "honzo.h"
HonzoHandle* handle = HonzoHandle_parse(data, data_len, 1);
uint32_t count = HonzoHandle_chunk_count(handle);
// ... use handle ...
HonzoHandle_destroy(handle);
| Return | Meaning |
|---|---|
| 0 | Success |
| nonzero | Error |
Exported types
HonzoHandle– In-memory parser handle (reads entire file into a buffer)HonzoFileReader– File-backed streaming reader (reads one chunk at a time)HonzoErrorCode– Error codes returned by fallible functionsHonzoHead– File header structTocEntry– TOC entry structMetaMap– META data as key-value pairs
HonzoFileReader (streaming)
Open a Honzo file from the filesystem and read chunks on demand. Each get_chunk call performs one seek, one read, and one LZ4 decompression. The returned data is valid only until the next get_chunk call on the same reader.
HonzoFileReader lifecycle
| Symbol | Signature | Returns | Notes |
|---|---|---|---|
HonzoFileReader_open |
DiplomatStringView path, uint16_t reader_version |
HonzoFileReader_open_result |
Open from file path. |
HonzoFileReader_open_with_private_key |
DiplomatStringView path, uint16_t reader_version, DiplomatU8View private_key |
HonzoFileReader_open_with_private_key_result |
Open with DRM key. |
HonzoFileReader_destroy |
HonzoFileReader* self |
void |
Free the reader. |
HonzoFileReader accessors
| Symbol | Signature | Returns | Notes |
|---|---|---|---|
HonzoFileReader_chunk_count |
const HonzoFileReader* self |
uint32_t |
Number of chunks. |
HonzoFileReader_get_chunk_type |
const HonzoFileReader* self, uint32_t index |
uint32_t |
4-byte chunk tag as native-endian u32 (e.g. 0x50414843 for "CHAP"). Returns 0 if index out of range. |
HonzoFileReader_get_chunk_content_type_kind |
const HonzoFileReader* self, uint32_t index |
uint8_t |
Content type kind: 1 = markup, 2 = math. Returns 0 if index out of range. |
HonzoFileReader_get_chunk_content_type_value |
const HonzoFileReader* self, uint32_t index |
uint8_t |
Content type value: markup 0 = Markdown, 1 = HTML; math 0 = MathML, 1 = LaTeX. Returns 0 if index out of range. |
HonzoFileReader_get_chunk_alt_text |
const HonzoFileReader* self, uint32_t index |
HonzoFileReader_get_chunk_alt_text_result |
Human-readable label: chapter title for CHAP, alt text for IMG_, etc. Empty view if index out of range or no label. |
HonzoFileReader_get_chunk |
HonzoFileReader* self, uint32_t index |
HonzoFileReader_get_chunk_result |
Decompressed chunk data. Valid until next call to this function. |
HonzoFileReader_get_meta |
HonzoFileReader* self, DiplomatWrite* write |
HonzoFileReader_get_meta_result |
JSON metadata string. |
Metadata extraction without parsing
Extract the META block as JSON directly from a file on disk without loading
chunks into memory. Returns Ok(()) on success; on failure returns
HonzoErrorCode_FileNotFound, HonzoErrorCode_InvalidMagic,
HonzoErrorCode_ReaderVersionTooOld, or HonzoErrorCode_Truncated.
| Symbol | Signature | Returns | Notes |
|---|---|---|---|
hzo_extract_meta_from_file |
DiplomatStringView path, uint16_t reader_version, DiplomatWrite* write |
hzo_extract_meta_from_file_result |
JSON metadata string. |
hzo_extract_meta_from_file_result res =
hzo_extract_meta_from_file(book_path, 1, &write);
if (res.is_ok) {
// write.buf contains the META block as JSON
}
Image format detection
diplomat_external_guess_image_mime identifies image formats from raw bytes without linking the full image crate, which doesn’t compile for embedded targets. Returns Ok(mime_string) on recognition or an error for unknown formats.
diplomat_external_guess_image_mime_result res =
diplomat_external_guess_image_mime(chunk_bytes, &write);
if (res.is_ok) {
// write.buf contains e.g. "image/png", "image/jpeg", "image/gif", etc.
}
Recognizes: PNG, JPEG, GIF, BMP, TIFF (LE/BE), WebP, ICO, PNM (PBM/PGM/PPM/PAM).
Example
#include "HonzoFileReader.h"
#include <stdio.h>
#include <string.h>
int main(void) {
DiplomatStringView book_path = {"/sdcard/books/book.hzo", 22};
HonzoFileReader_open_result r =
HonzoFileReader_open(book_path, 1);
if (!r.is_ok) {
fprintf(stderr, "open failed: error %d\n", r.err);
return 1;
}
HonzoFileReader* reader = r.ok;
uint32_t n = HonzoFileReader_chunk_count(reader);
uint32_t covr_tag, covt_tag, img_tag, chap_tag;
memcpy(&covr_tag, "COVR", 4);
memcpy(&covt_tag, "COVT", 4);
memcpy(&img_tag, "IMG_", 4);
memcpy(&chap_tag, "CHAP", 4);
for (uint32_t i = 0; i < n; i++) {
uint32_t tag = HonzoFileReader_get_chunk_type(reader, i);
// Identify image chunks by type
if (tag == covr_tag || tag == covt_tag || tag == img_tag) {
HonzoFileReader_get_chunk_result c =
HonzoFileReader_get_chunk(reader, i);
if (c.is_ok) {
char mime_buf[32];
DiplomatWrite mime_write = diplomat_simple_write(mime_buf, sizeof(mime_buf));
diplomat_external_guess_image_mime_result mr =
diplomat_external_guess_image_mime(
(DiplomatU8View){c.ok.data, c.ok.len}, &mime_write);
printf("chunk %u: %s\n", i,
mr.is_ok ? mime_buf : "unknown");
}
continue;
}
// Only process CHAP chunks beyond images
if (tag != chap_tag) continue;
uint8_t kind = HonzoFileReader_get_chunk_content_type_kind(reader, i);
uint8_t val = HonzoFileReader_get_chunk_content_type_value(reader, i);
HonzoFileReader_get_chunk_result c =
HonzoFileReader_get_chunk(reader, i);
if (!c.is_ok) continue;
// c.ok.data / c.ok.len -- copy before next get_chunk call
printf("chunk %u: kind=%u val=%u size=%zu\n",
i, kind, val, c.ok.len);
}
HonzoFileReader_destroy(reader);
return 0;
}
HonzoHandle (in-memory parser)
Parse a Honzo file from a byte buffer in memory.
HonzoHandle lifecycle
| Symbol | Signature | Returns | Notes |
|---|---|---|---|
HonzoHandle_parse |
const uint8_t* data, size_t len, uint32_t version |
HonzoHandle* |
Parse from byte buffer. Returns NULL on error. |
HonzoHandle_destroy |
HonzoHandle* handle |
void |
Free the handle. |
HonzoHandle accessors
| Symbol | Signature | Returns | Notes |
|---|---|---|---|
HonzoHandle_chunk_count |
const HonzoHandle* |
uint32_t |
Number of chunks. |
HonzoHandle_head |
const HonzoHandle*, HonzoHead* out |
int32_t |
0 on success, nonzero on error. |
HonzoHandle_toc_entry |
const HonzoHandle*, uint32_t index, TocEntry* out |
int32_t |
0 on success, nonzero on error. |
HonzoHandle_chunk_data |
const HonzoHandle*, uint32_t index, const uint8_t** out, size_t* out_len |
int32_t |
Pointer to chunk data. Don’t free. |
HonzoHandle_meta_raw |
const HonzoHandle*, const uint8_t** out, size_t* out_len |
int32_t |
Raw META MessagePack bytes. |
HonzoHandle_error |
const HonzoHandle* |
const char* |
Last error message (UTF-8). |
HonzoErrorCode
| Code | Meaning |
|---|---|
HonzoErrorCode_Ok = 0 |
Success |
HonzoErrorCode_InvalidMagic = 1 |
Not a Honzo file |
HonzoErrorCode_ReaderVersionTooOld = 2 |
Reader version too low |
HonzoErrorCode_BufferTooShort = 3 |
Unexpected end of data |
HonzoErrorCode_CrcMismatch = 4 |
CRC32 checksum mismatch |
HonzoErrorCode_EncryptedChunk = 5 |
Chunk requires DRM key |
HonzoErrorCode_InvalidMathML = 6 |
Malformed MathML content |
HonzoErrorCode_Truncated = 7 |
Truncated or corrupt data |
HonzoErrorCode_InvalidCss = 8 |
Malformed CSS content |
HonzoErrorCode_InvalidSyncCue = 9 |
Invalid sync cue entry |
HonzoErrorCode_FileNotFound = 10 |
File does not exist |
HonzoErrorCode_Unknown = 255 |
Unspecified error |
HonzoHead struct
typedef struct {
uint32_t format_version;
uint16_t chunk_count;
uint8_t layout_mode;
uint8_t flags;
uint64_t data_offset;
uint64_t extra_offset;
uint64_t meta_offset;
uint32_t meta_size;
} HonzoHead;
TocEntry struct
typedef struct {
uint8_t chunk_type[4];
uint8_t content_type;
uint8_t compression;
uint8_t markup_type;
uint8_t cover_type;
uint16_t language;
uint16_t font_embedding;
uint16_t font_license_url_len;
uint64_t offset;
uint32_t size;
uint32_t orig_size;
} TocEntry;
Feature flags
The image feature (default: on) enables cover thumbnail generation and image validation, and is only needed when writing/building Honzo files. The streaming reader path (HonzoFileReader) never uses it.
# Host build (default, includes image support for builder tools)
cargo build -p honzo-c --release
# Embedded build (no image crate, smaller compile)
cargo build -p honzo-c --release --no-default-features
Feature propagation: honzo-c --image --> honzo-io --image --> honzo-chunks --image.
Building
Host
cargo build -p honzo-c --release
# Produces: target/release/libhonzo_c.a
# Headers: Build/crates/honzo-c/include/
Link with:
cc -o reader reader.c -L./target/release -lhonzo_c -lpthread -ldl -lm
ESP32
Requires the xtensa-esp32-espidf target. Install via espup.
# Build staticlib without image processing
cargo +esp build --release -p honzo-c \
--target xtensa-esp32-espidf \
-Zbuild-std=std,panic_abort \
--no-default-features
# Produces: target/xtensa-esp32-espidf/release/libhonzo_c.a
Link your C firmware against the staticlib using the ESP-IDF toolchain. The resulting binary occupies roughly 434 KB total (431 KB text, 2.2 KB RAM) for a minimal reader.