From afaa25b9bd5d9e8c2e0a410eede6f30680c35d72 Mon Sep 17 00:00:00 2001 From: Richard Qin Date: Wed, 13 May 2026 15:42:22 +0800 Subject: feat: add LZ4 decompressor implementation and update linker script --- na/lib/decompress_lz4.cc | 77 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 na/lib/decompress_lz4.cc (limited to 'na/lib') diff --git a/na/lib/decompress_lz4.cc b/na/lib/decompress_lz4.cc new file mode 100644 index 0000000..6a93936 --- /dev/null +++ b/na/lib/decompress_lz4.cc @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* Copyright (C) 2026 Richard Qin */ + +#include + +int lz4_decompress(const uint8* src, uint32 src_len, uint8* dst, uint32 dst_cap) +{ + const uint8* ip = src; + const uint8* iend = src + src_len; + uint8* op = dst; + uint8* oend = dst + dst_cap; + + while (ip < iend) { + uint8 token = *ip++; + uint32 lit_len = token >> 4; + + if (lit_len == 15) { + uint8 s = 0; + do { + if (ip >= iend) { + return -1; + } + s = *ip++; + lit_len += s; + } while (s == 255); + } + + if (ip + lit_len > iend) { + return -1; + } + if (op + lit_len > oend) { + return -1; + } + + for (uint32 i = 0; i < lit_len; ++i) { + *op++ = *ip++; + } + + if (ip >= iend) { + break; + } + if (ip + 2 > iend) { + return -1; + } + + uint32 off = static_cast(ip[0]) | (static_cast(ip[1]) << 8); + ip += 2; + if (off == 0 || off > static_cast(op - dst)) { + return -1; + } + + uint32 match_len = token & 0x0F; + if (match_len == 15) { + uint8 s = 0; + do { + if (ip >= iend) { + return -1; + } + s = *ip++; + match_len += s; + } while (s == 255); + } + match_len += 4; + + if (op + match_len > oend) { + return -1; + } + + uint8* match = op - off; + for (uint32 i = 0; i < match_len; ++i) { + op[i] = match[i]; + } + op += match_len; + } + + return static_cast(op - dst); +} -- cgit v1.2.3