summaryrefslogtreecommitdiff
path: root/lib/libyaz0/yaz0.c
diff options
context:
space:
mode:
authorbriaguya <70942617+briaguya0@users.noreply.github.com>2026-07-24 18:09:55 -0400
committerGitHub <noreply@github.com>2026-07-24 18:09:55 -0400
commit4cae44160693e1beb562e39dc301bd42278be1f9 (patch)
tree5d247f7821a6040221b4bf34d2cae2b87c42d23a /lib/libyaz0/yaz0.c
parentcd33252589a61d044138f449041a87adee2a8291 (diff)
oot support (#219)
Diffstat (limited to 'lib/libyaz0/yaz0.c')
-rw-r--r--lib/libyaz0/yaz0.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/lib/libyaz0/yaz0.c b/lib/libyaz0/yaz0.c
new file mode 100644
index 0000000..20f94fb
--- /dev/null
+++ b/lib/libyaz0/yaz0.c
@@ -0,0 +1,57 @@
+#include "yaz0.h"
+#include "libmio0/utils.h"
+#include <stdlib.h>
+#include <string.h>
+
+uint8_t* yaz0_decode(const uint8_t* in, uint32_t* out_size) {
+ if (strncmp((const char*)in, "Yaz0", 4) != 0) {
+ return NULL;
+ }
+
+ uint32_t decompressed_size = read_u32_be(in + 4);
+ uint8_t* out = malloc(decompressed_size);
+ if (!out) {
+ return NULL;
+ }
+
+ uint32_t src = YAZ0_HEADER_LENGTH;
+ uint32_t dst = 0;
+ uint8_t group_head = 0;
+ int bits_left = 0;
+
+ while (dst < decompressed_size) {
+ if (bits_left == 0) {
+ group_head = in[src++];
+ bits_left = 8;
+ }
+
+ if (group_head & 0x80) {
+ /* literal byte */
+ out[dst++] = in[src++];
+ } else {
+ /* back-reference */
+ uint8_t b1 = in[src++];
+ uint8_t b2 = in[src++];
+
+ uint32_t dist = ((b1 & 0x0F) << 8) | b2;
+ uint32_t copy_src = dst - (dist + 1);
+ uint32_t count;
+
+ if (b1 >> 4) {
+ count = (b1 >> 4) + 2;
+ } else {
+ count = in[src++] + 0x12;
+ }
+
+ for (uint32_t i = 0; i < count; i++) {
+ out[dst++] = out[copy_src + i];
+ }
+ }
+
+ group_head <<= 1;
+ bits_left--;
+ }
+
+ *out_size = decompressed_size;
+ return out;
+}