mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-03 07:29:23 +00:00
Add Deflate() / Inflate() to redbean and fix bugs
The Compress() and Uncompress() APIs were a mistake. The functions themselves work fine, but it's a design blemish and does superfluous work. Since they were only introduced in the last few weeks, they're now deprecated and references to them have been scrubbed from the website and other documentation. Please use the new APIs since the old APIs will be removed at some point in the future. This change introduces automated Lua unit tests for the Redbean APIs. There's a few functions that were broken which have now been fixed, e.g. Underlong() and Decimate().
This commit is contained in:
parent
a18044c504
commit
fe5c475f83
12 changed files with 347 additions and 98 deletions
|
@ -101,3 +101,6 @@ o/$(MODE)/%.pyc: %.py o/$(MODE)/third_party/python/pycomp.com
|
|||
|
||||
o/$(MODE)/%.lua: %.lua o/$(MODE)/third_party/lua/luac.com
|
||||
@$(COMPILE) -ALUAC o/$(MODE)/third_party/lua/luac.com -s -o $@ $<
|
||||
|
||||
o/$(MODE)/%.lua.runs: %.lua o/$(MODE)/tool/net/redbean.com
|
||||
@$(COMPILE) -ALUA -tT$@ o/$(MODE)/tool/net/redbean.com $(LUAFLAGS) -i $<
|
||||
|
|
|
@ -44,7 +44,7 @@ char *Underlong(const char *p, size_t n, size_t *z) {
|
|||
int8_t v1[16], v2[16], vz[16];
|
||||
if (z) *z = 0;
|
||||
if (n == -1) n = p ? strlen(p) : 0;
|
||||
if ((q = r = malloc(n + 1))) {
|
||||
if ((q = r = malloc(n * 2 + 1))) {
|
||||
for (i = 0; i < n;) {
|
||||
bzero(vz, 16); /* 50x speedup for ASCII */
|
||||
while (i + 16 < n) {
|
||||
|
|
|
@ -22,6 +22,11 @@
|
|||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/unicode/unicode.h"
|
||||
|
||||
TEST(wcwidth, test) {
|
||||
ASSERT_EQ(0, wcwidth(0));
|
||||
ASSERT_EQ(-1, wcwidth(1));
|
||||
}
|
||||
|
||||
TEST(strwidth, testCjkWidesAndCombiningLowLines_withThompsonPikeEncoding) {
|
||||
/*───────────────────────────────────────────────────┬─*/
|
||||
EXPECT_EQ(20, strwidth(/**/ "𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷▒▒▒▒▒▒▒▒▒▒▒▒" /*│*/, 0));
|
||||
|
@ -63,6 +68,8 @@ TEST(wcwidth, testCjkWidesAndCombiningLowLines_widthIsNotLength) {
|
|||
|
||||
TEST(wcwidth, block) {
|
||||
EXPECT_EQ(1, wcwidth(u'▄'));
|
||||
EXPECT_EQ(0x3061, L'ち');
|
||||
EXPECT_EQ(2, wcwidth(L'ち'));
|
||||
}
|
||||
|
||||
TEST(strwidth, testTextDelimitingControlCodes_dontHaveSubstance) {
|
||||
|
|
|
@ -23,14 +23,21 @@
|
|||
#include "libc/testlib/testlib.h"
|
||||
#include "net/http/escape.h"
|
||||
|
||||
size_t n;
|
||||
|
||||
TEST(Underlong, test) {
|
||||
size_t n;
|
||||
EXPECT_BINEQ(u"e e", gc(Underlong("e\300\200e", -1, &n)));
|
||||
EXPECT_EQ(3, n);
|
||||
EXPECT_BINEQ(u"e ", gc(Underlong("e\300\200", -1, &n)));
|
||||
EXPECT_EQ(2, n);
|
||||
}
|
||||
|
||||
TEST(Underlong, testWeirdInvalidLatin1) {
|
||||
EXPECT_BINEQ(u"eÀe ", gc(Underlong("e\300e", -1, &n)));
|
||||
EXPECT_EQ(4, n);
|
||||
}
|
||||
|
||||
TEST(Underlong, testNormalText) {
|
||||
size_t n;
|
||||
EXPECT_STREQ(kHyperion, gc(Underlong(kHyperion, kHyperionSize, &n)));
|
||||
EXPECT_EQ(kHyperionSize, n);
|
||||
}
|
||||
|
|
97
test/tool/net/lfuncs_test.lua
Normal file
97
test/tool/net/lfuncs_test.lua
Normal file
|
@ -0,0 +1,97 @@
|
|||
-- Copyright 2022 Justine Alexandra Roberts Tunney
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for
|
||||
-- any purpose with or without fee is hereby granted, provided that the
|
||||
-- above copyright notice and this permission notice appear in all copies.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
-- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
-- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
-- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
-- DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
-- PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
-- TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
x = Rdtsc()
|
||||
y = Rdtsc()
|
||||
assert(y > x)
|
||||
|
||||
assert(Bsr(1) == 0)
|
||||
assert(Bsr(2) == 1)
|
||||
assert(Bsr(3) == 1)
|
||||
assert(Bsr(4) == 2)
|
||||
assert(Bsr(0x80000001) == 31)
|
||||
|
||||
assert(Bsf(1) == 0)
|
||||
assert(Bsf(2) == 1)
|
||||
assert(Bsf(3) == 0)
|
||||
assert(Bsf(4) == 2)
|
||||
assert(Bsf(0x80000001) == 0)
|
||||
|
||||
assert(Lemur64() == 0x1940efe9d47ae889)
|
||||
assert(Lemur64() == 0xd4b3103f567f9974)
|
||||
|
||||
assert(hex(0x1940efe9d47ae889) == "0x1940efe9d47ae889")
|
||||
assert(oct(0x1940efe9d47ae889) == "0145007376472436564211")
|
||||
assert(bin(0x1940efe9d47ae889) == "0b0001100101000000111011111110100111010100011110101110100010001001")
|
||||
|
||||
assert(DecodeBase64("abcdefgABCDE") == "\x69\xb7\x1d\x79\xf8\x00\x04\x20\xc4")
|
||||
assert(EncodeBase64("\x69\xb7\x1d\x79\xf8\x00\x04\x20\xc4") == "abcdefgABCDE")
|
||||
|
||||
assert(Decimate("\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\x00") == "\xff\x00\xff\x00\xff\x00")
|
||||
|
||||
assert(Underlong("hello") == "hello")
|
||||
assert(Underlong("hello\xc0\x80") == "hello\x00")
|
||||
|
||||
assert(ParseIp("x") == -1)
|
||||
assert(ParseIp("127.0.0.1") == 0x7f000001)
|
||||
|
||||
assert(GetMonospaceWidth('c') == 1)
|
||||
assert(GetMonospaceWidth(string.byte('c')) == 1)
|
||||
assert(GetMonospaceWidth(0) == 0)
|
||||
assert(GetMonospaceWidth(1) == -1)
|
||||
assert(GetMonospaceWidth(32) == 1)
|
||||
assert(GetMonospaceWidth(0x3061) == 2)
|
||||
assert(GetMonospaceWidth("ちち") == 4)
|
||||
|
||||
assert(IsPublicIp(0x08080808))
|
||||
assert(not IsPublicIp(0x0a000000))
|
||||
assert(not IsPublicIp(0x7f000001))
|
||||
|
||||
assert(not IsPrivateIp(0x08080808))
|
||||
assert(IsPrivateIp(0x0a000000))
|
||||
assert(not IsPrivateIp(0x7f000001))
|
||||
|
||||
assert(not IsLoopbackIp(0x08080808))
|
||||
assert(not IsLoopbackIp(0x0a000000))
|
||||
assert(IsLoopbackIp(0x7f000001))
|
||||
|
||||
assert(IndentLines("hi\nthere") == " hi\n there")
|
||||
assert(IndentLines("hi\nthere\n") == " hi\n there\n")
|
||||
assert(IndentLines("hi\nthere\n", 2) == " hi\n there\n")
|
||||
|
||||
assert(ParseHttpDateTime("Fri, 08 Jul 2022 16:17:43 GMT") == 1657297063)
|
||||
|
||||
assert(VisualizeControlCodes("hello\x00") == "hello␀")
|
||||
|
||||
assert(math.floor(10 * MeasureEntropy(" ") + .5) == 0)
|
||||
assert(math.floor(10 * MeasureEntropy("abcabcabcabc") + .5) == 16)
|
||||
|
||||
assert(Crc32(0, "123456789") == 0xcbf43926)
|
||||
assert(Crc32c(0, "123456789") == 0xe3069283)
|
||||
assert(Md5("hello") == "\x5d\x41\x40\x2a\xbc\x4b\x2a\x76\xb9\x71\x9d\x91\x10\x17\xc5\x92")
|
||||
assert(Sha1("hello") == "\xaa\xf4\xc6\x1d\xdc\xc5\xe8\xa2\xda\xbe\xde\x0f\x3b\x48\x2c\xd9\xae\xa9\x43\x4d")
|
||||
assert(Sha224("hello") == "\xea\x09\xae\x9c\xc6\x76\x8c\x50\xfc\xee\x90\x3e\xd0\x54\x55\x6e\x5b\xfc\x83\x47\x90\x7f\x12\x59\x8a\xa2\x41\x93")
|
||||
assert(Sha256("hello") == "\x2c\xf2\x4d\xba\x5f\xb0\xa3\x0e\x26\xe8\x3b\x2a\xc5\xb9\xe2\x9e\x1b\x16\x1e\x5c\x1f\xa7\x42\x5e\x73\x04\x33\x62\x93\x8b\x98\x24")
|
||||
assert(Sha384("hello") == "\x59\xe1\x74\x87\x77\x44\x8c\x69\xde\x6b\x80\x0d\x7a\x33\xbb\xfb\x9f\xf1\xb4\x63\xe4\x43\x54\xc3\x55\x3b\xcd\xb9\xc6\x66\xfa\x90\x12\x5a\x3c\x79\xf9\x03\x97\xbd\xf5\xf6\xa1\x3d\xe8\x28\x68\x4f")
|
||||
assert(Sha512("hello") == "\x9b\x71\xd2\x24\xbd\x62\xf3\x78\x5d\x96\xd4\x6a\xd3\xea\x3d\x73\x31\x9b\xfb\xc2\x89\x0c\xaa\xda\xe2\xdf\xf7\x25\x19\x67\x3c\xa7\x23\x23\xc3\xd9\x9b\xa5\xc1\x1d\x7c\x7a\xcc\x6e\x14\xb8\xc5\xda\x0c\x46\x63\x47\x5c\x2e\x5c\x3a\xde\xf4\x6f\x73\xbc\xde\xc0\x43")
|
||||
|
||||
assert(Deflate("hello") == "\xcbH\xcd\xc9\xc9\x07\x00")
|
||||
assert(Inflate("\xcbH\xcd\xc9\xc9\x07\x00", 5) == "hello")
|
||||
|
||||
-- deprecated compression api we wish to forget as quickly as possible
|
||||
assert(Uncompress(Compress("hello")) == "hello")
|
||||
assert(Compress("hello") == "\x05\x86\xa6\x106x\x9c\xcbH\xcd\xc9\xc9\x07\x00\x06,\x02\x15")
|
||||
assert(Compress("hello", 0) == "\x05\x86\xa6\x106x\x01\x01\x05\x00\xfa\xffhello\x06,\x02\x15")
|
||||
assert(Compress("hello", 0, true) == "x\x01\x01\x05\x00\xfa\xffhello\x06,\x02\x15")
|
52
test/tool/net/lunix_test.lua
Normal file
52
test/tool/net/lunix_test.lua
Normal file
|
@ -0,0 +1,52 @@
|
|||
-- Copyright 2022 Justine Alexandra Roberts Tunney
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for
|
||||
-- any purpose with or without fee is hereby granted, provided that the
|
||||
-- above copyright notice and this permission notice appear in all copies.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
-- WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
-- WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||
-- AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
-- DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
-- PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
-- TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
-- dup()+close()
|
||||
fd = assert(unix.dup(2))
|
||||
assert(unix.close(fd))
|
||||
|
||||
-- dup2()+close()
|
||||
assert(assert(unix.dup(2, 10)) == 10)
|
||||
assert(unix.close(10))
|
||||
|
||||
-- fork()+exit()
|
||||
if assert(unix.fork()) == 0 then
|
||||
unix.exit(42)
|
||||
end
|
||||
pid, ws = assert(unix.wait())
|
||||
assert(unix.WIFEXITED(ws))
|
||||
assert(unix.WEXITSTATUS(ws) == 42)
|
||||
|
||||
-- pledge()
|
||||
if GetHostOs() == "LINUX" then
|
||||
if assert(unix.fork()) == 0 then
|
||||
assert(unix.pledge("stdio"))
|
||||
_, err = unix.socket()
|
||||
assert(err:errno() == unix.EPERM)
|
||||
unix.exit(0)
|
||||
end
|
||||
pid, ws = assert(unix.wait())
|
||||
assert(unix.WIFEXITED(ws))
|
||||
assert(unix.WEXITSTATUS(ws) == 0)
|
||||
elseif GetHostOs() == "OPENBSD" then
|
||||
if assert(unix.fork()) == 0 then
|
||||
assert(unix.pledge("stdio"))
|
||||
unix.socket()
|
||||
unix.exit(1)
|
||||
end
|
||||
pid, ws = assert(unix.wait())
|
||||
assert(unix.WIFSIGNALED(ws))
|
||||
assert(unix.WTERMSIG(ws) == unix.SIGABRT)
|
||||
end
|
|
@ -8,70 +8,71 @@ TEST_TOOL_NET_A = o/$(MODE)/test/tool/net/net.a
|
|||
TEST_TOOL_NET_FILES := $(wildcard test/tool/net/*)
|
||||
TEST_TOOL_NET_SRCS = $(filter %.c,$(TEST_TOOL_NET_FILES))
|
||||
TEST_TOOL_NET_SRCS_TEST = $(filter %_test.c,$(TEST_TOOL_NET_SRCS))
|
||||
TEST_TOOL_NET_LUAS_TEST = $(filter %_test.lua,$(TEST_TOOL_NET_FILES))
|
||||
TEST_TOOL_NET_HDRS = $(filter %.h,$(TEST_TOOL_NET_FILES))
|
||||
TEST_TOOL_NET_COMS = $(TEST_TOOL_NET_OBJS:%.o=%.com)
|
||||
TEST_TOOL_NET_COMS = $(TEST_TOOL_NET_SRCS:%.c=o/$(MODE)/%.com)
|
||||
|
||||
TEST_TOOL_NET_OBJS = \
|
||||
$(TEST_TOOL_NET_SRCS:%.c=o/$(MODE)/%.o) \
|
||||
TEST_TOOL_NET_OBJS = \
|
||||
$(TEST_TOOL_NET_SRCS:%.c=o/$(MODE)/%.o) \
|
||||
o/$(MODE)/tool/net/redbean.com.zip.o
|
||||
|
||||
TEST_TOOL_NET_BINS = \
|
||||
$(TEST_TOOL_NET_COMS) \
|
||||
TEST_TOOL_NET_BINS = \
|
||||
$(TEST_TOOL_NET_COMS) \
|
||||
$(TEST_TOOL_NET_COMS:%=%.dbg)
|
||||
|
||||
TEST_TOOL_NET_TESTS = \
|
||||
TEST_TOOL_NET_TESTS = \
|
||||
$(TEST_TOOL_NET_SRCS_TEST:%.c=o/$(MODE)/%.com.ok)
|
||||
|
||||
TEST_TOOL_NET_CHECKS = \
|
||||
$(TEST_TOOL_NET_HDRS:%=o/$(MODE)/%.ok) \
|
||||
$(TEST_TOOL_NET_SRCS_TEST:%.c=o/$(MODE)/%.com.runs)
|
||||
TEST_TOOL_NET_CHECKS = \
|
||||
$(TEST_TOOL_NET_HDRS:%=o/$(MODE)/%.ok) \
|
||||
$(TEST_TOOL_NET_SRCS_TEST:%.c=o/$(MODE)/%.com.runs) \
|
||||
$(TEST_TOOL_NET_LUAS_TEST:%.lua=o/$(MODE)/%.lua.runs)
|
||||
|
||||
TEST_TOOL_NET_DIRECTDEPS = \
|
||||
LIBC_CALLS \
|
||||
LIBC_FMT \
|
||||
LIBC_INTRIN \
|
||||
LIBC_LOG \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_RAND \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_SOCK \
|
||||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
LIBC_TESTLIB \
|
||||
LIBC_UNICODE \
|
||||
LIBC_X \
|
||||
LIBC_ZIPOS \
|
||||
THIRD_PARTY_REGEX \
|
||||
THIRD_PARTY_MBEDTLS \
|
||||
TEST_TOOL_NET_DIRECTDEPS = \
|
||||
LIBC_CALLS \
|
||||
LIBC_FMT \
|
||||
LIBC_INTRIN \
|
||||
LIBC_LOG \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_RAND \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_SOCK \
|
||||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
LIBC_TESTLIB \
|
||||
LIBC_UNICODE \
|
||||
LIBC_X \
|
||||
LIBC_ZIPOS \
|
||||
THIRD_PARTY_REGEX \
|
||||
THIRD_PARTY_MBEDTLS \
|
||||
THIRD_PARTY_SQLITE3
|
||||
|
||||
TEST_TOOL_NET_DEPS := \
|
||||
TEST_TOOL_NET_DEPS := \
|
||||
$(call uniq,$(foreach x,$(TEST_TOOL_NET_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(TEST_TOOL_NET_A): \
|
||||
test/tool/net/ \
|
||||
$(TEST_TOOL_NET_A).pkg \
|
||||
$(TEST_TOOL_NET_A): \
|
||||
test/tool/net/ \
|
||||
$(TEST_TOOL_NET_A).pkg \
|
||||
$(TEST_TOOL_NET_OBJS)
|
||||
|
||||
$(TEST_TOOL_NET_A).pkg: \
|
||||
$(TEST_TOOL_NET_OBJS) \
|
||||
$(TEST_TOOL_NET_A).pkg: \
|
||||
$(TEST_TOOL_NET_OBJS) \
|
||||
$(foreach x,$(TEST_TOOL_NET_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/test/tool/net/%.com.dbg: \
|
||||
$(TEST_TOOL_NET_DEPS) \
|
||||
$(TEST_TOOL_NET_A) \
|
||||
o/$(MODE)/test/tool/net/%.o \
|
||||
$(TEST_TOOL_NET_A).pkg \
|
||||
$(LIBC_TESTMAIN) \
|
||||
$(CRT) \
|
||||
o/$(MODE)/test/tool/net/%.com.dbg: \
|
||||
$(TEST_TOOL_NET_DEPS) \
|
||||
$(TEST_TOOL_NET_A) \
|
||||
o/$(MODE)/test/tool/net/%.o \
|
||||
$(TEST_TOOL_NET_A).pkg \
|
||||
$(LIBC_TESTMAIN) \
|
||||
$(CRT) \
|
||||
$(APE_NO_MODIFY_SELF)
|
||||
@$(APELINK)
|
||||
|
||||
.PHONY: o/$(MODE)/test/tool/net
|
||||
o/$(MODE)/test/tool/net: \
|
||||
$(TEST_TOOL_NET_BINS) \
|
||||
o/$(MODE)/test/tool/net: \
|
||||
$(TEST_TOOL_NET_BINS) \
|
||||
$(TEST_TOOL_NET_CHECKS)
|
||||
|
|
|
@ -624,7 +624,11 @@
|
|||
((eq major-mode 'sh-mode)
|
||||
(compile (format "sh %s" file)))
|
||||
((eq major-mode 'lua-mode)
|
||||
(compile (format "lua.com %s" file)))
|
||||
(let* ((mode (cosmo--make-mode arg))
|
||||
(redbean (format "%s/o/%s/tool/net/redbean.com" root mode)))
|
||||
(if (file-executable-p redbean)
|
||||
(compile (format "%s -i %s" redbean file))
|
||||
(compile (format "lua.com %s" file)))))
|
||||
((and (eq major-mode 'python-mode)
|
||||
(cosmo-startswith "third_party/python/Lib/test/" file))
|
||||
(let ((mode (cosmo--make-mode arg)))
|
||||
|
|
|
@ -1359,8 +1359,8 @@ FUNCTIONS
|
|||
Shrinks byte buffer in half using John Costella's magic kernel.
|
||||
This downscales data 2x using an eight-tap convolution, e.g.
|
||||
|
||||
>: Decimate(b'\\xff\\xff\\x00\\x00\\xff\\xff\\x00\\x00\\xff\\xff\\x00\\x00')
|
||||
b'\\xff\\x00\\xff\\x00\\xff\\x00'
|
||||
>: Decimate('\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\x00')
|
||||
"\xff\x00\xff\x00\xff\x00"
|
||||
|
||||
This is very fast if SSSE3 is available (Intel 2004+ / AMD 2011+).
|
||||
|
||||
|
@ -1369,56 +1369,40 @@ FUNCTIONS
|
|||
the density of information. Cryptographic random should be in
|
||||
the ballpark of 7.9 whereas plaintext will be more like 4.5.
|
||||
|
||||
Compress(uncompdata:str[, level:int[, raw:bool]]) → compdata:str
|
||||
Deflate(uncompressed:str[, level:int])
|
||||
├─→ compressed:str
|
||||
└─→ nil, error:str
|
||||
|
||||
Compresses data using DEFLATE algorithm. The compression
|
||||
format here is defined to be quick and handy for things like
|
||||
database fields. For example:
|
||||
Compresses data.
|
||||
|
||||
>: Compress('hello')
|
||||
"\x05\x86\xa6\x106x\x9c\xcbH\xcd\xc9\xc9\x07\x00\x06,\x02\x15"
|
||||
>: Uncompress(Compress('hello'))
|
||||
>: Deflate("hello")
|
||||
"\xcbH\xcd\xc9\xc9\x07\x00"
|
||||
>: Inflate("\xcbH\xcd\xc9\xc9\x07\x00", 5)
|
||||
"hello"
|
||||
|
||||
The binary wire format is defined as follows:
|
||||
|
||||
1. uleb64 uncompressed byte size (1 to 10 bytes)
|
||||
2. uint32_t crc32 (4 bytes; zlib polynomial)
|
||||
3. data (created by zlib compress function)
|
||||
The output format is raw DEFLATE that's suitable for embedding
|
||||
into formats like a ZIP file. It's recommended that, like ZIP,
|
||||
you also store separately a Crc32() checksum in addition to
|
||||
the original uncompressed size.
|
||||
|
||||
`level` is the compression level, which defaults to 7. The max
|
||||
is 9. Lower numbers go faster. Higher numbers go slower, but
|
||||
have better compression ratios.
|
||||
is 9. Lower numbers go faster (4 for instance is a sweet spot)
|
||||
and higher numbers go slower but have better compression.
|
||||
|
||||
`raw` may be set to true if you only want `data` (3) to be
|
||||
returned. In this case, it's assumed the caller will take
|
||||
responsibility for storing the length (and optionall crc)
|
||||
separately. See the redbean Crc32() API.
|
||||
Inflate(compressed:str, maxoutsize:int)
|
||||
├─→ uncompressed:str
|
||||
└─→ nil, error:str
|
||||
|
||||
>: a = 'hello'
|
||||
>: b = Compress(a, 9, true)
|
||||
>: Uncompress(b, #a)
|
||||
"hello"
|
||||
Decompresses data.
|
||||
|
||||
Uncompress(compdata:str[, uncomplen:int]) → uncompdata:str
|
||||
This function performs the inverse of Deflate(). It's
|
||||
recommended that you perform a Crc32() check on the output
|
||||
string after this function succeeds.
|
||||
|
||||
Uncompresses data using DEFLATE algorithm. This applies the
|
||||
inverse transform of the Compress() function. See its docs for
|
||||
further details on usage and encoding.
|
||||
|
||||
This function throws exceptions in the event that the value
|
||||
couldn't be decoded. There's a crc32 check to make our check
|
||||
of validity iron-clad. It's implemented using Intel CLMUL so
|
||||
it has ludicrous speed performance as well.
|
||||
|
||||
If you used the `raw` parameter when calling Compress() i.e.
|
||||
`compdata` doesn't have the redbean header described above,
|
||||
then the `uncomplen` parameter may be supplied. In that case
|
||||
your data is handed over directly to zlib `uncompress()`. In
|
||||
this case an exception will be raised if the value couldn't be
|
||||
decoded, or if the resulting length differed from the supplied
|
||||
length. It's recommended that Crc32() check still be performed
|
||||
manually after using this method.
|
||||
`maxoutsize` is the uncompressed size, which should be known.
|
||||
However, it is permissable (although not advised) to specify
|
||||
some large number in which case (on success) the byte length
|
||||
of the output string may be less than `maxoutsize`.
|
||||
|
||||
Benchmark(func[, count[, maxattempts]])
|
||||
└─→ nanos:real, ticks:int, overhead-ticks:int, tries:int
|
||||
|
|
|
@ -163,6 +163,7 @@ int LuaDecimate(lua_State *L) {
|
|||
s = luaL_checklstring(L, 1, &n);
|
||||
m = ROUNDUP(n, 16);
|
||||
p = luaL_buffinitsize(L, &buf, m);
|
||||
memcpy(p, s, n);
|
||||
bzero(p + n, m - n);
|
||||
cDecimate2xUint8x8(m, (unsigned char *)p,
|
||||
(signed char[8]){-1, -3, 3, 17, 17, 3, -3, -1});
|
||||
|
@ -355,7 +356,7 @@ int LuaIndentLines(lua_State *L) {
|
|||
|
||||
int LuaGetMonospaceWidth(lua_State *L) {
|
||||
int w;
|
||||
if (lua_isinteger(L, 1)) {
|
||||
if (lua_isnumber(L, 1)) {
|
||||
w = wcwidth(lua_tointeger(L, 1));
|
||||
} else if (lua_isstring(L, 1)) {
|
||||
w = strwidth(luaL_checkstring(L, 1), luaL_optinteger(L, 2, 0) & 7);
|
||||
|
@ -766,9 +767,9 @@ int LuaCompress(lua_State *L) {
|
|||
}
|
||||
|
||||
int LuaUncompress(lua_State *L) {
|
||||
int rc;
|
||||
char *q;
|
||||
uint32_t crc;
|
||||
int rc, level;
|
||||
const char *p;
|
||||
luaL_Buffer buf;
|
||||
size_t n, m, len;
|
||||
|
@ -797,3 +798,89 @@ int LuaUncompress(lua_State *L) {
|
|||
luaL_pushresultsize(&buf, m);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// unix.deflate(uncompressed:str[, level:int])
|
||||
// ├─→ compressed:str
|
||||
// └─→ nil, error:str
|
||||
int LuaDeflate(lua_State *L) {
|
||||
char *out;
|
||||
z_stream zs;
|
||||
int rc, level;
|
||||
const char *in;
|
||||
luaL_Buffer buf;
|
||||
size_t insize, outsize, actualoutsize;
|
||||
in = luaL_checklstring(L, 1, &insize);
|
||||
level = luaL_optinteger(L, 2, Z_DEFAULT_COMPRESSION);
|
||||
outsize = compressBound(insize);
|
||||
out = luaL_buffinitsize(L, &buf, outsize);
|
||||
|
||||
zs.next_in = (const uint8_t *)in;
|
||||
zs.avail_in = insize;
|
||||
zs.next_out = (uint8_t *)out;
|
||||
zs.avail_out = outsize;
|
||||
zs.zalloc = Z_NULL;
|
||||
zs.zfree = Z_NULL;
|
||||
|
||||
if ((rc = deflateInit2(&zs, level, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL,
|
||||
Z_DEFAULT_STRATEGY)) != Z_OK) {
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "%s() failed: %d", "deflateInit2", rc);
|
||||
return 2;
|
||||
}
|
||||
|
||||
rc = deflate(&zs, Z_FINISH);
|
||||
actualoutsize = outsize - zs.avail_out;
|
||||
deflateEnd(&zs);
|
||||
|
||||
if (rc != Z_STREAM_END) {
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "%s() failed: %d", "deflate", rc);
|
||||
return 2;
|
||||
}
|
||||
|
||||
luaL_pushresultsize(&buf, actualoutsize);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// unix.inflate(compressed:str, maxoutsize:int)
|
||||
// ├─→ uncompressed:str
|
||||
// └─→ nil, error:str
|
||||
int LuaInflate(lua_State *L) {
|
||||
int rc;
|
||||
char *out;
|
||||
z_stream zs;
|
||||
const char *in;
|
||||
luaL_Buffer buf;
|
||||
size_t insize, outsize, actualoutsize;
|
||||
in = luaL_checklstring(L, 1, &insize);
|
||||
outsize = luaL_checkinteger(L, 2);
|
||||
out = luaL_buffinitsize(L, &buf, outsize);
|
||||
|
||||
zs.next_in = (const uint8_t *)in;
|
||||
zs.avail_in = insize;
|
||||
zs.total_in = insize;
|
||||
zs.next_out = (uint8_t *)out;
|
||||
zs.avail_out = outsize;
|
||||
zs.total_out = outsize;
|
||||
zs.zalloc = Z_NULL;
|
||||
zs.zfree = Z_NULL;
|
||||
|
||||
if ((rc = inflateInit2(&zs, -MAX_WBITS)) != Z_OK) {
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "%s() failed: %d", "inflateInit2", rc);
|
||||
return 2;
|
||||
}
|
||||
|
||||
rc = inflate(&zs, Z_FINISH);
|
||||
actualoutsize = outsize - zs.avail_out;
|
||||
inflateEnd(&zs);
|
||||
|
||||
if (rc != Z_STREAM_END) {
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "%s() failed: %d", "inflate", rc);
|
||||
return 2;
|
||||
}
|
||||
|
||||
luaL_pushresultsize(&buf, actualoutsize);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ int LuaCrc32c(lua_State *);
|
|||
int LuaDecimate(lua_State *);
|
||||
int LuaDecodeBase64(lua_State *);
|
||||
int LuaDecodeLatin1(lua_State *);
|
||||
int LuaDeflate(lua_State *);
|
||||
int LuaEncodeBase64(lua_State *);
|
||||
int LuaEncodeLatin1(lua_State *);
|
||||
int LuaEscapeFragment(lua_State *);
|
||||
|
@ -48,6 +49,7 @@ int LuaGetTime(lua_State *);
|
|||
int LuaHasControlCodes(lua_State *);
|
||||
int LuaHex(lua_State *);
|
||||
int LuaIndentLines(lua_State *);
|
||||
int LuaInflate(lua_State *);
|
||||
int LuaIsAcceptableHost(lua_State *);
|
||||
int LuaIsAcceptablePath(lua_State *);
|
||||
int LuaIsAcceptablePort(lua_State *);
|
||||
|
|
|
@ -3896,7 +3896,8 @@ static int LuaFetch(lua_State *L) {
|
|||
freeaddrinfo(addr), addr = 0;
|
||||
if (rc == -1) {
|
||||
close(sock);
|
||||
return LuaNilError(L, "connect(%s:%s) error: %s", host, port, strerror(errno));
|
||||
return LuaNilError(L, "connect(%s:%s) error: %s", host, port,
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
#ifndef UNSECURE
|
||||
|
@ -4978,6 +4979,7 @@ static bool LuaRunAsset(const char *path, bool mandatory) {
|
|||
// <SORTED>
|
||||
// list of functions that can't be run from the repl
|
||||
static const char *const kDontAutoComplete[] = {
|
||||
"Compress", // deprecated
|
||||
"GetBody", //
|
||||
"GetClientAddr", //
|
||||
"GetClientFd", //
|
||||
|
@ -5037,6 +5039,7 @@ static const char *const kDontAutoComplete[] = {
|
|||
"SetCookie", //
|
||||
"SetHeader", //
|
||||
"SslInit", // TODO
|
||||
"Uncompress", // deprecated
|
||||
"Write", //
|
||||
};
|
||||
// </SORTED>
|
||||
|
@ -5052,6 +5055,7 @@ static const luaL_Reg kLuaFuncs[] = {
|
|||
{"Decimate", LuaDecimate}, //
|
||||
{"DecodeBase64", LuaDecodeBase64}, //
|
||||
{"DecodeLatin1", LuaDecodeLatin1}, //
|
||||
{"Deflate", LuaDeflate}, //
|
||||
{"EncodeBase64", LuaEncodeBase64}, //
|
||||
{"EncodeJson", LuaEncodeJson}, //
|
||||
{"EncodeLatin1", LuaEncodeLatin1}, //
|
||||
|
@ -5113,11 +5117,12 @@ static const luaL_Reg kLuaFuncs[] = {
|
|||
{"HasParam", LuaHasParam}, //
|
||||
{"HidePath", LuaHidePath}, //
|
||||
{"IndentLines", LuaIndentLines}, //
|
||||
{"Inflate", LuaInflate}, //
|
||||
{"IsAcceptableHost", LuaIsAcceptableHost}, //
|
||||
{"IsAcceptablePath", LuaIsAcceptablePath}, //
|
||||
{"IsAcceptablePort", LuaIsAcceptablePort}, //
|
||||
{"IsClientUsingSsl", LuaIsClientUsingSsl}, //
|
||||
{"IsAssetCompressed", LuaIsAssetCompressed}, //
|
||||
{"IsClientUsingSsl", LuaIsClientUsingSsl}, //
|
||||
{"IsDaemon", LuaIsDaemon}, //
|
||||
{"IsHeaderRepeatable", LuaIsHeaderRepeatable}, //
|
||||
{"IsHiddenPath", LuaIsHiddenPath}, //
|
||||
|
@ -5333,7 +5338,7 @@ static void DisableRawMode(void) {
|
|||
++__strace;
|
||||
}
|
||||
|
||||
static void LuaInterpreter(lua_State *L) {
|
||||
static int LuaInterpreter(lua_State *L) {
|
||||
int i, n, sig, status;
|
||||
const char *script;
|
||||
if (optind < __argc) {
|
||||
|
@ -5349,7 +5354,7 @@ static void LuaInterpreter(lua_State *L) {
|
|||
status = lua_runchunk(L, n, LUA_MULTRET);
|
||||
TRACE_END;
|
||||
}
|
||||
lua_report(L, status);
|
||||
return lua_report(L, status);
|
||||
} else {
|
||||
lua_repl_blocking = true;
|
||||
lua_repl_completions_callback = HandleCompletions;
|
||||
|
@ -5384,6 +5389,7 @@ static void LuaInterpreter(lua_State *L) {
|
|||
if ((sig = linenoiseGetInterrupt())) {
|
||||
raise(sig);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5392,8 +5398,7 @@ static void LuaInit(void) {
|
|||
lua_State *L = GL;
|
||||
LuaSetArgv(L);
|
||||
if (interpretermode) {
|
||||
LuaInterpreter(L);
|
||||
exit(0);
|
||||
exit(LuaInterpreter(L));
|
||||
}
|
||||
if (LuaRunAsset("/.init.lua", true)) {
|
||||
hasonhttprequest = IsHookDefined("OnHttpRequest");
|
||||
|
|
Loading…
Add table
Reference in a new issue