From 3549efad7a72990de8bb7c4ef87db2306a85bab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Thu, 18 May 2023 16:09:57 +0800 Subject: [PATCH 01/35] fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5a1d4db..dfbeb73 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ echo -n "1234567" | base16384 -e - - | iconv -f utf-16be -t utf-8 3. Decode simple text 简单文本解码 ```bash -echo -n "婌焳廔萷" | iconv -f utf-8 -t utf-16be | ./base16384 -d - - +echo -n "婌焳廔萷" | iconv -f utf-8 -t utf-16be | base16384 -d - - 1234567 ``` From da390aa973dc7aab0a7d2e1a94e4e74aa4823d9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Sun, 23 Jul 2023 22:52:10 +0800 Subject: [PATCH 02/35] fix: 32bit be decoding --- CMakeLists.txt | 2 +- base1432.c | 6 +++++- base16384.c | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 57e01ac..e56b1f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8.12) if (POLICY CMP0048) cmake_policy(SET CMP0048 NEW) endif (POLICY CMP0048) -project(base16384 VERSION 2.2.3) +project(base16384 VERSION 2.2.4) add_executable(base16384_b base16384.c) diff --git a/base1432.c b/base1432.c index faca57e..86d9080 100644 --- a/base1432.c +++ b/base1432.c @@ -194,7 +194,11 @@ int base16384_decode(const char* data, int dlen, char* buf, int blen) { if(offset--) { buf[i] = (sum & 0x0f000000) >> 20; // 这里有读取越界 - sum = vals[n]; + #ifdef WORDS_BIGENDIAN + sum = __builtin_bswap32(vals[n]); + #else + sum = vals[n]; + #endif sum -= 0x0000004e; buf[i++] |= (sum & 0x0000003c) >> 2; if(offset--) { diff --git a/base16384.c b/base16384.c index 73e2ae0..e6e04b0 100644 --- a/base16384.c +++ b/base16384.c @@ -39,7 +39,7 @@ unsigned long get_start_ms() { #endif static void print_usage() { - puts("Copyright (c) 2022-2023 Fumiama Minamoto.\nBase16384 2.2.3 (May 18th 2023). Usage:"); + puts("Copyright (c) 2022-2023 Fumiama Minamoto.\nBase16384 2.2.4 (July 23rd 2023). Usage:"); puts("base16384 [-edt] [inputfile] [outputfile]"); puts(" -e\t\tencode"); puts(" -d\t\tdecode"); From 12f669ef173daab63867864567862b9341e1f46e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BF=98=E5=BF=A7=E5=8C=97=E8=90=B1=E8=8D=89?= Date: Thu, 27 Jul 2023 12:48:33 +0800 Subject: [PATCH 03/35] chore: add Rust alternative (#18) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dfbeb73..74d9218 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # base16384 > **Note**: This project used the awesome cross-platform binary compiling tool [cosmopolitan](https://github.com/jart/cosmopolitan) -> Alternatives: [Go](https://github.com/fumiama/go-base16384), [Python](https://github.com/synodriver/pybase16384), [Android](https://github.com/fumiama/android-base16384), [TypeScript](https://github.com/shigma/base16384.js), [Lua(binding)](https://github.com/synodriver/lua-base16384), [Lua(pure)](https://github.com/Yiwen-Chan/base16384), [C#](https://github.com/lc6464/Base16384Coder-Console) +> Alternatives: [Go](https://github.com/fumiama/go-base16384), [Python](https://github.com/synodriver/pybase16384), [Android](https://github.com/fumiama/android-base16384), [TypeScript](https://github.com/shigma/base16384.js), [Lua(binding)](https://github.com/synodriver/lua-base16384), [Lua(pure)](https://github.com/Yiwen-Chan/base16384), [C#](https://github.com/lc6464/Base16384Coder-Console), [Rust](https://github.com/Wybxc/base16384-rs) Encode binary file to printable utf16be, and vice versa. From 7897031513903b3f4980cb16be8dfea066dc8386 Mon Sep 17 00:00:00 2001 From: LC <64722907+lc6464@users.noreply.github.com> Date: Thu, 24 Aug 2023 16:55:30 +0800 Subject: [PATCH 04/35] Update C# Link (#20) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 74d9218..41f1a88 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # base16384 > **Note**: This project used the awesome cross-platform binary compiling tool [cosmopolitan](https://github.com/jart/cosmopolitan) -> Alternatives: [Go](https://github.com/fumiama/go-base16384), [Python](https://github.com/synodriver/pybase16384), [Android](https://github.com/fumiama/android-base16384), [TypeScript](https://github.com/shigma/base16384.js), [Lua(binding)](https://github.com/synodriver/lua-base16384), [Lua(pure)](https://github.com/Yiwen-Chan/base16384), [C#](https://github.com/lc6464/Base16384Coder-Console), [Rust](https://github.com/Wybxc/base16384-rs) +> Alternatives: [Go](https://github.com/fumiama/go-base16384), [Python](https://github.com/synodriver/pybase16384), [Android](https://github.com/fumiama/android-base16384), [TypeScript](https://github.com/shigma/base16384.js), [Lua(binding)](https://github.com/synodriver/lua-base16384), [Lua(pure)](https://github.com/Yiwen-Chan/base16384), [C#](https://github.com/lc6464/Base16384.Net), [Rust](https://github.com/Wybxc/base16384-rs) Encode binary file to printable utf16be, and vice versa. From 5dc272b8b7784228d31ce89e41e52034bd5e91c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Fri, 25 Aug 2023 21:53:18 +0800 Subject: [PATCH 05/35] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E4=BF=AE=E5=A4=8D#19?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除未使用的参数 int blen - 完善文档、注释 - 完善文件名错误检测 - 修复 encbuf, decbuf 处理逻辑 --- CMakeLists.txt | 2 +- base1432.c | 6 +++--- base1464.c | 6 +++--- base16384.1 | 13 +++++++++++-- base16384.c | 21 ++++++++++++--------- base16384.h | 29 +++++++++++++++++------------ file.c | 49 ++++++++++++++++++++++--------------------------- 7 files changed, 69 insertions(+), 57 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e56b1f5..f75817f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8.12) if (POLICY CMP0048) cmake_policy(SET CMP0048 NEW) endif (POLICY CMP0048) -project(base16384 VERSION 2.2.4) +project(base16384 VERSION 2.2.5) add_executable(base16384_b base16384.c) diff --git a/base1432.c b/base1432.c index 86d9080..ac09987 100644 --- a/base1432.c +++ b/base1432.c @@ -1,6 +1,6 @@ /* base1432.c * This file is part of the base16384 distribution (https://github.com/fumiama/base16384). - * Copyright (c) 2022 Fumiama Minamoto. + * Copyright (c) 2022-2023 Fumiama Minamoto. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -62,7 +62,7 @@ // #define DEBUG -int base16384_encode(const char* data, int dlen, char* buf, int blen) { +int base16384_encode(const char* data, int dlen, char* buf) { int outlen = dlen / 7 * 8; int offset = dlen % 7; switch(offset) { // 算上偏移标志字符占用的2字节 @@ -140,7 +140,7 @@ int base16384_encode(const char* data, int dlen, char* buf, int blen) { return outlen; } -int base16384_decode(const char* data, int dlen, char* buf, int blen) { +int base16384_decode(const char* data, int dlen, char* buf) { int outlen = dlen; int offset = 0; if(data[dlen-2] == '=') { diff --git a/base1464.c b/base1464.c index a29b002..73b0432 100644 --- a/base1464.c +++ b/base1464.c @@ -1,6 +1,6 @@ /* base1464.c * This file is part of the base16384 distribution (https://github.com/fumiama/base16384). - * Copyright (c) 2022 Fumiama Minamoto. + * Copyright (c) 2022-2023 Fumiama Minamoto. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -62,7 +62,7 @@ // #define DEBUG -int base16384_encode(const char* data, int dlen, char* buf, int blen) { +int base16384_encode(const char* data, int dlen, char* buf) { int outlen = dlen / 7 * 8; int offset = dlen % 7; switch(offset) { // 算上偏移标志字符占用的2字节 @@ -136,7 +136,7 @@ int base16384_encode(const char* data, int dlen, char* buf, int blen) { return outlen; } -int base16384_decode(const char* data, int dlen, char* buf, int blen) { +int base16384_decode(const char* data, int dlen, char* buf) { int outlen = dlen; int offset = 0; if(data[dlen-2] == '=') { diff --git a/base16384.1 b/base16384.1 index 7630b8c..c8e0921 100644 --- a/base16384.1 +++ b/base16384.1 @@ -3,7 +3,7 @@ base16384 \- Encode binary files to printable utf16be .SH SYNOPSIS .B base16384 --[e|d] <\fIinputfile\fR> <\fIoutputfile\fR> +-[e|d|t] <\fIinputfile\fR> <\fIoutputfile\fR> .SH DESCRIPTION .LP There are @@ -29,6 +29,12 @@ to \fB\-e\fR Read data from \fIinputfile\fR and encode them into \fIoutputfile\fR. .TP 0.5i +\fB\-d\fR +Read data from \fIinputfile\fR and decode them into \fIoutputfile\fR. +.TP 0.5i +\fB\-t\fR +Show spend time. +.TP 0.5i \fBinputfile\fR An absolute or relative file path. Specially, pass - to read from stdin. .TP 0.5i @@ -59,6 +65,9 @@ Map input file error. .TP 0.5i \fB7\fR Write file error in mmap. +.TP 0.5i +\fB8\fR +Invalid input/output filename. .SH "SEE ALSO" https://github.com/fumiama/base16384 .SH BUGS @@ -68,7 +77,7 @@ on github. .SH AUTHOR This manual page contributed by Fumiama Minamoto. .SH "COPYRIGHT" -Copyright \(co 2022, Fumiama Minamoto +Copyright \(co 2022-2023, Fumiama Minamoto This file is part of .IR "base16384" . .LP diff --git a/base16384.c b/base16384.c index e6e04b0..d3c4b7b 100644 --- a/base16384.c +++ b/base16384.c @@ -1,6 +1,6 @@ /* base16384.c * This file is part of the base16384 distribution (https://github.com/fumiama/base16384). - * Copyright (c) 2022 Fumiama Minamoto. + * Copyright (c) 2022-2023 Fumiama Minamoto. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,7 +39,7 @@ unsigned long get_start_ms() { #endif static void print_usage() { - puts("Copyright (c) 2022-2023 Fumiama Minamoto.\nBase16384 2.2.4 (July 23rd 2023). Usage:"); + puts("Copyright (c) 2022-2023 Fumiama Minamoto.\nBase16384 2.2.5 (August 25th 2023). Usage:"); puts("base16384 [-edt] [inputfile] [outputfile]"); puts(" -e\t\tencode"); puts(" -d\t\tdecode"); @@ -97,15 +97,18 @@ int main(int argc, char** argv) { printf("spend time: %lums\n", get_start_ms() - t); #endif } + #define print_base16384_err(n) case base16384_err_##n: perror("base16384_err_"#n); break if(exitstat) switch(exitstat) { - case base16384_err_get_file_size: perror("base16384_err_get_file_size"); break; - case base16384_err_fopen_output_file: perror("base16384_err_fopen_output_file"); break; - case base16384_err_fopen_input_file: perror("base16384_err_fopen_input_file"); break; - case base16384_err_write_file: perror("base16384_err_write_file"); break; - case base16384_err_open_input_file: perror("base16384_err_open_input_file"); break; - case base16384_err_map_input_file: perror("base16384_err_map_input_file"); break; - case base16384_err_read_file: perror("base16384_err_read_file"); break; + print_base16384_err(get_file_size); + print_base16384_err(fopen_output_file); + print_base16384_err(fopen_input_file); + print_base16384_err(write_file); + print_base16384_err(open_input_file); + print_base16384_err(map_input_file); + print_base16384_err(read_file); + print_base16384_err(invalid_file_name); default: perror("base16384"); break; } + #undef print_base16384_err return exitstat; } diff --git a/base16384.h b/base16384.h index 9faa14d..f4bb985 100644 --- a/base16384.h +++ b/base16384.h @@ -3,7 +3,7 @@ /* base16384.h * This file is part of the base16384 distribution (https://github.com/fumiama/base16384). - * Copyright (c) 2022 Fumiama Minamoto. + * Copyright (c) 2022-2023 Fumiama Minamoto. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,22 +24,27 @@ #include #endif +#define define_base16384_err_t(n) base16384_err_##n + // base16384_err_t is the return value of base16384_en/decode_file enum base16384_err_t { - base16384_err_ok, - base16384_err_get_file_size, - base16384_err_fopen_output_file, - base16384_err_fopen_input_file, - base16384_err_write_file, - base16384_err_open_input_file, - base16384_err_map_input_file, - base16384_err_read_file, + define_base16384_err_t(ok), + define_base16384_err_t(get_file_size), + define_base16384_err_t(fopen_output_file), + define_base16384_err_t(fopen_input_file), + define_base16384_err_t(write_file), + define_base16384_err_t(open_input_file), + define_base16384_err_t(map_input_file), + define_base16384_err_t(read_file), + define_base16384_err_t(invalid_file_name), }; // base16384_err_t is the return value of base16384_en/decode_file typedef enum base16384_err_t base16384_err_t; +#undef define_base16384_err_t + #define BASE16384_ENCBUFSZ (BUFSIZ*1024/7*7) -#define BASE16384_DECBUFSZ (BUFSIZ*1024/8*8+2) +#define BASE16384_DECBUFSZ (BUFSIZ*1024/8*8+16) // base16384_encode_len calc min buf size to fill encode result static inline int base16384_encode_len(int dlen) { @@ -75,10 +80,10 @@ static inline int base16384_decode_len(int dlen, int offset) { } // base16384_encode encodes data and write result into buf -int base16384_encode(const char* data, int dlen, char* buf, int blen); +int base16384_encode(const char* data, int dlen, char* buf); // base16384_decode decodes data and write result into buf -int base16384_decode(const char* data, int dlen, char* buf, int blen); +int base16384_decode(const char* data, int dlen, char* buf); // base16384_encode_file encodes input file to output file. // use `-` to specify stdin/stdout diff --git a/file.c b/file.c index ff5bc09..dc58810 100644 --- a/file.c +++ b/file.c @@ -1,6 +1,6 @@ /* file.c * This file is part of the base16384 distribution (https://github.com/fumiama/base16384). - * Copyright (c) 2022 Fumiama Minamoto. + * Copyright (c) 2022-2023 Fumiama Minamoto. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #ifdef _WIN32 @@ -48,6 +49,7 @@ base16384_err_t base16384_encode_file(const char* input, const char* output, cha off_t inputsize; FILE* fp = NULL; FILE* fpo; + if(!input || !output || strlen(input) <= 0 || strlen(output) <= 0) return base16384_err_invalid_file_name; if(is_standard_io(input)) { // read from stdin inputsize = 0; fp = stdin; @@ -59,8 +61,8 @@ base16384_err_t base16384_encode_file(const char* input, const char* output, cha if(!fpo) { return base16384_err_fopen_output_file; } - if(!inputsize || inputsize > BUFSIZ*1024) { // stdin or big file, use encbuf & fread - inputsize = BUFSIZ*1024/7*7; + if(!inputsize || inputsize > BASE16384_ENCBUFSZ) { // stdin or big file, use encbuf & fread + inputsize = BASE16384_ENCBUFSZ/8*8; #ifdef _WIN32 } #endif @@ -69,12 +71,11 @@ base16384_err_t base16384_encode_file(const char* input, const char* output, cha return base16384_err_fopen_input_file; } - int outputsize = base16384_encode_len(inputsize)+16; size_t cnt = 0; fputc(0xFE, fpo); fputc(0xFF, fpo); while((cnt = fread(encbuf, sizeof(char), inputsize, fp)) > 0) { - int n = base16384_encode(encbuf, cnt, decbuf, outputsize); + int n = base16384_encode(encbuf, cnt, decbuf); if(fwrite(decbuf, n, 1, fpo) <= 0) { return base16384_err_write_file; } @@ -87,14 +88,13 @@ base16384_err_t base16384_encode_file(const char* input, const char* output, cha if(fd < 0) { return base16384_err_open_input_file; } - char *input_file = mmap(NULL, (size_t)inputsize, PROT_READ, MAP_PRIVATE, fd, 0); + char *input_file = mmap(NULL, (size_t)inputsize+16, PROT_READ, MAP_PRIVATE, fd, 0); if(input_file == MAP_FAILED) { return base16384_err_map_input_file; } - int outputsize = base16384_encode_len(inputsize)+16; fputc(0xFE, fpo); fputc(0xFF, fpo); - int n = base16384_encode(input_file, (int)inputsize, decbuf, outputsize); + int n = base16384_encode(input_file, (int)inputsize, decbuf); if(fwrite(decbuf, n, 1, fpo) <= 0) { return base16384_err_write_file; } @@ -113,13 +113,12 @@ base16384_err_t base16384_encode_fp(FILE* input, FILE* output, char* encbuf, cha if(!output) { return base16384_err_fopen_output_file; } - off_t inputsize = BUFSIZ*1024/7*7; - int outputsize = base16384_encode_len(inputsize)+16; + off_t inputsize = BASE16384_ENCBUFSZ/8*8; size_t cnt = 0; fputc(0xFE, output); fputc(0xFF, output); while((cnt = fread(encbuf, sizeof(char), inputsize, input)) > 0) { - int n = base16384_encode(encbuf, cnt, decbuf, outputsize); + int n = base16384_encode(encbuf, cnt, decbuf); if(fwrite(decbuf, n, 1, output) <= 0) { return base16384_err_write_file; } @@ -134,12 +133,11 @@ base16384_err_t base16384_encode_fd(int input, int output, char* encbuf, char* d if(output < 0) { return base16384_err_fopen_output_file; } - off_t inputsize = BUFSIZ*1024/7*7; - int outputsize = base16384_encode_len(inputsize)+16; + off_t inputsize = BASE16384_ENCBUFSZ/8*8; size_t cnt = 0; write(output, "\xfe\xff", 2); while((cnt = read(input, encbuf, inputsize)) > 0) { - int n = base16384_encode(encbuf, cnt, decbuf, outputsize); + int n = base16384_encode(encbuf, cnt, decbuf); if(write(output, decbuf, n) < n) { return base16384_err_write_file; } @@ -167,6 +165,7 @@ base16384_err_t base16384_decode_file(const char* input, const char* output, cha off_t inputsize; FILE* fp = NULL; FILE* fpo; + if(!input || !output || strlen(input) <= 0 || strlen(output) <= 0) return base16384_err_invalid_file_name; if(is_standard_io(input)) { // read from stdin inputsize = 0; fp = stdin; @@ -178,8 +177,8 @@ base16384_err_t base16384_decode_file(const char* input, const char* output, cha if(!fpo) { return base16384_err_fopen_output_file; } - if(!inputsize || inputsize > BUFSIZ*1024) { // stdin or big file, use decbuf & fread - inputsize = BUFSIZ*1024/8*8; + if(!inputsize || inputsize > BASE16384_DECBUFSZ) { // stdin or big file, use decbuf & fread + inputsize = BASE16384_DECBUFSZ/8*8; #ifdef _WIN32 } #endif @@ -187,7 +186,6 @@ base16384_err_t base16384_decode_file(const char* input, const char* output, cha if(!fp) { return base16384_err_fopen_input_file; } - int outputsize = base16384_decode_len(inputsize, 0)+16; int cnt = 0; int end = 0; rm_head(fp); @@ -196,7 +194,7 @@ base16384_err_t base16384_decode_file(const char* input, const char* output, cha decbuf[cnt++] = '='; decbuf[cnt++] = end; } - if(fwrite(encbuf, base16384_decode(decbuf, cnt, encbuf, outputsize), 1, fpo) <= 0) { + if(fwrite(encbuf, base16384_decode(decbuf, cnt, encbuf), 1, fpo) <= 0) { return base16384_err_write_file; } } @@ -208,13 +206,12 @@ base16384_err_t base16384_decode_file(const char* input, const char* output, cha if(fd < 0) { return base16384_err_open_input_file; } - char *input_file = mmap(NULL, (size_t)inputsize, PROT_READ, MAP_PRIVATE, fd, 0); + char *input_file = mmap(NULL, (size_t)inputsize+16, PROT_READ, MAP_PRIVATE, fd, 0); if(input_file == MAP_FAILED) { return base16384_err_map_input_file; } - int outputsize = base16384_decode_len(inputsize, 0)+16; int off = skip_offset(input_file); - if(fwrite(encbuf, base16384_decode(input_file+off, inputsize-off, encbuf, outputsize), 1, fpo) <= 0) { + if(fwrite(encbuf, base16384_decode(input_file+off, inputsize-off, encbuf), 1, fpo) <= 0) { return base16384_err_write_file; } munmap(input_file, (size_t)inputsize); @@ -232,8 +229,7 @@ base16384_err_t base16384_decode_fp(FILE* input, FILE* output, char* encbuf, cha if(!output) { return base16384_err_fopen_output_file; } - off_t inputsize = BUFSIZ*1024/8*8; - int outputsize = base16384_decode_len(inputsize, 0)+16; + off_t inputsize = BASE16384_DECBUFSZ/8*8; int cnt = 0; int end = 0; rm_head(input); @@ -242,7 +238,7 @@ base16384_err_t base16384_decode_fp(FILE* input, FILE* output, char* encbuf, cha decbuf[cnt++] = '='; decbuf[cnt++] = end; } - if(fwrite(encbuf, base16384_decode(decbuf, cnt, encbuf, outputsize), 1, output) <= 0) { + if(fwrite(encbuf, base16384_decode(decbuf, cnt, encbuf), 1, output) <= 0) { return base16384_err_write_file; } } @@ -265,8 +261,7 @@ base16384_err_t base16384_decode_fd(int input, int output, char* encbuf, char* d if(output < 0) { return base16384_err_fopen_output_file; } - off_t inputsize = BUFSIZ*1024/8*8; - int outputsize = base16384_decode_len(inputsize, 0)+16; + off_t inputsize = BASE16384_DECBUFSZ/8*8; int cnt = 0; int end = 0; decbuf[0] = 0; @@ -283,7 +278,7 @@ base16384_err_t base16384_decode_fd(int input, int output, char* encbuf, char* d end = 0; } else end = 1; } else end = 0; - cnt = base16384_decode(decbuf, cnt, encbuf, outputsize); + cnt = base16384_decode(decbuf, cnt, encbuf); if(write(output, encbuf, cnt) < cnt) { return base16384_err_write_file; } From c7fdf86d09ccf69dab26dd747c800d3de2e09e13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Fri, 25 Aug 2023 22:13:23 +0800 Subject: [PATCH 06/35] fix: disable mmap in windows --- file.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/file.c b/file.c index dc58810..1b5c9bd 100644 --- a/file.c +++ b/file.c @@ -63,7 +63,7 @@ base16384_err_t base16384_encode_file(const char* input, const char* output, cha } if(!inputsize || inputsize > BASE16384_ENCBUFSZ) { // stdin or big file, use encbuf & fread inputsize = BASE16384_ENCBUFSZ/8*8; - #ifdef _WIN32 + #if defined _WIN32 || defined __cosmopolitan } #endif if(!fp) fp = fopen(input, "rb"); @@ -82,7 +82,7 @@ base16384_err_t base16384_encode_file(const char* input, const char* output, cha } if(!is_standard_io(output)) fclose(fpo); if(!is_standard_io(input)) fclose(fp); - #ifndef _WIN32 + #if !defined _WIN32 && !defined __cosmopolitan } else { // small file, use mmap & fwrite int fd = open(input, O_RDONLY); if(fd < 0) { @@ -179,7 +179,7 @@ base16384_err_t base16384_decode_file(const char* input, const char* output, cha } if(!inputsize || inputsize > BASE16384_DECBUFSZ) { // stdin or big file, use decbuf & fread inputsize = BASE16384_DECBUFSZ/8*8; - #ifdef _WIN32 + #if defined _WIN32 || defined __cosmopolitan } #endif if(!fp) fp = fopen(input, "rb"); @@ -200,7 +200,7 @@ base16384_err_t base16384_decode_file(const char* input, const char* output, cha } if(!is_standard_io(output)) fclose(fpo); if(!is_standard_io(input)) fclose(fp); - #ifndef _WIN32 + #if !defined _WIN32 && !defined __cosmopolitan } else { // small file, use mmap & fwrite int fd = open(input, O_RDONLY); if(fd < 0) { From b61b3dd13e0a34c6fd32200d2b0a4f469d4ce501 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Sat, 26 Aug 2023 15:43:18 +0800 Subject: [PATCH 07/35] fix: encode bufsz (#19) --- base16384.h | 2 +- file.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/base16384.h b/base16384.h index f4bb985..fd19063 100644 --- a/base16384.h +++ b/base16384.h @@ -43,7 +43,7 @@ typedef enum base16384_err_t base16384_err_t; #undef define_base16384_err_t -#define BASE16384_ENCBUFSZ (BUFSIZ*1024/7*7) +#define BASE16384_ENCBUFSZ (BUFSIZ*1024/7*7+7) #define BASE16384_DECBUFSZ (BUFSIZ*1024/8*8+16) // base16384_encode_len calc min buf size to fill encode result diff --git a/file.c b/file.c index 1b5c9bd..0d07623 100644 --- a/file.c +++ b/file.c @@ -62,7 +62,7 @@ base16384_err_t base16384_encode_file(const char* input, const char* output, cha return base16384_err_fopen_output_file; } if(!inputsize || inputsize > BASE16384_ENCBUFSZ) { // stdin or big file, use encbuf & fread - inputsize = BASE16384_ENCBUFSZ/8*8; + inputsize = BASE16384_ENCBUFSZ-7; #if defined _WIN32 || defined __cosmopolitan } #endif @@ -113,7 +113,7 @@ base16384_err_t base16384_encode_fp(FILE* input, FILE* output, char* encbuf, cha if(!output) { return base16384_err_fopen_output_file; } - off_t inputsize = BASE16384_ENCBUFSZ/8*8; + off_t inputsize = BASE16384_ENCBUFSZ-7; size_t cnt = 0; fputc(0xFE, output); fputc(0xFF, output); @@ -133,7 +133,7 @@ base16384_err_t base16384_encode_fd(int input, int output, char* encbuf, char* d if(output < 0) { return base16384_err_fopen_output_file; } - off_t inputsize = BASE16384_ENCBUFSZ/8*8; + off_t inputsize = BASE16384_ENCBUFSZ-7; size_t cnt = 0; write(output, "\xfe\xff", 2); while((cnt = read(input, encbuf, inputsize)) > 0) { From df5ceea0c7c825da626ef96c5d0bb85b05513be5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Sat, 26 Aug 2023 15:44:45 +0800 Subject: [PATCH 08/35] v2.2.5 --- base16384.1 | 2 +- base16384.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/base16384.1 b/base16384.1 index c8e0921..279534d 100644 --- a/base16384.1 +++ b/base16384.1 @@ -1,4 +1,4 @@ -.TH BASE16384 1 "27 April 2022" "GNU" "User Commands" +.TH BASE16384 1 "26 August 2023" "GNU" "User Commands" .SH NAME base16384 \- Encode binary files to printable utf16be .SH SYNOPSIS diff --git a/base16384.c b/base16384.c index d3c4b7b..53d1891 100644 --- a/base16384.c +++ b/base16384.c @@ -39,7 +39,7 @@ unsigned long get_start_ms() { #endif static void print_usage() { - puts("Copyright (c) 2022-2023 Fumiama Minamoto.\nBase16384 2.2.5 (August 25th 2023). Usage:"); + puts("Copyright (c) 2022-2023 Fumiama Minamoto.\nBase16384 2.2.5 (August 26th 2023). Usage:"); puts("base16384 [-edt] [inputfile] [outputfile]"); puts(" -e\t\tencode"); puts(" -d\t\tdecode"); From cfe8e1b8b6c9d3173febfb5fa883a197221865d3 Mon Sep 17 00:00:00 2001 From: oboard Date: Fri, 16 Feb 2024 14:47:34 +0800 Subject: [PATCH 09/35] Update Swift Link (#21) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 41f1a88..e6bbd8b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # base16384 > **Note**: This project used the awesome cross-platform binary compiling tool [cosmopolitan](https://github.com/jart/cosmopolitan) -> Alternatives: [Go](https://github.com/fumiama/go-base16384), [Python](https://github.com/synodriver/pybase16384), [Android](https://github.com/fumiama/android-base16384), [TypeScript](https://github.com/shigma/base16384.js), [Lua(binding)](https://github.com/synodriver/lua-base16384), [Lua(pure)](https://github.com/Yiwen-Chan/base16384), [C#](https://github.com/lc6464/Base16384.Net), [Rust](https://github.com/Wybxc/base16384-rs) +> Alternatives: [Go](https://github.com/fumiama/go-base16384), [Python](https://github.com/synodriver/pybase16384), [Android](https://github.com/fumiama/android-base16384), [TypeScript](https://github.com/shigma/base16384.js), [Lua(binding)](https://github.com/synodriver/lua-base16384), [Lua(pure)](https://github.com/Yiwen-Chan/base16384), [C#](https://github.com/lc6464/Base16384.Net), [Rust](https://github.com/Wybxc/base16384-rs), [Swift](https://github.com/oboard/swift-ui-base16384) Encode binary file to printable utf16be, and vice versa. From 7a025ff5d30322e14d164d76f19d95ec00c81a31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Thu, 4 Apr 2024 03:11:53 +0900 Subject: [PATCH 10/35] feat: add param -n -t & optimize param parsing & tidy documents --- CMakeLists.txt | 3 +- base1432.c | 152 ++++++++++++++++++++--------- base1464.c | 145 +++++++++++++++++++--------- base16384.1 | 24 ++++- base16384.c | 135 +++++++++++++++----------- base16384.h | 176 ++++++++++++++++++++++++++------- binary.h | 90 +++++++++++++++++ file.c | 257 +++++++++++++++++++++++++++++++++++++------------ 8 files changed, 736 insertions(+), 246 deletions(-) create mode 100644 binary.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f75817f..edafedc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8.12) if (POLICY CMP0048) cmake_policy(SET CMP0048 NEW) endif (POLICY CMP0048) -project(base16384 VERSION 2.2.5) +project(base16384 VERSION 2.3.0) add_executable(base16384_b base16384.c) @@ -13,6 +13,7 @@ if (${isBigEndian}) endif() IF(CMAKE_SIZEOF_VOID_P EQUAL 8) + add_definitions(-DIS_64BIT_PROCESSOR) add_library(base16384 SHARED file.c base1464.c) add_library(base16384_s STATIC file.c base1464.c) ELSE() diff --git a/base1432.c b/base1432.c index ac09987..df723e2 100644 --- a/base1432.c +++ b/base1432.c @@ -1,6 +1,6 @@ /* base1432.c * This file is part of the base16384 distribution (https://github.com/fumiama/base16384). - * Copyright (c) 2022-2023 Fumiama Minamoto. + * Copyright (c) 2022-2024 Fumiama Minamoto. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,51 +16,7 @@ * along with this program. If not, see . */ -#ifdef __cosmopolitan // always le -# define be16toh(x) bswap_16(x) -# define be32toh(x) bswap_32(x) -# define htobe16(x) bswap_16(x) -# define htobe32(x) bswap_32(x) -#else -#include -#include -#include -#ifdef __linux__ -# include -#endif -#ifdef __FreeBSD__ -# include -#endif -#ifdef __NetBSD__ -# include -#endif -#ifdef __OpenBSD__ -# include -# define be16toh(x) betoh16(x) -# define be32toh(x) betoh32(x) -#endif -#ifdef __APPLE__ -# define be16toh(x) ntohs(x) -# define be32toh(x) ntohl(x) -# define htobe16(x) ntohs(x) -# define htobe32(x) htonl(x) -#endif -#ifdef _WIN32 - #ifdef WORDS_BIGENDIAN - # define be16toh(x) (x) - # define be32toh(x) (x) - # define htobe16(x) (x) - # define htobe32(x) (x) - #else - # define be16toh(x) _byteswap_ushort(x) - # define be32toh(x) _byteswap_ulong(x) - # define htobe16(x) _byteswap_ushort(x) - # define htobe32(x) _byteswap_ulong(x) - #endif -#endif -#endif - -// #define DEBUG +#include "binary.h" int base16384_encode(const char* data, int dlen, char* buf) { int outlen = dlen / 7 * 8; @@ -140,6 +96,49 @@ int base16384_encode(const char* data, int dlen, char* buf) { return outlen; } +int base16384_encode_unsafe(const char* data, int dlen, char* buf) { + int outlen = dlen / 7 * 8; + int offset = dlen % 7; + switch(offset) { // 算上偏移标志字符占用的2字节 + case 0: break; + case 1: outlen += 4; break; + case 2: + case 3: outlen += 6; break; + case 4: + case 5: outlen += 8; break; + case 6: outlen += 10; break; + default: break; + } + #ifdef DEBUG + printf("outlen: %llu, offset: %u, malloc: %llu\n", outlen, offset, outlen + 8); + #endif + uint32_t* vals = (uint32_t*)buf; + uint32_t n = 0; + int32_t i = 0; + for(; i < dlen; i += 7) { + register uint32_t sum = 0; + register uint32_t shift = htobe32(*(uint32_t*)(data+i)); + sum |= (shift>>2) & 0x3fff0000; + sum |= (shift>>4) & 0x00003fff; + sum += 0x4e004e00; + vals[n++] = be32toh(sum); + shift <<= 26; + shift &= 0x3c000000; + sum = 0; + shift |= (htobe32(*(uint32_t*)(data+i+4))>>6)&0x03fffffc; + sum |= shift & 0x3fff0000; + shift >>= 2; + sum |= shift & 0x00003fff; + sum += 0x4e004e00; + vals[n++] = be32toh(sum); + } + if(offset) { + buf[outlen - 2] = '='; + buf[outlen - 1] = offset; + } + return outlen; +} + int base16384_decode(const char* data, int dlen, char* buf) { int outlen = dlen; int offset = 0; @@ -214,3 +213,64 @@ int base16384_decode(const char* data, int dlen, char* buf) { } return outlen; } + +int base16384_decode_unsafe(const char* data, int dlen, char* buf) { + int outlen = dlen; + int offset = 0; + if(data[dlen-2] == '=') { + offset = data[dlen-1]; + switch(offset) { // 算上偏移标志字符占用的2字节 + case 0: break; + case 1: outlen -= 4; break; + case 2: + case 3: outlen -= 6; break; + case 4: + case 5: outlen -= 8; break; + case 6: outlen -= 10; break; + default: break; + } + } + outlen = outlen / 8 * 7 + offset; + uint32_t* vals = (uint32_t*)data; + uint32_t n = 0; + int32_t i = 0; + for(; i < outlen-7; i+=7) { // n实际每次自增2 + register uint32_t sum = 0; + register uint32_t shift = htobe32(vals[n++]) - 0x4e004e00; + shift <<= 2; + sum |= shift & 0xfffc0000; + shift <<= 2; + sum |= shift & 0x0003fff0; + shift = htobe32(vals[n++]) - 0x4e004e00; + sum |= shift >> 26; + *(uint32_t*)(buf+i) = be32toh(sum); + sum = 0; + shift <<= 6; + sum |= shift & 0xffc00000; + shift <<= 2; + sum |= shift & 0x003fff00; + *(uint32_t*)(buf+i+4) = be32toh(sum); + } + register uint32_t sum = 0; + register uint32_t shift = htobe32(vals[n++]); + if(((shift>>24)&0xff) < 0x4e) shift |= 0xff000000; + if(((shift>> 8)&0xff) < 0x4e) shift |= 0x0000ff00; + shift -= 0x4e004e00; + shift <<= 2; + sum |= shift & 0xfffc0000; + shift <<= 2; + sum |= shift & 0x0003fff0; + shift = htobe32(vals[n++]); + if(((shift>>24)&0xff) < 0x4e) shift |= 0xff000000; + if(((shift>> 8)&0xff) < 0x4e) shift |= 0x0000ff00; + shift -= 0x4e004e00; + sum |= shift >> 26; + *(uint32_t*)(buf+i) = be32toh(sum); + sum = 0; + shift <<= 6; + sum |= shift & 0xffc00000; + shift <<= 2; + sum |= shift & 0x003fff00; + *(uint32_t*)(buf+i+4) = be32toh(sum); + return outlen; +} diff --git a/base1464.c b/base1464.c index 73b0432..77d1ff3 100644 --- a/base1464.c +++ b/base1464.c @@ -1,6 +1,6 @@ /* base1464.c * This file is part of the base16384 distribution (https://github.com/fumiama/base16384). - * Copyright (c) 2022-2023 Fumiama Minamoto. + * Copyright (c) 2022-2024 Fumiama Minamoto. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,51 +16,7 @@ * along with this program. If not, see . */ -#include -#include -#include -#ifdef __linux__ -# include -#endif -#ifdef __FreeBSD__ -# include -#endif -#ifdef __NetBSD__ -# include -#endif -#ifdef __OpenBSD__ -# include -# define be16toh(x) betoh16(x) -# define be32toh(x) betoh32(x) -# define be64toh(x) betoh64(x) -#endif -#ifdef __APPLE__ -# define be16toh(x) ntohs(x) -# define be32toh(x) ntohl(x) -# define be64toh(x) ntohll(x) -# define htobe16(x) ntohs(x) -# define htobe32(x) htonl(x) -# define htobe64(x) htonll(x) -#endif -#ifdef _WIN64 - #ifdef WORDS_BIGENDIAN - # define be16toh(x) (x) - # define be32toh(x) (x) - # define be64toh(x) (x) - # define htobe16(x) (x) - # define htobe32(x) (x) - # define htobe64(x) (x) - #else - # define be16toh(x) _byteswap_ushort(x) - # define be32toh(x) _byteswap_ulong(x) - # define be64toh(x) _byteswap_uint64(x) - # define htobe16(x) _byteswap_ushort(x) - # define htobe32(x) _byteswap_ulong(x) - # define htobe64(x) _byteswap_uint64(x) - #endif -#endif - -// #define DEBUG +#include "binary.h" int base16384_encode(const char* data, int dlen, char* buf) { int outlen = dlen / 7 * 8; @@ -136,6 +92,48 @@ int base16384_encode(const char* data, int dlen, char* buf) { return outlen; } +int base16384_encode_unsafe(const char* data, int dlen, char* buf) { + int outlen = dlen / 7 * 8; + int offset = dlen % 7; + switch(offset) { // 算上偏移标志字符占用的2字节 + case 0: break; + case 1: outlen += 4; break; + case 2: + case 3: outlen += 6; break; + case 4: + case 5: outlen += 8; break; + case 6: outlen += 10; break; + default: break; + } + #ifdef DEBUG + printf("outlen: %llu, offset: %u, malloc: %llu\n", outlen, offset, outlen + 8); + #endif + uint64_t* vals = (uint64_t*)buf; + uint64_t n = 0; + int64_t i = 0; + for(; i < dlen; i += 7) { + register uint64_t sum = 0; + register uint64_t shift = htobe64(*(uint64_t*)(data+i))>>2; // 这里有读取越界 + sum |= shift & 0x3fff000000000000; + shift >>= 2; + sum |= shift & 0x00003fff00000000; + shift >>= 2; + sum |= shift & 0x000000003fff0000; + shift >>= 2; + sum |= shift & 0x0000000000003fff; + sum += 0x4e004e004e004e00; + vals[n++] = be64toh(sum); + #ifdef DEBUG + printf("i: %llu, add sum: %016llx\n", i, sum); + #endif + } + if(offset) { + buf[outlen - 2] = '='; + buf[outlen - 1] = offset; + } + return outlen; +} + int base16384_decode(const char* data, int dlen, char* buf) { int outlen = dlen; int offset = 0; @@ -201,3 +199,58 @@ int base16384_decode(const char* data, int dlen, char* buf) { } return outlen; } + +int base16384_decode_unsafe(const char* data, int dlen, char* buf) { + int outlen = dlen; + int offset = 0; + if(data[dlen-2] == '=') { + offset = data[dlen-1]; + switch(offset) { // 算上偏移标志字符占用的2字节 + case 0: break; + case 1: outlen -= 4; break; + case 2: + case 3: outlen -= 6; break; + case 4: + case 5: outlen -= 8; break; + case 6: outlen -= 10; break; + default: break; + } + } + outlen = outlen / 8 * 7 + offset; + uint64_t* vals = (uint64_t*)data; + uint64_t n = 0; + int64_t i = 0; + for(; i < outlen-7; n++, i+=7) { + register uint64_t sum = 0; + register uint64_t shift = htobe64(vals[n]) - 0x4e004e004e004e00; + shift <<= 2; + sum |= shift & 0xfffc000000000000; + shift <<= 2; + sum |= shift & 0x0003fff000000000; + shift <<= 2; + sum |= shift & 0x0000000fffc00000; + shift <<= 2; + sum |= shift & 0x00000000003fff00; + *(uint64_t*)(buf+i) = be64toh(sum); + #ifdef DEBUG + printf("i: %llu, add sum: %016llx\n", i, sum); + #endif + } + register uint64_t sum = 0; + register uint64_t shift = htobe64(vals[n]); + if(((shift>>56)&0xff) < 0x4e) shift |= 0xff00000000000000; + if(((shift>>40)&0xff) < 0x4e) shift |= 0x0000ff0000000000; + if(((shift>>24)&0xff) < 0x4e) shift |= 0x00000000ff000000; + if(((shift>> 8)&0xff) < 0x4e) shift |= 0x000000000000ff00; + shift -= 0x4e004e004e004e00; + shift <<= 2; + sum |= shift & 0xfffc000000000000; + shift <<= 2; + sum |= shift & 0x0003fff000000000; + shift <<= 2; + sum |= shift & 0x0000000fffc00000; + shift <<= 2; + sum |= shift & 0x00000000003fff00; + *(uint64_t*)(buf+i) = be64toh(sum); + return outlen; +} diff --git a/base16384.1 b/base16384.1 index 279534d..47c869a 100644 --- a/base16384.1 +++ b/base16384.1 @@ -1,9 +1,9 @@ -.TH BASE16384 1 "26 August 2023" "GNU" "User Commands" +.TH BASE16384 1 "4 April 2024" "GNU" "User Commands" .SH NAME base16384 \- Encode binary files to printable utf16be .SH SYNOPSIS .B base16384 --[e|d|t] <\fIinputfile\fR> <\fIoutputfile\fR> +-[edtn] <\fIinputfile\fR> <\fIoutputfile\fR> .SH DESCRIPTION .LP There are @@ -27,7 +27,11 @@ to .sp 1 .TP 0.5i \fB\-e\fR -Read data from \fIinputfile\fR and encode them into \fIoutputfile\fR. +Read data from \fIinputfile\fR and encode them into \fIoutputfile\fR. It's the default option when neither +.B -e +nor +.B -d +is specified. .TP 0.5i \fB\-d\fR Read data from \fIinputfile\fR and decode them into \fIoutputfile\fR. @@ -35,6 +39,12 @@ Read data from \fIinputfile\fR and decode them into \fIoutputfile\fR. \fB\-t\fR Show spend time. .TP 0.5i +\fB\-n\fR +Do not write utf16be file header (0xFEFF) to the output. +.TP 0.5i +\fB\-c\fR +Embed or validate checksum in remainder when using stdin/stdout or inputsize > _BASE16384_ENCBUFSZ. +.TP 0.5i \fBinputfile\fR An absolute or relative file path. Specially, pass - to read from stdin. .TP 0.5i @@ -68,6 +78,12 @@ Write file error in mmap. .TP 0.5i \fB8\fR Invalid input/output filename. +.TP 0.5i +\fB9\fR +Invalid commandline parameter. +.TP 0.5i +\fB10\fR +Invalid decoding checksum. .SH "SEE ALSO" https://github.com/fumiama/base16384 .SH BUGS @@ -77,7 +93,7 @@ on github. .SH AUTHOR This manual page contributed by Fumiama Minamoto. .SH "COPYRIGHT" -Copyright \(co 2022-2023, Fumiama Minamoto +Copyright \(co 2022-2024, Fumiama Minamoto This file is part of .IR "base16384" . .LP diff --git a/base16384.c b/base16384.c index 53d1891..dffafaa 100644 --- a/base16384.c +++ b/base16384.c @@ -1,6 +1,6 @@ /* base16384.c * This file is part of the base16384 distribution (https://github.com/fumiama/base16384). - * Copyright (c) 2022-2023 Fumiama Minamoto. + * Copyright (c) 2022-2024 Fumiama Minamoto. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,77 +38,98 @@ unsigned long get_start_ms() { } #endif -static void print_usage() { - puts("Copyright (c) 2022-2023 Fumiama Minamoto.\nBase16384 2.2.5 (August 26th 2023). Usage:"); - puts("base16384 [-edt] [inputfile] [outputfile]"); - puts(" -e\t\tencode"); - puts(" -d\t\tdecode"); - puts(" -t\t\tshow spend time"); - puts(" inputfile\tpass - to read from stdin"); - puts(" outputfile\tpass - to write to stdout"); +static base16384_err_t print_usage() { + fputs("Copyright (c) 2022-2024 Fumiama Minamoto.\nBase16384 2.3.0 (April 4th 2024). Usage:\n", stderr); + fputs("base16384 [-edtn] [inputfile] [outputfile]\n", stderr); + fputs(" -e\t\tencode (default)\n", stderr); + fputs(" -d\t\tdecode\n", stderr); + fputs(" -t\t\tshow spend time\n", stderr); + fputs(" -n\t\tdon't write utf16be file header (0xFEFF)\n", stderr); + fputs(" -c\t\tembed or validate checksum in remainder\n", stderr); + fputs(" inputfile\tpass - to read from stdin\n", stderr); + fputs(" outputfile\tpass - to write to stdout\n", stderr); + return base16384_err_invalid_commandline_parameter; } int main(int argc, char** argv) { - if(argc != 4 || argv[1][0] != '-') { - print_usage(); - return -1; - } - int flaglen = strlen(argv[1]); - if(flaglen <= 1 || flaglen > 3) { - print_usage(); - return -2; - } + + const char* cmd = argv[1]; + if(argc != 4 || cmd[0] != '-') return print_usage(); + + int flaglen = strlen(cmd); + if(flaglen <= 1 || flaglen > 5) return print_usage(); + #ifdef _WIN32 clock_t t = 0; #else unsigned long t = 0; #endif + + uint16_t is_encode = 1, use_timer = 0, no_header = 0, use_checksum = 0; + #define set_flag(f, v) ((f) = (((((f)>>8)+1) << 8)&0xff00) | (v&0x00ff)) + #define flag_has_been_set(f) ((f)>>8) + #define set_or_test_flag(f, v) (flag_has_been_set(f)?1:(set_flag(f, v), 0)) + while(--flaglen) switch(cmd[flaglen]) { // skip cmd[0] = '-' + case 'e': + if(set_or_test_flag(is_encode, 1)) return print_usage(); + break; + case 'd': + if(set_or_test_flag(is_encode, 0)) return print_usage(); + break; + case 't': + if(set_or_test_flag(use_timer, 1)) return print_usage(); + break; + case 'n': + if(set_or_test_flag(no_header, 1)) return print_usage(); + break; + case 'c': + if(set_or_test_flag(use_checksum, 1)) return print_usage(); + break; + default: + return print_usage(); + break; + } + #define clear_high_byte(x) ((x) &= 0x00ff) + clear_high_byte(is_encode); clear_high_byte(use_timer); + clear_high_byte(no_header); clear_high_byte(use_checksum); + + if(use_timer) { + #ifdef _WIN32 + t = clock(); + #else + t = get_start_ms(); + #endif + } + base16384_err_t exitstat = base16384_err_ok; - char cmd = argv[1][1]; - if(cmd == 't') { - if(flaglen == 2) { - print_usage(); return -3; - } + #define do_coding(method) base16384_##method##_file_detailed( \ + argv[2], argv[3], encbuf, decbuf, \ + (no_header?BASE16384_FLAG_NOHEADER:0) | (use_checksum?BASE16384_FLAG_SUM_CHECK_ON_REMAIN:0) \ + ) + exitstat = is_encode?do_coding(encode):do_coding(decode); + + if(t) { #ifdef _WIN32 - t = clock(); + fprintf(stderr, "spend time: %lums\n", clock() - t); #else - t = get_start_ms(); - #endif - cmd = argv[1][2]; - } else if(flaglen == 3) { - if(argv[1][2] != 't') { - print_usage(); return -4; - } - #ifdef _WIN32 - t = clock(); - #else - t = get_start_ms(); + fprintf(stderr, "spend time: %lums\n", get_start_ms() - t); #endif } - switch(cmd) { - case 'e': exitstat = base16384_encode_file(argv[2], argv[3], encbuf, decbuf); break; - case 'd': exitstat = base16384_decode_file(argv[2], argv[3], encbuf, decbuf); break; - default: print_usage(); return -5; - } - if(t && !exitstat && *(uint16_t*)(argv[3]) != *(uint16_t*)"-") { - #ifdef _WIN32 - printf("spend time: %lums\n", clock() - t); - #else - printf("spend time: %lums\n", get_start_ms() - t); - #endif - } - #define print_base16384_err(n) case base16384_err_##n: perror("base16384_err_"#n); break + + #define print_base16384_err(n) case base16384_err_##n: perror("base16384_err_"#n) if(exitstat) switch(exitstat) { - print_base16384_err(get_file_size); - print_base16384_err(fopen_output_file); - print_base16384_err(fopen_input_file); - print_base16384_err(write_file); - print_base16384_err(open_input_file); - print_base16384_err(map_input_file); - print_base16384_err(read_file); - print_base16384_err(invalid_file_name); + print_base16384_err(get_file_size); break; + print_base16384_err(fopen_output_file); break; + print_base16384_err(fopen_input_file); break; + print_base16384_err(write_file); break; + print_base16384_err(open_input_file); break; + print_base16384_err(map_input_file); break; + print_base16384_err(read_file); break; + print_base16384_err(invalid_file_name); break; + print_base16384_err(invalid_commandline_parameter); break; + print_base16384_err(invalid_decoding_checksum); break; default: perror("base16384"); break; } - #undef print_base16384_err return exitstat; + } diff --git a/base16384.h b/base16384.h index fd19063..6bf9e74 100644 --- a/base16384.h +++ b/base16384.h @@ -3,7 +3,7 @@ /* base16384.h * This file is part of the base16384 distribution (https://github.com/fumiama/base16384). - * Copyright (c) 2022-2023 Fumiama Minamoto. + * Copyright (c) 2022-2024 Fumiama Minamoto. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,31 +26,49 @@ #define define_base16384_err_t(n) base16384_err_##n -// base16384_err_t is the return value of base16384_en/decode_file -enum base16384_err_t { - define_base16384_err_t(ok), - define_base16384_err_t(get_file_size), - define_base16384_err_t(fopen_output_file), - define_base16384_err_t(fopen_input_file), - define_base16384_err_t(write_file), - define_base16384_err_t(open_input_file), - define_base16384_err_t(map_input_file), - define_base16384_err_t(read_file), - define_base16384_err_t(invalid_file_name), -}; -// base16384_err_t is the return value of base16384_en/decode_file -typedef enum base16384_err_t base16384_err_t; + enum base16384_err_t { + define_base16384_err_t(ok), + define_base16384_err_t(get_file_size), + define_base16384_err_t(fopen_output_file), + define_base16384_err_t(fopen_input_file), + define_base16384_err_t(write_file), + define_base16384_err_t(open_input_file), + define_base16384_err_t(map_input_file), + define_base16384_err_t(read_file), + define_base16384_err_t(invalid_file_name), + define_base16384_err_t(invalid_commandline_parameter), + define_base16384_err_t(invalid_decoding_checksum), + }; + + /** + * @brief return value of base16384_en/decode_file + */ + typedef enum base16384_err_t base16384_err_t; #undef define_base16384_err_t -#define BASE16384_ENCBUFSZ (BUFSIZ*1024/7*7+7) -#define BASE16384_DECBUFSZ (BUFSIZ*1024/8*8+16) +#define _BASE16384_ENCBUFSZ (BUFSIZ*1024/7*7) +#define _BASE16384_DECBUFSZ (BUFSIZ*1024/8*8) -// base16384_encode_len calc min buf size to fill encode result -static inline int base16384_encode_len(int dlen) { +#define BASE16384_ENCBUFSZ (_BASE16384_ENCBUFSZ+16) +#define BASE16384_DECBUFSZ (_BASE16384_DECBUFSZ+16) + +// disable 0xFEFF file header in encode +#define BASE16384_FLAG_NOHEADER (1<<0) +// enable sum check when using stdin or inputsize > _BASE16384_ENCBUFSZ +#define BASE16384_FLAG_SUM_CHECK_ON_REMAIN (1<<1) +// initial sum value used in BASE16384_FLAG_SUM_CHECK_ON_REMAIN +#define BASE16384_SIMPLE_SUM_INIT_VALUE (0x8e29c213) + +/** + * @brief calculate the exact encoded size + * @param dlen the data length to encode + * @return the size +*/ +static inline int _base16384_encode_len(int dlen) { int outlen = dlen / 7 * 8; int offset = dlen % 7; - switch(offset) { // 算上偏移标志字符占用的2字节 + switch(offset) { // 算上偏移标志字符占用的 2 字节 case 0: break; case 1: outlen += 4; break; case 2: @@ -60,13 +78,27 @@ static inline int base16384_encode_len(int dlen) { case 6: outlen += 10; break; default: break; } - return outlen + 8; // 冗余的8B用于可能的结尾的覆盖 + return outlen; } -// base16384_decode_len calc min buf size to fill decode result -static inline int base16384_decode_len(int dlen, int offset) { +/** + * @brief calculate minimum encoding buffer size (16 bits larger than the real encoded size) + * @param dlen the data length to encode + * @return the minimum encoding buffer size +*/ +static inline int base16384_encode_len(int dlen) { + return _base16384_encode_len(dlen) + 16; // 冗余的 16 字节用于可能的结尾的 unsafe 覆盖 +} + +/** + * @brief calculate the exact decoded size + * @param dlen the data length to decode + * @param offset the last char `xx` of the underfilled coding (0x3Dxx) or 0 for the full coding + * @return the size +*/ +static inline int _base16384_decode_len(int dlen, int offset) { int outlen = dlen; - switch(offset) { // 算上偏移标志字符占用的2字节 + switch(offset) { // 算上偏移标志字符占用的 2 字节 case 0: break; case 1: outlen -= 4; break; case 2: @@ -76,39 +108,117 @@ static inline int base16384_decode_len(int dlen, int offset) { case 6: outlen -= 10; break; default: break; } - return outlen / 8 * 7 + offset + 1; // 多出1字节用于循环覆盖 + return outlen / 8 * 7 + offset; } -// base16384_encode encodes data and write result into buf +/** + * @brief calculate minimum decoding buffer size (16 bits larger than the real decoded size) + * @param dlen the data length to decode + * @param offset the last char `xx` of the underfilled coding (0x3Dxx) or 0 for the full coding + * @return the minimum decoding buffer size +*/ +static inline int base16384_decode_len(int dlen, int offset) { + return _base16384_decode_len(dlen, offset) + 16; // 多出 16 字节用于 unsafe 循环覆盖 +} + +/** + * @brief encode data and write result into buf + * @param data data to encode + * @param dlen the data length + * @param buf the output buffer, whose size must greater than `base16384_encode_len` + * @return the total length written +*/ int base16384_encode(const char* data, int dlen, char* buf); -// base16384_decode decodes data and write result into buf +/** + * @brief encode data and write result into buf without considering border condition + * @param data data to encode + * @param dlen the data length + * @param buf the output buffer, whose size must greater than `base16384_encode_len` + * @return the total length written +*/ +int base16384_encode_unsafe(const char* data, int dlen, char* buf); + +/** + * @brief decode data and write result into buf + * @param data data to decode + * @param dlen the data length + * @param buf the output buffer, whose size must greater than `base16384_decode_len` + * @return the total length written +*/ int base16384_decode(const char* data, int dlen, char* buf); +/** + * @brief decode data and write result into buf without considering border condition + * @param data data to decode + * @param dlen the data length + * @param buf the output buffer, whose size must greater than `base16384_decode_len` + * @return the total length written +*/ +int base16384_decode_unsafe(const char* data, int dlen, char* buf); + +// base16384_encode_file_detailed encodes input file to output file. +// use `-` to specify stdin/stdout +// encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ +base16384_err_t base16384_encode_file_detailed(const char* input, const char* output, char* encbuf, char* decbuf, int flag); + +// base16384_encode_fp_detailed encodes input file to output file. +// encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ +base16384_err_t base16384_encode_fp_detailed(FILE* input, FILE* output, char* encbuf, char* decbuf, int flag); + +// base16384_encode_fd_detailed encodes input fd to output fd. +// encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ +base16384_err_t base16384_encode_fd_detailed(int input, int output, char* encbuf, char* decbuf, int flag); + +// base16384_decode_file_detailed decodes input file to output file. +// use `-` to specify stdin/stdout +// encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ +base16384_err_t base16384_decode_file_detailed(const char* input, const char* output, char* encbuf, char* decbuf, int flag); + +// base16384_decode_fp_detailed decodes input file to output file. +// encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ +base16384_err_t base16384_decode_fp_detailed(FILE* input, FILE* output, char* encbuf, char* decbuf, int flag); + +// base16384_decode_fd_detailed decodes input fd to output fd. +// encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ +base16384_err_t base16384_decode_fd_detailed(int input, int output, char* encbuf, char* decbuf, int flag); + // base16384_encode_file encodes input file to output file. // use `-` to specify stdin/stdout // encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ -base16384_err_t base16384_encode_file(const char* input, const char* output, char* encbuf, char* decbuf); +static inline base16384_err_t base16384_encode_file(const char* input, const char* output, char* encbuf, char* decbuf) { + return base16384_encode_file_detailed(input, output, encbuf, decbuf, 0); +} // base16384_encode_fp encodes input file to output file. // encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ -base16384_err_t base16384_encode_fp(FILE* input, FILE* output, char* encbuf, char* decbuf); +static inline base16384_err_t base16384_encode_fp(FILE* input, FILE* output, char* encbuf, char* decbuf) { + return base16384_encode_fp_detailed(input, output, encbuf, decbuf, 0); +} // base16384_encode_fd encodes input fd to output fd. // encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ -base16384_err_t base16384_encode_fd(int input, int output, char* encbuf, char* decbuf); +static inline base16384_err_t base16384_encode_fd(int input, int output, char* encbuf, char* decbuf) { + return base16384_encode_fd_detailed(input, output, encbuf, decbuf, 0); +} // base16384_decode_file decodes input file to output file. // use `-` to specify stdin/stdout // encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ -base16384_err_t base16384_decode_file(const char* input, const char* output, char* encbuf, char* decbuf); +static inline base16384_err_t base16384_decode_file(const char* input, const char* output, char* encbuf, char* decbuf) { + return base16384_decode_file_detailed(input, output, encbuf, decbuf, 0); +} // base16384_decode_fp decodes input file to output file. // encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ -base16384_err_t base16384_decode_fp(FILE* input, FILE* output, char* encbuf, char* decbuf); +static inline base16384_err_t base16384_decode_fp(FILE* input, FILE* output, char* encbuf, char* decbuf) { + return base16384_decode_fp_detailed(input, output, encbuf, decbuf, 0); +} // base16384_decode_fd decodes input fd to output fd. // encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ -base16384_err_t base16384_decode_fd(int input, int output, char* encbuf, char* decbuf); +static inline base16384_err_t base16384_decode_fd(int input, int output, char* encbuf, char* decbuf) { + return base16384_decode_fd_detailed(input, output, encbuf, decbuf, 0); +} #endif diff --git a/binary.h b/binary.h new file mode 100644 index 0000000..7f180d7 --- /dev/null +++ b/binary.h @@ -0,0 +1,90 @@ +#ifndef _BINARY_H_ +#define _BINARY_H_ + +/* binary.h + * This file is part of the base16384 distribution (https://github.com/fumiama/base16384). + * Copyright (c) 2022-2024 Fumiama Minamoto. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifdef __cosmopolitan // always le + #define be16toh(x) bswap_16(x) + #define be32toh(x) bswap_32(x) + #define htobe16(x) bswap_16(x) + #define htobe32(x) bswap_32(x) +#else + #include + #include + #include + #ifdef __linux__ + #include + #endif + #ifdef __FreeBSD__ + #include + #endif + #ifdef __NetBSD__ + #include + #endif + #ifdef __OpenBSD__ + #include + #define be16toh(x) betoh16(x) + #define be32toh(x) betoh32(x) + #ifdef IS_64BIT_PROCESSOR + #define be64toh(x) betoh64(x) + #endif + #endif + #ifdef __APPLE__ + #define be16toh(x) ntohs(x) + #define be32toh(x) ntohl(x) + #ifdef IS_64BIT_PROCESSOR + #define be64toh(x) ntohll(x) + #endif + #define htobe16(x) htons(x) + #define htobe32(x) htonl(x) + #ifdef IS_64BIT_PROCESSOR + #define htobe64(x) htonll(x) + #endif + #endif + #ifdef _MSC_VER + #ifdef WORDS_BIGENDIAN + #define be16toh(x) (x) + #define be32toh(x) (x) + #ifdef IS_64BIT_PROCESSOR + #define be64toh(x) (x) + #endif + #define htobe16(x) (x) + #define htobe32(x) (x) + #ifdef IS_64BIT_PROCESSOR + #define htobe64(x) (x) + #endif + #else + #define be16toh(x) _byteswap_ushort(x) + #define be32toh(x) _byteswap_ulong(x) + #ifdef IS_64BIT_PROCESSOR + #define be64toh(x) _byteswap_uint64(x) + #endif + #define htobe16(x) _byteswap_ushort(x) + #define htobe32(x) _byteswap_ulong(x) + #ifdef IS_64BIT_PROCESSOR + #define htobe64(x) _byteswap_uint64(x) + #endif + #endif + #endif +#endif + +// leftrotate function definition +#define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (sizeof(x)*8 - (c)))) + +#endif diff --git a/file.c b/file.c index 0d07623..35ff956 100644 --- a/file.c +++ b/file.c @@ -1,6 +1,6 @@ /* file.c * This file is part of the base16384 distribution (https://github.com/fumiama/base16384). - * Copyright (c) 2022-2023 Fumiama Minamoto. + * Copyright (c) 2022-2024 Fumiama Minamoto. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef _WIN32 #include #include @@ -33,6 +34,7 @@ #endif #endif #include "base16384.h" +#include "binary.h" #ifdef __cosmopolitan #define get_file_size(filepath) ((off_t)GetFileSize(filepath)) @@ -45,11 +47,77 @@ static inline off_t get_file_size(const char* filepath) { #define is_standard_io(filename) (*(uint16_t*)(filename) == *(uint16_t*)"-") -base16384_err_t base16384_encode_file(const char* input, const char* output, char* encbuf, char* decbuf) { +static inline uint32_t calc_sum(uint32_t sum, size_t cnt, char* encbuf) { + uint32_t i; + #ifdef DEBUG + fprintf(stderr, "cnt: %zu, roundin: %08x, ", cnt, sum); + #endif + for(i = 0; i < cnt/sizeof(sum); i++) { + #ifdef DEBUG + if (!i) { + fprintf(stderr, "firstval: %08x, ", htobe32(((uint32_t*)encbuf)[i])); + } + #endif + sum += LEFTROTATE(htobe32(((uint32_t*)encbuf)[i]), encbuf[i*sizeof(sum)]%(8*sizeof(sum))); + } + #ifdef DEBUG + fprintf(stderr, "roundmid: %08x", sum); + #endif + size_t rem = cnt % sizeof(sum); + if(rem) { + uint32_t x = htobe32(((uint32_t*)encbuf)[i]) & (0xffffffff << (8*(sizeof(sum)-rem))); + sum += LEFTROTATE(x, encbuf[i*sizeof(sum)]%(8*sizeof(sum))); + #ifdef DEBUG + fprintf(stderr, ", roundrem:%08x\n", sum); + #endif + } + #ifdef DEBUG + else fprintf(stderr, "\n"); + #endif + return sum; +} + +static inline uint32_t calc_and_embed_sum(uint32_t sum, size_t cnt, char* encbuf) { + sum = calc_sum(sum, cnt, encbuf); + if(cnt%7) { // last encode + *(uint32_t*)(&encbuf[cnt]) = htobe32(sum); + } + return sum; +} + +static inline int calc_and_check_sum(uint32_t* s, size_t cnt, char* encbuf) { + uint32_t sum = calc_sum(*s, cnt, encbuf); + if(cnt%7) { // is last decode block + int shift = (int[]){0, 26, 20, 28, 22, 30, 24}[cnt%7]; + uint32_t sum_read = be32toh((*(uint32_t*)(&encbuf[cnt]))) >> shift; + sum >>= shift; + #ifdef DEBUG + fprintf(stderr, "cntrm: %lu, mysum: %08x, sumrd: %08x\n", cnt%7, sum, sum_read); + #endif + return sum != sum_read; + } + *s = sum; + return 0; +} + +#define goto_base16384_file_detailed_cleanup(method, reason, dobeforereturn) { \ + errnobak = errno; \ + retval = reason; \ + dobeforereturn; \ + goto base16384_##method##_file_detailed_cleanup; \ +} + +base16384_err_t base16384_encode_file_detailed(const char* input, const char* output, char* encbuf, char* decbuf, int flag) { off_t inputsize; FILE* fp = NULL; FILE* fpo; - if(!input || !output || strlen(input) <= 0 || strlen(output) <= 0) return base16384_err_invalid_file_name; + uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE; + int errnobak = 0; + base16384_err_t retval = base16384_err_ok; + if(!input || !output || strlen(input) <= 0 || strlen(output) <= 0) { + errno = EINVAL; + return base16384_err_invalid_file_name; + } if(is_standard_io(input)) { // read from stdin inputsize = 0; fp = stdin; @@ -61,64 +129,81 @@ base16384_err_t base16384_encode_file(const char* input, const char* output, cha if(!fpo) { return base16384_err_fopen_output_file; } - if(!inputsize || inputsize > BASE16384_ENCBUFSZ) { // stdin or big file, use encbuf & fread - inputsize = BASE16384_ENCBUFSZ-7; + if(!inputsize || inputsize > _BASE16384_ENCBUFSZ) { // stdin or big file, use encbuf & fread + inputsize = _BASE16384_ENCBUFSZ; #if defined _WIN32 || defined __cosmopolitan } #endif if(!fp) fp = fopen(input, "rb"); if(!fp) { - return base16384_err_fopen_input_file; + goto_base16384_file_detailed_cleanup(encode, base16384_err_fopen_input_file, {}); } - size_t cnt = 0; - fputc(0xFE, fpo); - fputc(0xFF, fpo); + if(!(flag&BASE16384_FLAG_NOHEADER)) { + fputc(0xFE, fpo); + fputc(0xFF, fpo); + } + #ifdef DEBUG + inputsize = 917504; + fprintf(stderr, "inputsize: %lld\n", inputsize); + #endif + size_t cnt; while((cnt = fread(encbuf, sizeof(char), inputsize, fp)) > 0) { - int n = base16384_encode(encbuf, cnt, decbuf); + if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) sum = calc_and_embed_sum(sum, cnt, encbuf); + int n = base16384_encode_unsafe(encbuf, cnt, decbuf); if(fwrite(decbuf, n, 1, fpo) <= 0) { - return base16384_err_write_file; + goto_base16384_file_detailed_cleanup(encode, base16384_err_write_file, {}); } } - if(!is_standard_io(output)) fclose(fpo); - if(!is_standard_io(input)) fclose(fp); #if !defined _WIN32 && !defined __cosmopolitan } else { // small file, use mmap & fwrite int fd = open(input, O_RDONLY); if(fd < 0) { - return base16384_err_open_input_file; + goto_base16384_file_detailed_cleanup(encode, base16384_err_open_input_file, {}); } char *input_file = mmap(NULL, (size_t)inputsize+16, PROT_READ, MAP_PRIVATE, fd, 0); if(input_file == MAP_FAILED) { - return base16384_err_map_input_file; + goto_base16384_file_detailed_cleanup(encode, base16384_err_map_input_file, close(fd)); + } + if(!(flag&BASE16384_FLAG_NOHEADER)) { + fputc(0xFE, fpo); + fputc(0xFF, fpo); } - fputc(0xFE, fpo); - fputc(0xFF, fpo); int n = base16384_encode(input_file, (int)inputsize, decbuf); if(fwrite(decbuf, n, 1, fpo) <= 0) { - return base16384_err_write_file; + goto_base16384_file_detailed_cleanup(encode, base16384_err_write_file, { + munmap(input_file, (size_t)inputsize); + close(fd); + }); } munmap(input_file, (size_t)inputsize); - if(!is_standard_io(output)) fclose(fpo); close(fd); } #endif - return base16384_err_ok; +base16384_encode_file_detailed_cleanup: + if(fpo && !is_standard_io(output)) fclose(fpo); + if(fp && !is_standard_io(input)) fclose(fp); + if(errnobak) errno = errnobak; + return retval; } -base16384_err_t base16384_encode_fp(FILE* input, FILE* output, char* encbuf, char* decbuf) { +base16384_err_t base16384_encode_fp_detailed(FILE* input, FILE* output, char* encbuf, char* decbuf, int flag) { if(!input) { return base16384_err_fopen_input_file; } if(!output) { return base16384_err_fopen_output_file; } - off_t inputsize = BASE16384_ENCBUFSZ-7; + off_t inputsize = _BASE16384_ENCBUFSZ; size_t cnt = 0; - fputc(0xFE, output); - fputc(0xFF, output); + uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE; + if(!(flag&BASE16384_FLAG_NOHEADER)) { + fputc(0xFE, output); + fputc(0xFF, output); + } while((cnt = fread(encbuf, sizeof(char), inputsize, input)) > 0) { - int n = base16384_encode(encbuf, cnt, decbuf); + if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) sum = calc_and_embed_sum(sum, cnt, encbuf); + int n = base16384_encode_unsafe(encbuf, cnt, decbuf); if(fwrite(decbuf, n, 1, output) <= 0) { return base16384_err_write_file; } @@ -126,18 +211,20 @@ base16384_err_t base16384_encode_fp(FILE* input, FILE* output, char* encbuf, cha return base16384_err_ok; } -base16384_err_t base16384_encode_fd(int input, int output, char* encbuf, char* decbuf) { +base16384_err_t base16384_encode_fd_detailed(int input, int output, char* encbuf, char* decbuf, int flag) { if(input < 0) { return base16384_err_fopen_input_file; } if(output < 0) { return base16384_err_fopen_output_file; } - off_t inputsize = BASE16384_ENCBUFSZ-7; + off_t inputsize = _BASE16384_ENCBUFSZ; size_t cnt = 0; - write(output, "\xfe\xff", 2); + uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE; + if(!(flag&BASE16384_FLAG_NOHEADER)) write(output, "\xfe\xff", 2); while((cnt = read(input, encbuf, inputsize)) > 0) { - int n = base16384_encode(encbuf, cnt, decbuf); + if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) sum = calc_and_embed_sum(sum, cnt, encbuf); + int n = base16384_encode_unsafe(encbuf, cnt, decbuf); if(write(output, decbuf, n) < n) { return base16384_err_write_file; } @@ -161,11 +248,17 @@ static inline int is_next_end(FILE* fp) { return 0; } -base16384_err_t base16384_decode_file(const char* input, const char* output, char* encbuf, char* decbuf) { +base16384_err_t base16384_decode_file_detailed(const char* input, const char* output, char* encbuf, char* decbuf, int flag) { off_t inputsize; FILE* fp = NULL; FILE* fpo; - if(!input || !output || strlen(input) <= 0 || strlen(output) <= 0) return base16384_err_invalid_file_name; + uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE; + base16384_err_t retval = base16384_err_ok; + int errnobak = 0; + if(!input || !output || strlen(input) <= 0 || strlen(output) <= 0) { + errno = EINVAL; + return base16384_err_invalid_file_name; + } if(is_standard_io(input)) { // read from stdin inputsize = 0; fp = stdin; @@ -177,93 +270,130 @@ base16384_err_t base16384_decode_file(const char* input, const char* output, cha if(!fpo) { return base16384_err_fopen_output_file; } - if(!inputsize || inputsize > BASE16384_DECBUFSZ) { // stdin or big file, use decbuf & fread - inputsize = BASE16384_DECBUFSZ/8*8; + if(!inputsize || inputsize > _BASE16384_DECBUFSZ) { // stdin or big file, use decbuf & fread + inputsize = _BASE16384_DECBUFSZ; #if defined _WIN32 || defined __cosmopolitan } #endif if(!fp) fp = fopen(input, "rb"); if(!fp) { - return base16384_err_fopen_input_file; + goto_base16384_file_detailed_cleanup(decode, base16384_err_fopen_input_file, {}); } int cnt = 0; int end = 0; rm_head(fp); + if(errno) { + goto_base16384_file_detailed_cleanup(decode, base16384_err_read_file, {}); + } + #ifdef DEBUG + fprintf(stderr, "inputsize: %lld\n", inputsize); + #endif while((cnt = fread(decbuf, sizeof(char), inputsize, fp)) > 0) { if((end = is_next_end(fp))) { decbuf[cnt++] = '='; decbuf[cnt++] = end; } - if(fwrite(encbuf, base16384_decode(decbuf, cnt, encbuf), 1, fpo) <= 0) { - return base16384_err_write_file; + if(errno) goto_base16384_file_detailed_cleanup(decode, base16384_err_read_file, {}); + cnt = base16384_decode_unsafe(decbuf, cnt, encbuf); + if(fwrite(encbuf, cnt, 1, fpo) <= 0) { + goto_base16384_file_detailed_cleanup(decode, base16384_err_write_file, {}); + } + if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) { + if(calc_and_check_sum(&sum, cnt, encbuf)) { + errno = EINVAL; + goto_base16384_file_detailed_cleanup(decode, base16384_err_invalid_decoding_checksum, {}); + } } } - if(!is_standard_io(output)) fclose(fpo); - if(!is_standard_io(input)) fclose(fp); #if !defined _WIN32 && !defined __cosmopolitan } else { // small file, use mmap & fwrite int fd = open(input, O_RDONLY); if(fd < 0) { - return base16384_err_open_input_file; + goto_base16384_file_detailed_cleanup(decode, base16384_err_open_input_file, {}); } char *input_file = mmap(NULL, (size_t)inputsize+16, PROT_READ, MAP_PRIVATE, fd, 0); if(input_file == MAP_FAILED) { - return base16384_err_map_input_file; + goto_base16384_file_detailed_cleanup(decode, base16384_err_map_input_file, close(fd)); } int off = skip_offset(input_file); if(fwrite(encbuf, base16384_decode(input_file+off, inputsize-off, encbuf), 1, fpo) <= 0) { - return base16384_err_write_file; + goto_base16384_file_detailed_cleanup(decode, base16384_err_write_file, { + munmap(input_file, (size_t)inputsize); + close(fd); + }); } munmap(input_file, (size_t)inputsize); - if(!is_standard_io(output)) fclose(fpo); close(fd); } #endif - return base16384_err_ok; +base16384_decode_file_detailed_cleanup: + if(fpo && !is_standard_io(output)) fclose(fpo); + if(fp && !is_standard_io(input)) fclose(fp); + if(errnobak) errno = errnobak; + return retval; } -base16384_err_t base16384_decode_fp(FILE* input, FILE* output, char* encbuf, char* decbuf) { +base16384_err_t base16384_decode_fp_detailed(FILE* input, FILE* output, char* encbuf, char* decbuf, int flag) { if(!input) { + errno = EINVAL; return base16384_err_fopen_input_file; } if(!output) { + errno = EINVAL; return base16384_err_fopen_output_file; } - off_t inputsize = BASE16384_DECBUFSZ/8*8; + off_t inputsize = _BASE16384_DECBUFSZ; int cnt = 0; int end = 0; + uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE; rm_head(input); + if(errno) { + return base16384_err_read_file; + } while((cnt = fread(decbuf, sizeof(char), inputsize, input)) > 0) { if((end = is_next_end(input))) { decbuf[cnt++] = '='; decbuf[cnt++] = end; } - if(fwrite(encbuf, base16384_decode(decbuf, cnt, encbuf), 1, output) <= 0) { + cnt = base16384_decode_unsafe(decbuf, cnt, encbuf); + if(fwrite(encbuf, cnt, 1, output) <= 0) { return base16384_err_write_file; } + if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) { + if (calc_and_check_sum(&sum, cnt, encbuf)) { + errno = EINVAL; + return base16384_err_invalid_decoding_checksum; + } + } } return base16384_err_ok; } -static inline int is_next_end_fd(int fd) { - char ch = 0; +static inline uint16_t is_next_end_fd(int fd) { + uint8_t ch = 0; read(fd, &ch, 1); + uint16_t ret = (uint16_t)ch & 0x00ff; if(ch == '=') { read(fd, &ch, 1); + ret <<= 8; + ret |= (uint16_t)ch & 0x00ff; } - return (int)ch; + return ret; } -base16384_err_t base16384_decode_fd(int input, int output, char* encbuf, char* decbuf) { +base16384_err_t base16384_decode_fd_detailed(int input, int output, char* encbuf, char* decbuf, int flag) { if(input < 0) { + errno = EINVAL; return base16384_err_fopen_input_file; } if(output < 0) { + errno = EINVAL; return base16384_err_fopen_output_file; } - off_t inputsize = BASE16384_DECBUFSZ/8*8; + off_t inputsize = _BASE16384_DECBUFSZ; int cnt = 0; int end = 0; + uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE; decbuf[0] = 0; if(read(input, decbuf, 2) < 2) { return base16384_err_read_file; @@ -272,17 +402,26 @@ base16384_err_t base16384_decode_fd(int input, int output, char* encbuf, char* d while((end = read(input, decbuf+cnt, inputsize-cnt)) > 0 || cnt > 0) { if(end > 0) { cnt += end; - if((end = is_next_end_fd(input))) { + uint16_t next = is_next_end_fd(input); + if(errno) { + return base16384_err_read_file; + } + if(next&0xff00) { decbuf[cnt++] = '='; - decbuf[cnt++] = end; - end = 0; - } else end = 1; - } else end = 0; - cnt = base16384_decode(decbuf, cnt, encbuf); - if(write(output, encbuf, cnt) < cnt) { + } + decbuf[cnt++] = (char)(next&0x00ff); + } + end = base16384_decode_unsafe(decbuf, cnt, encbuf); + if(write(output, encbuf, end) < end) { return base16384_err_write_file; } - cnt = end; + if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) { + if (calc_and_check_sum(&sum, cnt, encbuf)) { + errno = EINVAL; + return base16384_err_invalid_decoding_checksum; + } + } + cnt = 0; } return base16384_err_ok; } From 263b2ec2dd5ddb1c111936f31ed7f2b93fa1da39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Thu, 4 Apr 2024 03:15:48 +0900 Subject: [PATCH 11/35] edit README --- README.md | 49 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index e6bbd8b..3d7888b 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,9 @@ Encode binary file to printable utf16be, and vice versa. -## Description 说明 +## Description +> 说明 + Use 16384 Chinene characters (from \u4E00 to \u8DFF) as the "alphabet", just like what base64 did. 使用16384个汉字(从`\u4E00`到`\u8DFF`)作为字符表,就像base64用64个字符作为字符表一样。 @@ -14,31 +16,38 @@ If length of the data has a remainder after moduled by 7, we will use \u3Dxx to 使用`\u3Dxx`附加在末尾以表示编码时数据不满7位的个数,其范围在01~06。 -## Benefits 优点 +## Benefits +> 优点 + Save more space and since the code 0x0000 is encoded to "一", finding zero space seems to be easier. 相较base64节省更多空间,更容易发现二进制文件的规律。 -## Usage 使用说明 +## Usage +> 用法 -### Install from Debian Bookworm or higher 从 Debian Bookworm 或更高版本安装 +### Install from Debian Bookworm or higher +> 从 Debian Bookworm 或更高版本安装 ```bash sudo apt install base16384 ``` -### Install from Homebrew 从 Homebrew 安装 +### Install from Homebrew +> 从 Homebrew 安装 ```bash brew install base16384 ``` -### Install from my PPA in Ubuntu 乌班图下从我的 PPA 安装 +### Install from my PPA in Ubuntu +> 乌班图下从我的 PPA 安装 ```bash sudo add-apt-repository ppa:fumiama/ppa sudo apt-get update sudo apt-get install base16384 ``` -### Build from source code 编译 +### Build from source code +> 编译 Clone this repo first. @@ -67,30 +76,36 @@ Now you can encode/decode a file by commands below. ```kotlin Usage: -base16384 [-edt] [inputfile] [outputfile] - -e encode - -d decode - -t show spend time - inputfile pass - to read from stdin - outputfile pass - to write to stdout +base16384 [-edtn] [inputfile] [outputfile] + -e encode (default) + -d decode + -t show spend time + -n don't write utf16be file header (0xFEFF) + -c embed or validate checksum in remainder + inputfile pass - to read from stdin + outputfile pass - to write to stdout ``` -## Examples 用例 -1. Encode simple text 简单文本编码 +## Examples +> 用例 +1. Encode simple text +> 简单文本编码 ```bash echo -n "1234567" | base16384 -e - - | iconv -f utf-16be -t utf-8 婌焳廔萷 ``` -3. Decode simple text 简单文本解码 +3. Decode simple text +> 简单文本解码 ```bash echo -n "婌焳廔萷" | iconv -f utf-8 -t utf-16be | base16384 -d - - 1234567 ``` -3. Encode file 编码文件 +3. Encode file +> 编码文件 The text below is the encoding of the base16384 itself on MacOS 12.6 arm64. It is clear to see the strucutre of the binary file. From 792b1ed72805abc0cbba18211aa649cf5d8e178b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Thu, 4 Apr 2024 03:17:57 +0900 Subject: [PATCH 12/35] edit README --- README.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 3d7888b..32f9ee9 100644 --- a/README.md +++ b/README.md @@ -89,26 +89,26 @@ base16384 [-edtn] [inputfile] [outputfile] ## Examples > 用例 1. Encode simple text -> 简单文本编码 + > 简单文本编码 -```bash -echo -n "1234567" | base16384 -e - - | iconv -f utf-16be -t utf-8 -婌焳廔萷 -``` + ```bash + echo -n "1234567" | base16384 -e - - | iconv -f utf-16be -t utf-8 + 婌焳廔萷 + ``` 3. Decode simple text -> 简单文本解码 + > 简单文本解码 -```bash -echo -n "婌焳廔萷" | iconv -f utf-8 -t utf-16be | base16384 -d - - -1234567 -``` + ```bash + echo -n "婌焳廔萷" | iconv -f utf-8 -t utf-16be | base16384 -d - - + 1234567 + ``` 3. Encode file -> 编码文件 + > 编码文件 -The text below is the encoding of the base16384 itself on MacOS 12.6 arm64. It is clear to see the strucutre of the binary file. + The text below is the encoding of the base16384 itself on MacOS 12.6 arm64. It is clear to see the strucutre of the binary file. -下面的文本是使用base16384程序在 MacOS Mojave 版本下编码自身的结果。可见文件结构十分清晰。 + 下面的文本是使用base16384程序在 MacOS Mojave 版本下编码自身的结果。可见文件结构十分清晰。 -臾糟蘜一乀縀倀倀一仰一习佀丈戀渀一一乤一丒一丁浟成扴捩卒懀一一一一一一一一一一伀一一一一一一一一一一一一一一一一一一一丙一不渄一旗荄捡戀一一一一一一一丁一一亀一一一一一一一一丠一一一丅一一戀一佀一一一丗菷徕虴一一一一一丅譽扅搕一一一一一丂爋一丐一仈刀一一一眂縀丈一一一一一一一市一一一一一一一佽浳欝搧娀一一一一也旕剕潐一一一一一丛俀一伀一唠一一一丆繰一乀一一一一一一嘄丠一一丆一一一一旗蔷忕灟栙擇侕耀一叵譑単挀一一一一一冀樀一帀七尀一一一仠唀一嘀一一一一一一乀倀一一一一一一丅譽煳欜璖螜一一一丁浟挑掅帀一一一一一禇帀丄一丸帐一一一壡舀一一一一一一一丈一一一一一一一一也旝擧殥籤旚擦枼一丗菵引晔一一一一一三乼一乀一俀一一一丂帟一丠一一一一一一一一一一一一一一一侐一予乀丅譽剁挐帀一一一一一丠一丐一一刈一一一丈一一一一伀一一一丰一七一一帀一一一佽浮椗蔷玵灯椗蔇忈也旑刕弄一一一一一一倀一伀一亀一一一一亀一什一一一一一一吀一估一一一一一一旗葶诐一一一一一一叵謑佔幀一一一一一丠渀一帀一昀一一一丈嘀一娀一一一一一丁渀一戀一一一一一丅譽穡旜薖莉絬旜啇嘁浟弐捄刀一一一一一嘈一丄一並一一一一倂一七一一一一一一东一丅縀一一一一一也旘蓶莵絮一一一一丗菴弅扁一一一一一丌亀一乀一丰丠一一一一一乀一一一一一一乀一一一一一一一一侐一么一丅譽婉憒艔弥戀一一一丰嘀丐一一刀一一一丌一一一丼习一一一丐一丁一一一一一一予一渌一一丰一亀一丈娀七一一一一一一与儀一币一劃刀付一一嘀一吀一你耀三一丁丵一夀刀下一丅一一一一丄一一帀一嬀一仠一世一一一一一一一一一一一一一一一亘嬀丂瘀一一一一一一一一一一仠一丠一一縀一姝攷嚽穩暋葇玱爀一一一丛一丁渀一斪罒跻舷圪讫惙硗垚愠一丠一一刀一七溠一崊一帀一儀一一么倪一丁一一一一一一上一倀昀一峀稀一一一一一一一丰一与一一昀一丠一一一幐一伀姝攷嚽穩暋蓆玉慹櫝呖芹倮朞擆玈一一一亘一丄一一渲一侀一丩一丁一一尌渀亀一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一丁捈灹挴瀏稘怣揞烼吀一劈畻皮刀丄澤姨什丄烣椴箵蘭虭先诚纄瀧幈繺凴焇蠒怣幀圠俈怠詁潭毃捒嚞挅敁掐捅嬢凬删跰忔蝉災劈筸嚀峋敒茢域蠮伀丂埁滸淨巤偵媑嚧稅侀距啓怏蘂歟粇蘈一簿淿跿礊蠜渠丂蛿跿跴瀏刐擐揄卹佟数貅稈一簿緿跿秧滾丰谖夀一嘇稉舏潞縐丁嚍整姰昀一怢毮熰崀丒咐綠儀丒妍竒蓗溷澴嬣蕫倒暝朢埐怰沃謧俾劒帜朤俎裒劈荷庿侀一伢埞蠬仰丁嚸蓍奭氋氛廒嵶稡垉莒咐嶠儀丒嚝匣俩巒樟虉圁膒帜朦奄圂剈矠僫仑感朄嶾翠趆忐皃谙廸敘一丒暷纐幉烝偁漢嬕粄缀伢嬍盄縀冣码一岱茦奼圄劘篐爘怣彙穌帀怣廘幌一蠼繐丁侉翓晟柑晅潿蕕嬦奄圆周嫠筴怒囕蕂贆一丄瀧注亃縀伡眳蠀縀伢蛛嬭筸奸楃怽蒰漢埐怰沃謣俺劒东地矶怀此瀴謔刀七唃瘓净七唁厅跃虉添跿幣承谏蘆毑劈舷昀一劆娒佈乲巾伢嬽譃縀冣欎一妀刀一衚巯跿盐一下燯跿跺掟觿跨繀一僣諿跿貔移跿怣懘湀一蠪廠丁劉谺慯觿赈煏檐言仨獃渀僠倀一岒击跿怣懝娼一蠟绠丂蘃一与爫賿跒囓蕰崀为咐蘀亸伀一冧苽跿芈苷洏一岅娸一簁帀七矞赿跴瀴诧净与滴尀丮习一仩耿淿謢嬽覃縀冠甎一妀樀一衬緟跼崟丌淿跽蟿跿蛿跿趥跿跻緿跿艿跿趟跿跕抈疕嚍嵵绰七盺兀丄瀴謘刀与熸嬀丒囓苘帀为尠舀么煏慱一仨莃帀伢嬽射一冣堍一劈苵倐一岋蘴一怣懕繀一敺椐舀亐爤協瀧獁提捤单佔拒嘞肠一丒暜茦埖怢涶栌购怢敜濔捈灼犈獷幈烁橱一乌烈儜疬荈煭意跿赈灷貆訴一幯縐一亅縃虖済一怢苙伢叉凢厰嘀么灗欄拇版烕檆栌蠭歃劈稖吐一勈竣礘怢檴瀴菭净丄瀧旨蛃一伢埙恢橴萗贏漪帀丁嚅聃虊稀一怠涐刀帀凣柠一么灓樄瀭诐婽焜冣弌一噜举嘹乀丈甌翿愢葜伲埦粀帀丂蜂一丄吧久婲沉舰一怠趏訾刚乀丈獷幉曳劆畆愤恤犌喨湄乸皝唇真繾渠唪嬜荀一一矚幣捁懾出佃虰娄一怣廙訄一怘罉匠俊跸犘甚凋侺涰一乁緀渀七睩乀丄萗牵唒囓扤崀丒嚷蕃瘋儀丄琧剈潰仸悤一丯跠一乌灿粏測一緿縀丁媉趺岰稀亾乀一僫諿净勈痝媉虺寀稀么潰啂謲執灱狈疪蜸恄渎濤唀丒吿僨伀一勈疽媉豺妀稀么潰啛膧洀一劈笗噦滎僗帡媉跺嗠稀久婿芈笗幦滎僐谓倀一勈疟癥僀与瓔一丐槰戀一衪渀丁便侀一冦洀一创訌一为杀一义灱瘼娣礓恢橮稹垉羠誰憬呉灱瘼娪凃启跠一乌灿粂昬一緿縀丁媉趺侐稀乌災苈算乄灹狈疪埙蠯繠丁噣訮渐一乌灻苈痧盾傀丄瀗乴墓嚟欲埦蠾溠丁嚋彲周嫠筴倓嚟趢谊一嚷蕃皰傀丄拇跫侐槰帀一弢涄瀇动一丅笅橁敐揤卽毃枤启跿赪趿跶移跿捿跿譗跿跚緿跽捈灹戕欅摁挔芈旽艶恢浴瀗葴歒暜蜢埓恢淋跸一专嚟覡渊一姿言一愢淮潌堀丯渐一人贿绰伢域愢氞漐堀丒噜俐赈灷蚜朲埲籎劑嘃盡佀丄澏纺乀一伲執愢涞満堀丒噜俖誸伀一冬庸什一冬垸亀一冬倱縖舕缅汁旗樵挢埥幕舕朅捁挔茈旽虨幢浸旙虨恢櫤琧捁灿劈苗嘌一妠嘀一弢淾渜堀丮総証乄灹苈疻盟偀丄瀗乴嵓嚞谧呌灼禓漤怀蠓乐丁噣萑嚟謲埶怢殮焼圀丒冝濷冸伀一冬庸什一冬垸亀一冬倱縒嘼帡楁攐揔卹佟数荔瀧獁提捤单佔拒嘞肠一丒暜缢坕縒暟挢埻枠臲菔恈灗欄瀬厢儀丄耬縱蓺腴瀶茰跿跴瀧淨悂帀伆贁一丈攀嶅搀渀伢奍爒噜爾噋亀丄瀧噈灗欄拇葈灲葤名謀奓嚖蔡茌怢繕爰一愢膎穉嚍孰纰丁媉觺妐渀义灱苈箷乍潿绸慈一丒噝稾勔一丄瀇褁丄一谷唀一劈篷帱讌樎炨嘀両樀谣吁一刘甘翿怢毫瘄一丮帠一乁灰剓唧癹倀丄瀏蛿凡塰刀义灱嚝甇蜟繺忐啦埈繾丸嶇蘩繠訑勇乁渏偏蘾拀恣懄张俀灷炜朲埪蠁习丁噣訮渐一乌灻苈痧瘟倀丄瀗丏漆縐丁媉蟒嚝覠攈一劈笗噦滎僗帡媉跺宰樀乄災貌舜一彌淾狔伀丐槰嘀一衊渐丁宅讝忄瀴菅傀丄瀭诐蠭繰丁垉羒噜举刃乀丄耧藨畁縀价谀一啐眲執蠣湰七礊灱苈痛盖俀下蘄一丮渀乀乌灹苈症癿俀丄瀧内蓃蛨樀一愢浾潨唀丠趏译劃谏敓挲執蠒买丂叀欌芈略囁虈劋瘀一一帀丁嘁艒吽嬇各匏曕稉囁豈刘渐嫫傢橴耧蓨杁縀伲埧灷狈疪蜑七渎熤刀丒吿僨伀一勈疽媉豺乀樀么潰仸掇跿跐槰帀一裏芈笗噦滎僗帡媉跺娰昀久婿芈笗幦滎僗庁媉诺壠昀仫厐槰戀一裃爛記一为繤哼儀一剈痡嚁缪一丁楁攐揔卹佟数荔瀧獁提捤单佔拔劈旽舧恢浴瀗葴塒暜缦埖恢淞潸吀丏淠一乵喓嚞趡崆一岱裠儀一岛縀一簀渀七瞲一丈甝媉覺嘰昀亾乀一僨一刀勈疝媉衺僀昀么灰虝稾岆一丄耧編俁渀倏蛿欑嘿滵茵愢泾燔匀両樇廍嚉葒娞劁嚺一一丄一丒丝匡燓幱湁延孛互娟犁侈伃岰砧啌灻粁嘘一愢汸畹媉誮弐丸仨玀縀伡燰粀帀丁媉诓嚟疢缅一劈攀嶅晿跿賠刀一岰囇么滱亅笅橁敐揤卽毃捒嚞挅敁掐捔卑慈滻侄瀥揀灟欈旼嶈赀一倧膅讃蚏瘀一恢櫬昄人亀一倭诐怢櫮濨匀丒嚜哠唀一劈巤倏然縀丂坝脑愞茆举趐廹攕匁襒搽茦嬴單渀乀么塶皷蕃癀佀丄琧喅蓟纔搗贏熨帀丁匱蜑晟诹廆彵縋瘄一丢藝伢孵菺估戀亊彵臃菔抺乀一倭诐怣敝涣褄一嚤敝匁赡娇幍坣腐橠常譄煚帤吡刎乺繤哰伀一勈痝劉覒嚵蔁嚉蒮弐丸仨桀渀伱燸烟櫄瀧汌灾粌渐一形汔继蘏煓淿跾蘄一与穂蘃一与稦蘂一与稈翀怠詁潭作幗戕蜅浝绤圅挢埥幕舕朅打怘詤羧亓園朤甇瘠幀洄性仁蠇舜嗠偁买刨舓匀一丄劧乂煓乯谏蜅毈犈艷唁一劆娲奈乶淾吏嘆裃昼丣礈滲乎税净傐帟倏哹氞拆崹匱蜒榠一一一巳謦褀一丏諼一息渄蘁尀憀勤拇赊烇側渿奈灷犌喸偌噵犈略囁衁勂啥嘉詒嚝蜣修侠池七贿怂櫬喬嚁蛿臰丁嘉諓丟嬠巋悢忏眧跇恠詀欴蟌涬岰朔翿彌汄搗丏漄帐丁吏箃側耧坈繺帤琏漃恰氐蜤埉幠趀刾勒一丄瘾豌埀抈甹囁螁瘞昀贀专亜蜢凡仒娞剑垉聒废匆凸亃虊帀一悃觤纜偈灳犌喘媁螀一訁娉膒嘾刽囁虇劘甥圉詐昿渍艺悃觤纜先灳犌喘抁螀一丽娉膒嘾刽囁虈犘甥圉詐昿渑艐悃觤纜剈灳犈喛一一劌喘桌偳犈嶄赈繸悤琧坉偼战巠却坒滻蜰甅怢櫤瀇瓀一丄焇琢愂櫤瀏漿怰氓传埱恢檔烥尀憀勠伸乌乲抨爳衈曲婤師谽弢剀秽楁攐揤卽毃枤勏觿赂趿跴姻跿忿緿謟賿跔淯跽噣羑愜倁訇趏敓茐嶾弁跴吵仿滾乗檹嚍兲帐丁噣传技唣跠滱綮穦准谺罈崛詁簀帀七礉滱絤哠吀一協瀧獁提捤单佔拢洌嗠淁蠇帟倧俁豀蘾几矈庣拀処叉氞苆崥匱蜒榠儣資趱跬欦褀一一七諿息渀一仼跀丄瓼一縿绰一久婻抨穳絈凲芘苒案灼拂啥嚉諓借嬢嬌瑒嚟嬣俣伓借笠埋怰池标琀跏縄渧汈凳犨狐灉跱折崐啍屳嗫熬呅婻打喑刁縑晜举勠一丄砬諯煓褬喤岃虀蛘胧图跿舨渰灁滾丐谒谀一劈萾胿穿蚜複簆湹緀一争胰沱怏焃偼舨潰瀁幠趀嘾劓一丈画修儠汯一一繺忀病傈愈渤吏蘃欞劋糋趱跬淿跽嘁賢毬喸抁螼一丁嚉葒娞犊凡凂洔堡娢仐昿渑艉怢殔焇眚湸樀一么繺肨嶌贉胐皅纈剁滾乗庡嚹窿褟資趱跒东謢培怰沒堇激一丄焇細滹臰甽傈洈湕笅橁敐揤卽毃悿緿謃賿跐巯跽叾跿艟觿赕趿跿誖簃一已擀儀丿聛嘌一跉楀娀仿坭渰七败簀縀凼玺什丏誖訃一已擸儀丿聜丌一跉樠娀仿坱丰七败羀縀凼珈什丏誗堃一已攰儀丿聜蘌一跉欀娀仿坴渰一一愣忑爌一幔跲护儀两咀一一衹緿跽瘕一与畳跿跚倠一仩芿跿讠縀一岜燿跿栏帀七瞾跿跶漨一为楏跿赨揀一冦磿跿蒆帀一表巿跽癲一与瑛跿跚嗠一仩焿跿订娀一岘姿跿栦一七睸跿跶炘一为擯跿赨筀一冥狿跿蒌嘀一衖緿跽盏一与獃跿跚局一仩徿跿讣脀一岓臿跿栀渐七眲跿跷寁獮月商玵猺嘉擇掵脊丘琗宔缶嫎充讕聲旙著彽瑩椙揷宥补丘琗宔缶嫎充讕聲旙瓷侕籟槝敇俕艟枚擆戁灡櫙愓曌蘴旙攧坽瑯標擥讥籰歝叶枥穥丘琗宔缶嫎充讕聲旝蔦珑獟枚擆戁灡櫙愓曌蘴旙攧坽絰杛珶玹繵欗葦玱猀暘收拄萳對叶揉聟楘攅讥籰歝叶枥穥丘琗宔缶嫎充讕聲旜瑖厑浦桛呐侉潳杌慣嫠舀廛蔇珉睧栝倂澌眠媌儣嚁呵楚搖莄湍桛琖莽良如爦反猱完膃庀耮媋焢亡剥曈儓忑瘠媌儣嚤簠捜萖殔蠀暘收拄萳對倅窵獤欗怅箥籰歝呦玱獝嘖蓷揑繵欙璖羕欀嘈僖戤坥榘蓶徔丠嘋摀爥牥曛葆戀渠奝亐珍癯毈唷侕籤嘝咖莔丠嘚擧俕艦桛呐珁潳櫈僒俑素檙搖庁瑲槛怇寑物榀倂侽荴樝敆枥穥停吗富渭嘝哲保聩欙怇徼湳欙哷提乷暀唦嘃賿一丐一东一一嘀一圀一一一三一一倀一伐稐俑搁帚帬一崀一仰一丛忀一一一净一七一一縀嘀夀丠一一仒一一娃一璀娀佘侀丏樘丁瘃一儐尀乀一丄伀乀帀一一一一一一一一一一一一一一一一一仰唀一刀一貇一丄一丁俐一伀一仡舀丁一丁湴一乀一予欀一帀一稝一丐一丶啀一刀一帇帀丄一丒濐一伀一十舀丁一丅虴一乀一侠欀一帀丁耝一丐一乼啀一刀一澇帀丄一两俐一伀一垡舀丁一上年一乀一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一丁劈湠勀一久也旗蔷徑睮樀北嘢幀旗菷寑牯歝唀偁乤汛呅词艵暗萦玹牥檀圇嚀彀旘蓆讍祟柙敇徥筥两万嚠彀旘蓆词猀爀唣久也枘蓆词猀爀唣湅也枙著後亐东爁匁浦槜呖蘂帀檒伔佽瑰歝吰偀乲戄戅讙聥晙三丁聘剐叶柝聩欙帉丁聠剐叶莵潰两万垠彀旛敖螵潰两万埀彀旛蔆掸亐东疁匁浰杜甦诈亐东瘀剅也樜璖蟑琀爀唨渄彀旜啗忌亐东眀剅也檙搖市帀檦丑匁浳欘敂弥屏弑慣市帀檨丑匁浳欜瓆掸亐东碀剅也歛瑶揑焀爀唫丄彀旝蔦珑猀爀一卼丅丁珶莡浥氙搷揑獟栙搖徕耀慙著彽腴晜畅讵脀扛搖玸乖暘收拄萳對台佭牥曘畖昃圁杛琶埕琀膀帠一七丩佰丌们叀一垕籣槙呐侹牥曛葆戂搁一珶昁蔀緀帀宥穥両縗丂威最圐刌二喀丰凰焀什垲戀丂旙渊丄仄乀丶玱猀稀攀僔佤丮渐娂舦一縏檬七両烠丌仄娀丰冠舀什娄刀刀舰戀一一丩佴焐卜訁柰呤促佣縫蘊爄一一偐尀万一布爑一侀丐乐咀丁渀刀指一习丄丧帐一封一夀蘀丁一一嘀一净开一一一帀一搀一仰刀乨咀一刀一堀一丼伀丁潰一伀一凐一丏乀七幌一乀一佐一七縐七蔕一丐一乩一一訄一弆一丄一丞縀一崁一垱嘀丁一三一一净帀丰崀一帀丂甀一仰刀仼剀一刀一紀一丼圀丰倀一伀一婀一丏偀不亀帀乀一儰一七縐丂爋一丐一仚一一訄一褂縀丄一丸一一伀一帀一一一与瘀一乀一刀一一一七茀一丐一伀一一一一伀帀丄一乀一一一一亰刀丁一丐一一一一乌伀一帀丄一一一一业乀一刀丁一一一一丈帐一伀一帀一一一丂渄一乀一刀一一一一紁一丐一伀一一一一寀帀丄一乀一一一一凐刀丁一丐一一一一伔伀一帀丄一一一一之乀一刀丁一一一一且縐一伀一帀一一一丅稄一乀一刀一一一丁漁一丐一伀一一一一柀帀丄一乀一一一一啐刀丁一丐一一一一俴伀一帀丄一一一一亅乀一刀丁一一一一丣丐一伀一帀一一一丁一一剀一么一丄縀一戀一佐一世一丁樀一吀一乤一丆渀一椀一俀一丝一丁蘀一嗀一亀一丈帀一瀀一一丁与一一言一囀一乀一丄帀一怀一估一且一丁戀一厀一乜一丆一一最一侠一丛一丁縀一啀一乸一万縀一渀一倐一丢一丂丁浟楚叶握獣歝呕计獡朙攠佽灡櫙愓曌蘴旙呖宽牥丗萦反猱完膃彽牥曛葆捽瑤丗萦反猱完膃彽牥曛葆捽瑩椙帅讉潳杌慣嫠艟朙搶讑獟果丅讉潳杌慣嫠艟杛琶讑猀旘琗宔缶嫎充讕籣槙呕讙爀旘琗宔缶嫎充讕籣槙呕讙睬杀叶垅腥婍焳滑浥榘蓶徕浦樀叶徕煢歙清讕籣暝摠佽略欗蔷待聴旛攰佽筡桛清譽浳欙咖蟀也旗蔷徑絵欜丅讍穯曚菶殕艴桛摐佽煬槜葐佽瑣椛蔶戁浦柙敆威浦槜呖蘁浦樝敆威浦檙搖币浦毜璗徔也楛搗丁浭歛瓖叀也槜呖蘁浰杜甦诈也樜璖蟑琀旜啗忌也檙搖币浳欘敂弥屏弑慣币浳欜瓆掸也歛瑶揑焀旝蔦珑猀朞擆彽腴歘珶垥籤杜清证聩榝号揍潧杀一一一一㴁 + 臾糟蘜一乀縀倀倀一仰一习佀丈戀渀一一乤一丒一丁浟成扴捩卒懀一一一一一一一一一一伀一一一一一一一一一一一一一一一一一一一丙一不渄一旗荄捡戀一一一一一一一丁一一亀一一一一一一一一丠一一一丅一一戀一佀一一一丗菷徕虴一一一一一丅譽扅搕一一一一一丂爋一丐一仈刀一一一眂縀丈一一一一一一一市一一一一一一一佽浳欝搧娀一一一一也旕剕潐一一一一一丛俀一伀一唠一一一丆繰一乀一一一一一一嘄丠一一丆一一一一旗蔷忕灟栙擇侕耀一叵譑単挀一一一一一冀樀一帀七尀一一一仠唀一嘀一一一一一一乀倀一一一一一一丅譽煳欜璖螜一一一丁浟挑掅帀一一一一一禇帀丄一丸帐一一一壡舀一一一一一一一丈一一一一一一一一也旝擧殥籤旚擦枼一丗菵引晔一一一一一三乼一乀一俀一一一丂帟一丠一一一一一一一一一一一一一一一侐一予乀丅譽剁挐帀一一一一一丠一丐一一刈一一一丈一一一一伀一一一丰一七一一帀一一一佽浮椗蔷玵灯椗蔇忈也旑刕弄一一一一一一倀一伀一亀一一一一亀一什一一一一一一吀一估一一一一一一旗葶诐一一一一一一叵謑佔幀一一一一一丠渀一帀一昀一一一丈嘀一娀一一一一一丁渀一戀一一一一一丅譽穡旜薖莉絬旜啇嘁浟弐捄刀一一一一一嘈一丄一並一一一一倂一七一一一一一一东一丅縀一一一一一也旘蓶莵絮一一一一丗菴弅扁一一一一一丌亀一乀一丰丠一一一一一乀一一一一一一乀一一一一一一一一侐一么一丅譽婉憒艔弥戀一一一丰嘀丐一一刀一一一丌一一一丼习一一一丐一丁一一一一一一予一渌一一丰一亀一丈娀七一一一一一一与儀一币一劃刀付一一嘀一吀一你耀三一丁丵一夀刀下一丅一一一一丄一一帀一嬀一仠一世一一一一一一一一一一一一一一一亘嬀丂瘀一一一一一一一一一一仠一丠一一縀一姝攷嚽穩暋葇玱爀一一一丛一丁渀一斪罒跻舷圪讫惙硗垚愠一丠一一刀一七溠一崊一帀一儀一一么倪一丁一一一一一一上一倀昀一峀稀一一一一一一一丰一与一一昀一丠一一一幐一伀姝攷嚽穩暋蓆玉慹櫝呖芹倮朞擆玈一一一亘一丄一一渲一侀一丩一丁一一尌渀亀一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一丁捈灹挴瀏稘怣揞烼吀一劈畻皮刀丄澤姨什丄烣椴箵蘭虭先诚纄瀧幈繺凴焇蠒怣幀圠俈怠詁潭毃捒嚞挅敁掐捅嬢凬删跰忔蝉災劈筸嚀峋敒茢域蠮伀丂埁滸淨巤偵媑嚧稅侀距啓怏蘂歟粇蘈一簿淿跿礊蠜渠丂蛿跿跴瀏刐擐揄卹佟数貅稈一簿緿跿秧滾丰谖夀一嘇稉舏潞縐丁嚍整姰昀一怢毮熰崀丒咐綠儀丒妍竒蓗溷澴嬣蕫倒暝朢埐怰沃謧俾劒帜朤俎裒劈荷庿侀一伢埞蠬仰丁嚸蓍奭氋氛廒嵶稡垉莒咐嶠儀丒嚝匣俩巒樟虉圁膒帜朦奄圂剈矠僫仑感朄嶾翠趆忐皃谙廸敘一丒暷纐幉烝偁漢嬕粄缀伢嬍盄縀冣码一岱茦奼圄劘篐爘怣彙穌帀怣廘幌一蠼繐丁侉翓晟柑晅潿蕕嬦奄圆周嫠筴怒囕蕂贆一丄瀧注亃縀伡眳蠀縀伢蛛嬭筸奸楃怽蒰漢埐怰沃謣俺劒东地矶怀此瀴謔刀七唃瘓净七唁厅跃虉添跿幣承谏蘆毑劈舷昀一劆娒佈乲巾伢嬽譃縀冣欎一妀刀一衚巯跿盐一下燯跿跺掟觿跨繀一僣諿跿貔移跿怣懘湀一蠪廠丁劉谺慯觿赈煏檐言仨獃渀僠倀一岒击跿怣懝娼一蠟绠丂蘃一与爫賿跒囓蕰崀为咐蘀亸伀一冧苽跿芈苷洏一岅娸一簁帀七矞赿跴瀴诧净与滴尀丮习一仩耿淿謢嬽覃縀冠甎一妀樀一衬緟跼崟丌淿跽蟿跿蛿跿趥跿跻緿跿艿跿趟跿跕抈疕嚍嵵绰七盺兀丄瀴謘刀与熸嬀丒囓苘帀为尠舀么煏慱一仨莃帀伢嬽射一冣堍一劈苵倐一岋蘴一怣懕繀一敺椐舀亐爤協瀧獁提捤单佔拒嘞肠一丒暜茦埖怢涶栌购怢敜濔捈灼犈獷幈烁橱一乌烈儜疬荈煭意跿赈灷貆訴一幯縐一亅縃虖済一怢苙伢叉凢厰嘀么灗欄拇版烕檆栌蠭歃劈稖吐一勈竣礘怢檴瀴菭净丄瀧旨蛃一伢埙恢橴萗贏漪帀丁嚅聃虊稀一怠涐刀帀凣柠一么灓樄瀭诐婽焜冣弌一噜举嘹乀丈甌翿愢葜伲埦粀帀丂蜂一丄吧久婲沉舰一怠趏訾刚乀丈獷幉曳劆畆愤恤犌喨湄乸皝唇真繾渠唪嬜荀一一矚幣捁懾出佃虰娄一怣廙訄一怘罉匠俊跸犘甚凋侺涰一乁緀渀七睩乀丄萗牵唒囓扤崀丒嚷蕃瘋儀丄琧剈潰仸悤一丯跠一乌灿粏測一緿縀丁媉趺岰稀亾乀一僫諿净勈痝媉虺寀稀么潰啂謲執灱狈疪蜸恄渎濤唀丒吿僨伀一勈疽媉豺妀稀么潰啛膧洀一劈笗噦滎僗帡媉跺嗠稀久婿芈笗幦滎僐谓倀一勈疟癥僀与瓔一丐槰戀一衪渀丁便侀一冦洀一创訌一为杀一义灱瘼娣礓恢橮稹垉羠誰憬呉灱瘼娪凃启跠一乌灿粂昬一緿縀丁媉趺侐稀乌災苈算乄灹狈疪埙蠯繠丁噣訮渐一乌灻苈痧盾傀丄瀗乴墓嚟欲埦蠾溠丁嚋彲周嫠筴倓嚟趢谊一嚷蕃皰傀丄拇跫侐槰帀一弢涄瀇动一丅笅橁敐揤卽毃枤启跿赪趿跶移跿捿跿譗跿跚緿跽捈灹戕欅摁挔芈旽艶恢浴瀗葴歒暜蜢埓恢淋跸一专嚟覡渊一姿言一愢淮潌堀丯渐一人贿绰伢域愢氞漐堀丒噜俐赈灷蚜朲埲籎劑嘃盡佀丄澏纺乀一伲執愢涞満堀丒噜俖誸伀一冬庸什一冬垸亀一冬倱縖舕缅汁旗樵挢埥幕舕朅捁挔茈旽虨幢浸旙虨恢櫤琧捁灿劈苗嘌一妠嘀一弢淾渜堀丮総証乄灹苈疻盟偀丄瀗乴嵓嚞谧呌灼禓漤怀蠓乐丁噣萑嚟謲埶怢殮焼圀丒冝濷冸伀一冬庸什一冬垸亀一冬倱縒嘼帡楁攐揔卹佟数荔瀧獁提捤单佔拒嘞肠一丒暜缢坕縒暟挢埻枠臲菔恈灗欄瀬厢儀丄耬縱蓺腴瀶茰跿跴瀧淨悂帀伆贁一丈攀嶅搀渀伢奍爒噜爾噋亀丄瀧噈灗欄拇葈灲葤名謀奓嚖蔡茌怢繕爰一愢膎穉嚍孰纰丁媉觺妐渀义灱苈箷乍潿绸慈一丒噝稾勔一丄瀇褁丄一谷唀一劈篷帱讌樎炨嘀両樀谣吁一刘甘翿怢毫瘄一丮帠一乁灰剓唧癹倀丄瀏蛿凡塰刀义灱嚝甇蜟繺忐啦埈繾丸嶇蘩繠訑勇乁渏偏蘾拀恣懄张俀灷炜朲埪蠁习丁噣訮渐一乌灻苈痧瘟倀丄瀗丏漆縐丁媉蟒嚝覠攈一劈笗噦滎僗帡媉跺宰樀乄災貌舜一彌淾狔伀丐槰嘀一衊渐丁宅讝忄瀴菅傀丄瀭诐蠭繰丁垉羒噜举刃乀丄耧藨畁縀价谀一啐眲執蠣湰七礊灱苈痛盖俀下蘄一丮渀乀乌灹苈症癿俀丄瀧内蓃蛨樀一愢浾潨唀丠趏译劃谏敓挲執蠒买丂叀欌芈略囁虈劋瘀一一帀丁嘁艒吽嬇各匏曕稉囁豈刘渐嫫傢橴耧蓨杁縀伲埧灷狈疪蜑七渎熤刀丒吿僨伀一勈疽媉豺乀樀么潰仸掇跿跐槰帀一裏芈笗噦滎僗帡媉跺娰昀久婿芈笗幦滎僗庁媉诺壠昀仫厐槰戀一裃爛記一为繤哼儀一剈痡嚁缪一丁楁攐揔卹佟数荔瀧獁提捤单佔拔劈旽舧恢浴瀗葴塒暜缦埖恢淞潸吀丏淠一乵喓嚞趡崆一岱裠儀一岛縀一簀渀七瞲一丈甝媉覺嘰昀亾乀一僨一刀勈疝媉衺僀昀么灰虝稾岆一丄耧編俁渀倏蛿欑嘿滵茵愢泾燔匀両樇廍嚉葒娞劁嚺一一丄一丒丝匡燓幱湁延孛互娟犁侈伃岰砧啌灻粁嘘一愢汸畹媉誮弐丸仨玀縀伡燰粀帀丁媉诓嚟疢缅一劈攀嶅晿跿賠刀一岰囇么滱亅笅橁敐揤卽毃捒嚞挅敁掐捔卑慈滻侄瀥揀灟欈旼嶈赀一倧膅讃蚏瘀一恢櫬昄人亀一倭诐怢櫮濨匀丒嚜哠唀一劈巤倏然縀丂坝脑愞茆举趐廹攕匁襒搽茦嬴單渀乀么塶皷蕃癀佀丄琧喅蓟纔搗贏熨帀丁匱蜑晟诹廆彵縋瘄一丢藝伢孵菺估戀亊彵臃菔抺乀一倭诐怣敝涣褄一嚤敝匁赡娇幍坣腐橠常譄煚帤吡刎乺繤哰伀一勈痝劉覒嚵蔁嚉蒮弐丸仨桀渀伱燸烟櫄瀧汌灾粌渐一形汔继蘏煓淿跾蘄一与穂蘃一与稦蘂一与稈翀怠詁潭作幗戕蜅浝绤圅挢埥幕舕朅打怘詤羧亓園朤甇瘠幀洄性仁蠇舜嗠偁买刨舓匀一丄劧乂煓乯谏蜅毈犈艷唁一劆娲奈乶淾吏嘆裃昼丣礈滲乎税净傐帟倏哹氞拆崹匱蜒榠一一一巳謦褀一丏諼一息渄蘁尀憀勤拇赊烇側渿奈灷犌喸偌噵犈略囁衁勂啥嘉詒嚝蜣修侠池七贿怂櫬喬嚁蛿臰丁嘉諓丟嬠巋悢忏眧跇恠詀欴蟌涬岰朔翿彌汄搗丏漄帐丁吏箃側耧坈繺帤琏漃恰氐蜤埉幠趀刾勒一丄瘾豌埀抈甹囁螁瘞昀贀专亜蜢凡仒娞剑垉聒废匆凸亃虊帀一悃觤纜偈灳犌喘媁螀一訁娉膒嘾刽囁虇劘甥圉詐昿渍艺悃觤纜先灳犌喘抁螀一丽娉膒嘾刽囁虈犘甥圉詐昿渑艐悃觤纜剈灳犈喛一一劌喘桌偳犈嶄赈繸悤琧坉偼战巠却坒滻蜰甅怢櫤瀇瓀一丄焇琢愂櫤瀏漿怰氓传埱恢檔烥尀憀勠伸乌乲抨爳衈曲婤師谽弢剀秽楁攐揤卽毃枤勏觿赂趿跴姻跿忿緿謟賿跔淯跽噣羑愜倁訇趏敓茐嶾弁跴吵仿滾乗檹嚍兲帐丁噣传技唣跠滱綮穦准谺罈崛詁簀帀七礉滱絤哠吀一協瀧獁提捤单佔拢洌嗠淁蠇帟倧俁豀蘾几矈庣拀処叉氞苆崥匱蜒榠儣資趱跬欦褀一一七諿息渀一仼跀丄瓼一縿绰一久婻抨穳絈凲芘苒案灼拂啥嚉諓借嬢嬌瑒嚟嬣俣伓借笠埋怰池标琀跏縄渧汈凳犨狐灉跱折崐啍屳嗫熬呅婻打喑刁縑晜举勠一丄砬諯煓褬喤岃虀蛘胧图跿舨渰灁滾丐谒谀一劈萾胿穿蚜複簆湹緀一争胰沱怏焃偼舨潰瀁幠趀嘾劓一丈画修儠汯一一繺忀病傈愈渤吏蘃欞劋糋趱跬淿跽嘁賢毬喸抁螼一丁嚉葒娞犊凡凂洔堡娢仐昿渑艉怢殔焇眚湸樀一么繺肨嶌贉胐皅纈剁滾乗庡嚹窿褟資趱跒东謢培怰沒堇激一丄焇細滹臰甽傈洈湕笅橁敐揤卽毃悿緿謃賿跐巯跽叾跿艟觿赕趿跿誖簃一已擀儀丿聛嘌一跉楀娀仿坭渰七败簀縀凼玺什丏誖訃一已擸儀丿聜丌一跉樠娀仿坱丰七败羀縀凼珈什丏誗堃一已攰儀丿聜蘌一跉欀娀仿坴渰一一愣忑爌一幔跲护儀两咀一一衹緿跽瘕一与畳跿跚倠一仩芿跿讠縀一岜燿跿栏帀七瞾跿跶漨一为楏跿赨揀一冦磿跿蒆帀一表巿跽癲一与瑛跿跚嗠一仩焿跿订娀一岘姿跿栦一七睸跿跶炘一为擯跿赨筀一冥狿跿蒌嘀一衖緿跽盏一与獃跿跚局一仩徿跿讣脀一岓臿跿栀渐七眲跿跷寁獮月商玵猺嘉擇掵脊丘琗宔缶嫎充讕聲旙著彽瑩椙揷宥补丘琗宔缶嫎充讕聲旙瓷侕籟槝敇俕艟枚擆戁灡櫙愓曌蘴旙攧坽瑯標擥讥籰歝叶枥穥丘琗宔缶嫎充讕聲旝蔦珑獟枚擆戁灡櫙愓曌蘴旙攧坽絰杛珶玹繵欗葦玱猀暘收拄萳對叶揉聟楘攅讥籰歝叶枥穥丘琗宔缶嫎充讕聲旜瑖厑浦桛呐侉潳杌慣嫠舀廛蔇珉睧栝倂澌眠媌儣嚁呵楚搖莄湍桛琖莽良如爦反猱完膃庀耮媋焢亡剥曈儓忑瘠媌儣嚤簠捜萖殔蠀暘收拄萳對倅窵獤欗怅箥籰歝呦玱獝嘖蓷揑繵欙璖羕欀嘈僖戤坥榘蓶徔丠嘋摀爥牥曛葆戀渠奝亐珍癯毈唷侕籤嘝咖莔丠嘚擧俕艦桛呐珁潳櫈僒俑素檙搖庁瑲槛怇寑物榀倂侽荴樝敆枥穥停吗富渭嘝哲保聩欙怇徼湳欙哷提乷暀唦嘃賿一丐一东一一嘀一圀一一一三一一倀一伐稐俑搁帚帬一崀一仰一丛忀一一一净一七一一縀嘀夀丠一一仒一一娃一璀娀佘侀丏樘丁瘃一儐尀乀一丄伀乀帀一一一一一一一一一一一一一一一一一仰唀一刀一貇一丄一丁俐一伀一仡舀丁一丁湴一乀一予欀一帀一稝一丐一丶啀一刀一帇帀丄一丒濐一伀一十舀丁一丅虴一乀一侠欀一帀丁耝一丐一乼啀一刀一澇帀丄一两俐一伀一垡舀丁一上年一乀一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一丁劈湠勀一久也旗蔷徑睮樀北嘢幀旗菷寑牯歝唀偁乤汛呅词艵暗萦玹牥檀圇嚀彀旘蓆讍祟柙敇徥筥两万嚠彀旘蓆词猀爀唣久也枘蓆词猀爀唣湅也枙著後亐东爁匁浦槜呖蘂帀檒伔佽瑰歝吰偀乲戄戅讙聥晙三丁聘剐叶柝聩欙帉丁聠剐叶莵潰两万垠彀旛敖螵潰两万埀彀旛蔆掸亐东疁匁浰杜甦诈亐东瘀剅也樜璖蟑琀爀唨渄彀旜啗忌亐东眀剅也檙搖市帀檦丑匁浳欘敂弥屏弑慣市帀檨丑匁浳欜瓆掸亐东碀剅也歛瑶揑焀爀唫丄彀旝蔦珑猀爀一卼丅丁珶莡浥氙搷揑獟栙搖徕耀慙著彽腴晜畅讵脀扛搖玸乖暘收拄萳對台佭牥曘畖昃圁杛琶埕琀膀帠一七丩佰丌们叀一垕籣槙呐侹牥曛葆戂搁一珶昁蔀緀帀宥穥両縗丂威最圐刌二喀丰凰焀什垲戀丂旙渊丄仄乀丶玱猀稀攀僔佤丮渐娂舦一縏檬七両烠丌仄娀丰冠舀什娄刀刀舰戀一一丩佴焐卜訁柰呤促佣縫蘊爄一一偐尀万一布爑一侀丐乐咀丁渀刀指一习丄丧帐一封一夀蘀丁一一嘀一净开一一一帀一搀一仰刀乨咀一刀一堀一丼伀丁潰一伀一凐一丏乀七幌一乀一佐一七縐七蔕一丐一乩一一訄一弆一丄一丞縀一崁一垱嘀丁一三一一净帀丰崀一帀丂甀一仰刀仼剀一刀一紀一丼圀丰倀一伀一婀一丏偀不亀帀乀一儰一七縐丂爋一丐一仚一一訄一褂縀丄一丸一一伀一帀一一一与瘀一乀一刀一一一七茀一丐一伀一一一一伀帀丄一乀一一一一亰刀丁一丐一一一一乌伀一帀丄一一一一业乀一刀丁一一一一丈帐一伀一帀一一一丂渄一乀一刀一一一一紁一丐一伀一一一一寀帀丄一乀一一一一凐刀丁一丐一一一一伔伀一帀丄一一一一之乀一刀丁一一一一且縐一伀一帀一一一丅稄一乀一刀一一一丁漁一丐一伀一一一一柀帀丄一乀一一一一啐刀丁一丐一一一一俴伀一帀丄一一一一亅乀一刀丁一一一一丣丐一伀一帀一一一丁一一剀一么一丄縀一戀一佐一世一丁樀一吀一乤一丆渀一椀一俀一丝一丁蘀一嗀一亀一丈帀一瀀一一丁与一一言一囀一乀一丄帀一怀一估一且一丁戀一厀一乜一丆一一最一侠一丛一丁縀一啀一乸一万縀一渀一倐一丢一丂丁浟楚叶握獣歝呕计獡朙攠佽灡櫙愓曌蘴旙呖宽牥丗萦反猱完膃彽牥曛葆捽瑤丗萦反猱完膃彽牥曛葆捽瑩椙帅讉潳杌慣嫠艟朙搶讑獟果丅讉潳杌慣嫠艟杛琶讑猀旘琗宔缶嫎充讕籣槙呕讙爀旘琗宔缶嫎充讕籣槙呕讙睬杀叶垅腥婍焳滑浥榘蓶徕浦樀叶徕煢歙清讕籣暝摠佽略欗蔷待聴旛攰佽筡桛清譽浳欙咖蟀也旗蔷徑絵欜丅讍穯曚菶殕艴桛摐佽煬槜葐佽瑣椛蔶戁浦柙敆威浦槜呖蘁浦樝敆威浦檙搖币浦毜璗徔也楛搗丁浭歛瓖叀也槜呖蘁浰杜甦诈也樜璖蟑琀旜啗忌也檙搖币浳欘敂弥屏弑慣币浳欜瓆掸也歛瑶揑焀旝蔦珑猀朞擆彽腴歘珶垥籤杜清证聩榝号揍潧杀一一一一㴁 From affc723f54b1f7470696d63fff5e5749981ddbee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Thu, 4 Apr 2024 15:26:21 +0900 Subject: [PATCH 13/35] chore: tidy documents & add test --- CMakeLists.txt | 26 +++++-- base16384.c | 43 +++++++----- base16384.h | 166 ++++++++++++++++++++++++-------------------- file.c | 4 +- test/CMakeLists.txt | 15 ++++ test/coder_test.c | 64 +++++++++++++++++ 6 files changed, 219 insertions(+), 99 deletions(-) create mode 100644 test/CMakeLists.txt create mode 100644 test/coder_test.c diff --git a/CMakeLists.txt b/CMakeLists.txt index edafedc..9fd796a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,32 +1,46 @@ cmake_minimum_required(VERSION 2.8.12) if (POLICY CMP0048) - cmake_policy(SET CMP0048 NEW) + cmake_policy(SET CMP0048 NEW) endif (POLICY CMP0048) project(base16384 VERSION 2.3.0) -add_executable(base16384_b base16384.c) +add_definitions(-DBASE16384_VERSION="${PROJECT_VERSION}") +add_definitions(-DBASE16384_VERSION_DATE="April 4th 2024") +message(STATUS "Testing endian...") include(TestBigEndian) test_big_endian(isBigEndian) +message(STATUS "Is big endian: ${isBigEndian}.") if (${isBigEndian}) add_definitions(-DWORDS_BIGENDIAN) -endif() +endif () -IF(CMAKE_SIZEOF_VOID_P EQUAL 8) +add_executable(base16384_b base16384.c) + +IF (CMAKE_SIZEOF_VOID_P EQUAL 8) + message(STATUS "Adding 64bit libraries...") add_definitions(-DIS_64BIT_PROCESSOR) add_library(base16384 SHARED file.c base1464.c) add_library(base16384_s STATIC file.c base1464.c) -ELSE() +ELSE () + message(STATUS "Adding 32bit libraries...") add_library(base16384 SHARED file.c base1432.c) add_library(base16384_s STATIC file.c base1432.c) -ENDIF() +ENDIF () set_target_properties(base16384_b PROPERTIES OUTPUT_NAME base16384) set_target_properties(base16384_s PROPERTIES OUTPUT_NAME base16384) set_target_properties(base16384 PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) +message(STATUS "Linking libraries...") target_link_libraries(base16384_b base16384_s) +if (BUILD STREQUAL "test") + message(STATUS "Building test...") + enable_testing() + add_subdirectory(test) +endif () + INSTALL(TARGETS base16384_b RUNTIME DESTINATION bin) INSTALL(TARGETS base16384 LIBRARY DESTINATION lib) INSTALL(TARGETS base16384_s ARCHIVE DESTINATION lib) diff --git a/base16384.c b/base16384.c index dffafaa..b5e9e24 100644 --- a/base16384.c +++ b/base16384.c @@ -39,7 +39,13 @@ unsigned long get_start_ms() { #endif static base16384_err_t print_usage() { - fputs("Copyright (c) 2022-2024 Fumiama Minamoto.\nBase16384 2.3.0 (April 4th 2024). Usage:\n", stderr); + #ifndef BASE16384_VERSION + #define BASE16384_VERSION "dev" + #endif + #ifndef BASE16384_VERSION_DATE + #define BASE16384_VERSION_DATE "unknown date" + #endif + fputs("Copyright (c) 2022-2024 Fumiama Minamoto.\nBase16384 "BASE16384_VERSION" ("BASE16384_VERSION_DATE"). Usage:\n", stderr); fputs("base16384 [-edtn] [inputfile] [outputfile]\n", stderr); fputs(" -e\t\tencode (default)\n", stderr); fputs(" -d\t\tdecode\n", stderr); @@ -102,12 +108,13 @@ int main(int argc, char** argv) { } base16384_err_t exitstat = base16384_err_ok; + #define do_coding(method) base16384_##method##_file_detailed( \ argv[2], argv[3], encbuf, decbuf, \ (no_header?BASE16384_FLAG_NOHEADER:0) | (use_checksum?BASE16384_FLAG_SUM_CHECK_ON_REMAIN:0) \ ) - exitstat = is_encode?do_coding(encode):do_coding(decode); - + exitstat = is_encode?do_coding(encode):do_coding(decode); + #undef do_coding if(t) { #ifdef _WIN32 fprintf(stderr, "spend time: %lums\n", clock() - t); @@ -116,20 +123,22 @@ int main(int argc, char** argv) { #endif } - #define print_base16384_err(n) case base16384_err_##n: perror("base16384_err_"#n) - if(exitstat) switch(exitstat) { - print_base16384_err(get_file_size); break; - print_base16384_err(fopen_output_file); break; - print_base16384_err(fopen_input_file); break; - print_base16384_err(write_file); break; - print_base16384_err(open_input_file); break; - print_base16384_err(map_input_file); break; - print_base16384_err(read_file); break; - print_base16384_err(invalid_file_name); break; - print_base16384_err(invalid_commandline_parameter); break; - print_base16384_err(invalid_decoding_checksum); break; - default: perror("base16384"); break; - } + #define base16384_perror_case(n) case base16384_err_##n: perror("base16384_err_"#n) + if(exitstat) switch(exitstat) { + base16384_perror_case(get_file_size); break; + base16384_perror_case(fopen_output_file); break; + base16384_perror_case(fopen_input_file); break; + base16384_perror_case(write_file); break; + base16384_perror_case(open_input_file); break; + base16384_perror_case(map_input_file); break; + base16384_perror_case(read_file); break; + base16384_perror_case(invalid_file_name); break; + base16384_perror_case(invalid_commandline_parameter); break; + base16384_perror_case(invalid_decoding_checksum); break; + default: perror("base16384"); break; + } + #undef base16384_perror_case + return exitstat; } diff --git a/base16384.h b/base16384.h index 6bf9e74..609503a 100644 --- a/base16384.h +++ b/base16384.h @@ -24,28 +24,23 @@ #include #endif -#define define_base16384_err_t(n) base16384_err_##n - - enum base16384_err_t { - define_base16384_err_t(ok), - define_base16384_err_t(get_file_size), - define_base16384_err_t(fopen_output_file), - define_base16384_err_t(fopen_input_file), - define_base16384_err_t(write_file), - define_base16384_err_t(open_input_file), - define_base16384_err_t(map_input_file), - define_base16384_err_t(read_file), - define_base16384_err_t(invalid_file_name), - define_base16384_err_t(invalid_commandline_parameter), - define_base16384_err_t(invalid_decoding_checksum), - }; - - /** - * @brief return value of base16384_en/decode_file - */ - typedef enum base16384_err_t base16384_err_t; - -#undef define_base16384_err_t +enum base16384_err_t { + base16384_err_ok, + base16384_err_get_file_size, + base16384_err_fopen_output_file, + base16384_err_fopen_input_file, + base16384_err_write_file, + base16384_err_open_input_file, + base16384_err_map_input_file, + base16384_err_read_file, + base16384_err_invalid_file_name, + base16384_err_invalid_commandline_parameter, + base16384_err_invalid_decoding_checksum, +}; +/** + * @brief return value of base16384_en/decode_file +*/ +typedef enum base16384_err_t base16384_err_t; #define _BASE16384_ENCBUFSZ (BUFSIZ*1024/7*7) #define _BASE16384_DECBUFSZ (BUFSIZ*1024/8*8) @@ -157,68 +152,91 @@ int base16384_decode(const char* data, int dlen, char* buf); */ int base16384_decode_unsafe(const char* data, int dlen, char* buf); -// base16384_encode_file_detailed encodes input file to output file. -// use `-` to specify stdin/stdout -// encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ -base16384_err_t base16384_encode_file_detailed(const char* input, const char* output, char* encbuf, char* decbuf, int flag); +#define base16384_typed_params(type) type input, type output, char* encbuf, char* decbuf +#define base16384_typed_flag_params(type) base16384_typed_params(type), int flag -// base16384_encode_fp_detailed encodes input file to output file. -// encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ -base16384_err_t base16384_encode_fp_detailed(FILE* input, FILE* output, char* encbuf, char* decbuf, int flag); +/** + * @brief encode input file to output file + * @param input filename or `-` to specify stdin + * @param output filename or `-` to specify stdout + * @param encbuf must be no less than BASE16384_ENCBUFSZ + * @param decbuf must be no less than BASE16384_DECBUFSZ + * @param flag BASE16384_FLAG_xxx value, add multiple flags by `|` + * @return the error code +*/ +base16384_err_t base16384_encode_file_detailed(base16384_typed_flag_params(const char*)); -// base16384_encode_fd_detailed encodes input fd to output fd. -// encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ -base16384_err_t base16384_encode_fd_detailed(int input, int output, char* encbuf, char* decbuf, int flag); +/** + * @brief encode input `FILE*` to output `FILE*` + * @param input `FILE*` pointer + * @param output `FILE*` pointer + * @param encbuf must be no less than BASE16384_ENCBUFSZ + * @param decbuf must be no less than BASE16384_DECBUFSZ + * @param flag BASE16384_FLAG_xxx value, add multiple flags by `|` + * @return the error code +*/ +base16384_err_t base16384_encode_fp_detailed(base16384_typed_flag_params(FILE*)); -// base16384_decode_file_detailed decodes input file to output file. -// use `-` to specify stdin/stdout -// encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ -base16384_err_t base16384_decode_file_detailed(const char* input, const char* output, char* encbuf, char* decbuf, int flag); +/** + * @brief encode input stream to output stream + * @param input file descripter + * @param output file descripter + * @param encbuf must be no less than BASE16384_ENCBUFSZ + * @param decbuf must be no less than BASE16384_DECBUFSZ + * @param flag BASE16384_FLAG_xxx value, add multiple flags by `|` + * @return the error code +*/ +base16384_err_t base16384_encode_fd_detailed(base16384_typed_flag_params(int)); -// base16384_decode_fp_detailed decodes input file to output file. -// encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ -base16384_err_t base16384_decode_fp_detailed(FILE* input, FILE* output, char* encbuf, char* decbuf, int flag); +/** + * @brief decode input file to output file + * @param input filename or `-` to specify stdin + * @param output filename or `-` to specify stdout + * @param encbuf must be no less than BASE16384_ENCBUFSZ + * @param decbuf must be no less than BASE16384_DECBUFSZ + * @param flag BASE16384_FLAG_xxx value, add multiple flags by `|` + * @return the error code +*/ +base16384_err_t base16384_decode_file_detailed(base16384_typed_flag_params(const char*)); -// base16384_decode_fd_detailed decodes input fd to output fd. -// encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ -base16384_err_t base16384_decode_fd_detailed(int input, int output, char* encbuf, char* decbuf, int flag); +/** + * @brief decode input `FILE*` to output `FILE*` + * @param input `FILE*` pointer + * @param output `FILE*` pointer + * @param encbuf must be no less than BASE16384_ENCBUFSZ + * @param decbuf must be no less than BASE16384_DECBUFSZ + * @param flag BASE16384_FLAG_xxx value, add multiple flags by `|` + * @return the error code +*/ +base16384_err_t base16384_decode_fp_detailed(base16384_typed_flag_params(FILE*)); -// base16384_encode_file encodes input file to output file. -// use `-` to specify stdin/stdout -// encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ -static inline base16384_err_t base16384_encode_file(const char* input, const char* output, char* encbuf, char* decbuf) { - return base16384_encode_file_detailed(input, output, encbuf, decbuf, 0); -} +/** + * @brief decode input stream to output stream + * @param input file descripter + * @param output file descripter + * @param encbuf must be no less than BASE16384_ENCBUFSZ + * @param decbuf must be no less than BASE16384_DECBUFSZ + * @param flag BASE16384_FLAG_xxx value, add multiple flags by `|` + * @return the error code +*/ +base16384_err_t base16384_decode_fd_detailed(base16384_typed_flag_params(int)); -// base16384_encode_fp encodes input file to output file. -// encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ -static inline base16384_err_t base16384_encode_fp(FILE* input, FILE* output, char* encbuf, char* decbuf) { - return base16384_encode_fp_detailed(input, output, encbuf, decbuf, 0); -} +#define BASE16384_DEFINE_DEATILED_WRAP(method, name, type) \ + static inline base16384_err_t base16384_##method##_##name##(base16384_typed_params(type)) { \ + return base16384_##method##_##name##_detailed(input, output, encbuf, decbuf, 0); \ + } -// base16384_encode_fd encodes input fd to output fd. -// encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ -static inline base16384_err_t base16384_encode_fd(int input, int output, char* encbuf, char* decbuf) { - return base16384_encode_fd_detailed(input, output, encbuf, decbuf, 0); -} + BASE16384_DEFINE_DEATILED_WRAP(encode, file, const char*); + BASE16384_DEFINE_DEATILED_WRAP(encode, fp, FILE*); + BASE16384_DEFINE_DEATILED_WRAP(encode, fd, int); -// base16384_decode_file decodes input file to output file. -// use `-` to specify stdin/stdout -// encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ -static inline base16384_err_t base16384_decode_file(const char* input, const char* output, char* encbuf, char* decbuf) { - return base16384_decode_file_detailed(input, output, encbuf, decbuf, 0); -} + BASE16384_DEFINE_DEATILED_WRAP(decode, file, const char*); + BASE16384_DEFINE_DEATILED_WRAP(decode, fp, FILE*); + BASE16384_DEFINE_DEATILED_WRAP(decode, fd, int); -// base16384_decode_fp decodes input file to output file. -// encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ -static inline base16384_err_t base16384_decode_fp(FILE* input, FILE* output, char* encbuf, char* decbuf) { - return base16384_decode_fp_detailed(input, output, encbuf, decbuf, 0); -} +#undef BASE16384_DEFINE_DEATILED_WRAP -// base16384_decode_fd decodes input fd to output fd. -// encbuf & decbuf must be no less than BASE16384_ENCBUFSZ & BASE16384_DECBUFSZ -static inline base16384_err_t base16384_decode_fd(int input, int output, char* encbuf, char* decbuf) { - return base16384_decode_fd_detailed(input, output, encbuf, decbuf, 0); -} +#undef base16384_typed_flag_params +#undef base16384_typed_params #endif diff --git a/file.c b/file.c index 35ff956..80bdd09 100644 --- a/file.c +++ b/file.c @@ -58,7 +58,7 @@ static inline uint32_t calc_sum(uint32_t sum, size_t cnt, char* encbuf) { fprintf(stderr, "firstval: %08x, ", htobe32(((uint32_t*)encbuf)[i])); } #endif - sum += LEFTROTATE(htobe32(((uint32_t*)encbuf)[i]), encbuf[i*sizeof(sum)]%(8*sizeof(sum))); + sum += ~LEFTROTATE(htobe32(((uint32_t*)encbuf)[i]), encbuf[i*sizeof(sum)]%(8*sizeof(sum))); } #ifdef DEBUG fprintf(stderr, "roundmid: %08x", sum); @@ -66,7 +66,7 @@ static inline uint32_t calc_sum(uint32_t sum, size_t cnt, char* encbuf) { size_t rem = cnt % sizeof(sum); if(rem) { uint32_t x = htobe32(((uint32_t*)encbuf)[i]) & (0xffffffff << (8*(sizeof(sum)-rem))); - sum += LEFTROTATE(x, encbuf[i*sizeof(sum)]%(8*sizeof(sum))); + sum += ~LEFTROTATE(x, encbuf[i*sizeof(sum)]%(8*sizeof(sum))); #ifdef DEBUG fprintf(stderr, ", roundrem:%08x\n", sum); #endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..48a9ab2 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 2.8.12) +if (POLICY CMP0048) + cmake_policy(SET CMP0048 NEW) +endif (POLICY CMP0048) +project(base16384_test VERSION 1.0.0) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) + +file (GLOB_RECURSE C_FILES "*.c") +foreach (C_FILE ${C_FILES}) + get_filename_component(FILE_NAME ${C_FILE} NAME_WE) + add_executable(${FILE_NAME} ${C_FILE}) + target_link_libraries(${FILE_NAME} base16384_s) + add_test(NAME do_${FILE_NAME} COMMAND ${FILE_NAME}) +endforeach () diff --git a/test/coder_test.c b/test/coder_test.c new file mode 100644 index 0000000..fb5f06f --- /dev/null +++ b/test/coder_test.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include + +#include "base16384.h" + +char encbuf[4096+16]; +char decbuf[4096/7*8+16]; +char tstbuf[4096+16]; + +#define loop_diff(target) \ + for(i = start; i < end; i++) { \ + if (encbuf[i] != tstbuf[i]) { \ + if(n) { \ + fprintf(stderr, " @%d", i); \ + n = 0; \ + } \ + fprintf(stderr, " %02x", (uint8_t)(target[i])); \ + } else if(!n) { \ + n = 1; \ + fprintf(stderr, " ..."); \ + } \ + } + +#define return_error(i, n) { \ + int end = i; \ + int start; \ + for(start = 0; start < end; start++) { \ + if(encbuf[start] != tstbuf[start]) break; \ + } \ + fprintf(stderr, "result mismatch @ loop %d, decsz: %d, first diff @ %d\n", i, n, start); \ + fprintf(stderr, "expect"); \ + n = 1; \ + loop_diff(encbuf); \ + fprintf(stderr, "\ngot "); \ + n = 1; \ + loop_diff(tstbuf); \ + fputc('\n', stderr); \ + return 1; \ +} + +int main() { + srand(time(NULL)); + int i, n; + for(i = 0; i < 4096; i += sizeof(int)) { + *(int*)(&encbuf[i]) = rand(); + } + fputs("testing base16384_encode/base16384_decode...\n", stderr); + for(i = 0; i < 4096; i++) { + n = base16384_encode(encbuf, i, decbuf); + n = base16384_decode(decbuf, n, tstbuf); + int decn = n; + if (memcmp(encbuf, tstbuf, n)) return_error(i, n); + } + fputs("testing base16384_encode_unsafe/base16384_decode_unsafe...\n", stderr); + for(i = 0; i < 4096; i++) { + n = base16384_encode_unsafe(encbuf, i, decbuf); + n = base16384_decode_unsafe(decbuf, n, tstbuf); + if ((n = memcmp(encbuf, tstbuf, n))) return_error(i, n); + } + return 0; +} From c5d5de227cc60919414d215d52892da05566e0dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Thu, 4 Apr 2024 20:50:47 +0900 Subject: [PATCH 14/35] feat(test): add wrap_test --- base16384.c | 18 +---- base16384.h | 42 ++++++++--- file.c | 71 +++++++++--------- test/CMakeLists.txt | 3 +- test/coder_test.c | 18 +++-- test/wrap_test.c | 173 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 257 insertions(+), 68 deletions(-) create mode 100644 test/wrap_test.c diff --git a/base16384.c b/base16384.c index b5e9e24..f860f40 100644 --- a/base16384.c +++ b/base16384.c @@ -123,22 +123,6 @@ int main(int argc, char** argv) { #endif } - #define base16384_perror_case(n) case base16384_err_##n: perror("base16384_err_"#n) - if(exitstat) switch(exitstat) { - base16384_perror_case(get_file_size); break; - base16384_perror_case(fopen_output_file); break; - base16384_perror_case(fopen_input_file); break; - base16384_perror_case(write_file); break; - base16384_perror_case(open_input_file); break; - base16384_perror_case(map_input_file); break; - base16384_perror_case(read_file); break; - base16384_perror_case(invalid_file_name); break; - base16384_perror_case(invalid_commandline_parameter); break; - base16384_perror_case(invalid_decoding_checksum); break; - default: perror("base16384"); break; - } - #undef base16384_perror_case - - return exitstat; + return base16384_perror(exitstat); } diff --git a/base16384.h b/base16384.h index 609503a..7ea5d88 100644 --- a/base16384.h +++ b/base16384.h @@ -221,22 +221,46 @@ base16384_err_t base16384_decode_fp_detailed(base16384_typed_flag_params(FILE*)) */ base16384_err_t base16384_decode_fd_detailed(base16384_typed_flag_params(int)); -#define BASE16384_DEFINE_DEATILED_WRAP(method, name, type) \ - static inline base16384_err_t base16384_##method##_##name##(base16384_typed_params(type)) { \ +#define BASE16384_WRAP_DECL(method, name, type) \ + static inline base16384_err_t base16384_##method##_##name(base16384_typed_params(type)) { \ return base16384_##method##_##name##_detailed(input, output, encbuf, decbuf, 0); \ } - BASE16384_DEFINE_DEATILED_WRAP(encode, file, const char*); - BASE16384_DEFINE_DEATILED_WRAP(encode, fp, FILE*); - BASE16384_DEFINE_DEATILED_WRAP(encode, fd, int); + BASE16384_WRAP_DECL(encode, file, const char*); + BASE16384_WRAP_DECL(encode, fp, FILE*); + BASE16384_WRAP_DECL(encode, fd, int); - BASE16384_DEFINE_DEATILED_WRAP(decode, file, const char*); - BASE16384_DEFINE_DEATILED_WRAP(decode, fp, FILE*); - BASE16384_DEFINE_DEATILED_WRAP(decode, fd, int); + BASE16384_WRAP_DECL(decode, file, const char*); + BASE16384_WRAP_DECL(decode, fp, FILE*); + BASE16384_WRAP_DECL(decode, fd, int); -#undef BASE16384_DEFINE_DEATILED_WRAP +#undef BASE16384_WRAP_DECL #undef base16384_typed_flag_params #undef base16384_typed_params +/** + * @brief call perror on error + * @param err the error + * @return the input parameter `err` +*/ +static inline base16384_err_t base16384_perror(base16384_err_t err) { + #define base16384_perror_case(n) case base16384_err_##n: perror("base16384_err_"#n) + if(err) switch(err) { + base16384_perror_case(get_file_size); break; + base16384_perror_case(fopen_output_file); break; + base16384_perror_case(fopen_input_file); break; + base16384_perror_case(write_file); break; + base16384_perror_case(open_input_file); break; + base16384_perror_case(map_input_file); break; + base16384_perror_case(read_file); break; + base16384_perror_case(invalid_file_name); break; + base16384_perror_case(invalid_commandline_parameter); break; + base16384_perror_case(invalid_decoding_checksum); break; + default: perror("base16384"); break; + } + #undef base16384_perror_case + return err; +} + #endif diff --git a/file.c b/file.c index 80bdd09..62f3f34 100644 --- a/file.c +++ b/file.c @@ -119,17 +119,18 @@ base16384_err_t base16384_encode_file_detailed(const char* input, const char* ou return base16384_err_invalid_file_name; } if(is_standard_io(input)) { // read from stdin - inputsize = 0; + inputsize = _BASE16384_ENCBUFSZ; fp = stdin; } else inputsize = get_file_size(input); - if(inputsize < 0) { + if(inputsize <= 0) { + if(!inputsize) errno = EINVAL; return base16384_err_get_file_size; } fpo = is_standard_io(output)?stdout:fopen(output, "wb"); if(!fpo) { return base16384_err_fopen_output_file; } - if(!inputsize || inputsize > _BASE16384_ENCBUFSZ) { // stdin or big file, use encbuf & fread + if(inputsize >= _BASE16384_ENCBUFSZ) { // stdin or big file, use encbuf & fread inputsize = _BASE16384_ENCBUFSZ; #if defined _WIN32 || defined __cosmopolitan } @@ -151,7 +152,7 @@ base16384_err_t base16384_encode_file_detailed(const char* input, const char* ou while((cnt = fread(encbuf, sizeof(char), inputsize, fp)) > 0) { if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) sum = calc_and_embed_sum(sum, cnt, encbuf); int n = base16384_encode_unsafe(encbuf, cnt, decbuf); - if(fwrite(decbuf, n, 1, fpo) <= 0) { + if(n && fwrite(decbuf, n, 1, fpo) <= 0) { goto_base16384_file_detailed_cleanup(encode, base16384_err_write_file, {}); } } @@ -170,7 +171,7 @@ base16384_err_t base16384_encode_file_detailed(const char* input, const char* ou fputc(0xFF, fpo); } int n = base16384_encode(input_file, (int)inputsize, decbuf); - if(fwrite(decbuf, n, 1, fpo) <= 0) { + if(n && fwrite(decbuf, n, 1, fpo) <= 0) { goto_base16384_file_detailed_cleanup(encode, base16384_err_write_file, { munmap(input_file, (size_t)inputsize); close(fd); @@ -204,7 +205,7 @@ base16384_err_t base16384_encode_fp_detailed(FILE* input, FILE* output, char* en while((cnt = fread(encbuf, sizeof(char), inputsize, input)) > 0) { if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) sum = calc_and_embed_sum(sum, cnt, encbuf); int n = base16384_encode_unsafe(encbuf, cnt, decbuf); - if(fwrite(decbuf, n, 1, output) <= 0) { + if(n && fwrite(decbuf, n, 1, output) <= 0) { return base16384_err_write_file; } } @@ -225,7 +226,7 @@ base16384_err_t base16384_encode_fd_detailed(int input, int output, char* encbuf while((cnt = read(input, encbuf, inputsize)) > 0) { if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) sum = calc_and_embed_sum(sum, cnt, encbuf); int n = base16384_encode_unsafe(encbuf, cnt, decbuf); - if(write(output, decbuf, n) < n) { + if(n && write(output, decbuf, n) < n) { return base16384_err_write_file; } } @@ -260,17 +261,18 @@ base16384_err_t base16384_decode_file_detailed(const char* input, const char* ou return base16384_err_invalid_file_name; } if(is_standard_io(input)) { // read from stdin - inputsize = 0; + inputsize = _BASE16384_DECBUFSZ; fp = stdin; } else inputsize = get_file_size(input); - if(inputsize < 0) { + if(inputsize <= 0) { + if(!inputsize) errno = EINVAL; return base16384_err_get_file_size; } fpo = is_standard_io(output)?stdout:fopen(output, "wb"); if(!fpo) { return base16384_err_fopen_output_file; } - if(!inputsize || inputsize > _BASE16384_DECBUFSZ) { // stdin or big file, use decbuf & fread + if(inputsize >= _BASE16384_DECBUFSZ) { // stdin or big file, use decbuf & fread inputsize = _BASE16384_DECBUFSZ; #if defined _WIN32 || defined __cosmopolitan } @@ -295,7 +297,7 @@ base16384_err_t base16384_decode_file_detailed(const char* input, const char* ou } if(errno) goto_base16384_file_detailed_cleanup(decode, base16384_err_read_file, {}); cnt = base16384_decode_unsafe(decbuf, cnt, encbuf); - if(fwrite(encbuf, cnt, 1, fpo) <= 0) { + if(cnt && fwrite(encbuf, cnt, 1, fpo) <= 0) { goto_base16384_file_detailed_cleanup(decode, base16384_err_write_file, {}); } if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) { @@ -316,7 +318,8 @@ base16384_err_t base16384_decode_file_detailed(const char* input, const char* ou goto_base16384_file_detailed_cleanup(decode, base16384_err_map_input_file, close(fd)); } int off = skip_offset(input_file); - if(fwrite(encbuf, base16384_decode(input_file+off, inputsize-off, encbuf), 1, fpo) <= 0) { + int n = base16384_decode(input_file+off, inputsize-off, encbuf); + if(n && fwrite(encbuf, n, 1, fpo) <= 0) { goto_base16384_file_detailed_cleanup(decode, base16384_err_write_file, { munmap(input_file, (size_t)inputsize); close(fd); @@ -356,7 +359,7 @@ base16384_err_t base16384_decode_fp_detailed(FILE* input, FILE* output, char* en decbuf[cnt++] = end; } cnt = base16384_decode_unsafe(decbuf, cnt, encbuf); - if(fwrite(encbuf, cnt, 1, output) <= 0) { + if(cnt && fwrite(encbuf, cnt, 1, output) <= 0) { return base16384_err_write_file; } if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) { @@ -371,10 +374,10 @@ base16384_err_t base16384_decode_fp_detailed(FILE* input, FILE* output, char* en static inline uint16_t is_next_end_fd(int fd) { uint8_t ch = 0; - read(fd, &ch, 1); + if(read(fd, &ch, 1) != 1) return (uint16_t)EOF; uint16_t ret = (uint16_t)ch & 0x00ff; if(ch == '=') { - read(fd, &ch, 1); + if(read(fd, &ch, 1) != 1) return (uint16_t)EOF; ret <<= 8; ret |= (uint16_t)ch & 0x00ff; } @@ -390,29 +393,32 @@ base16384_err_t base16384_decode_fd_detailed(int input, int output, char* encbuf errno = EINVAL; return base16384_err_fopen_output_file; } - off_t inputsize = _BASE16384_DECBUFSZ; + off_t inputsize = _BASE16384_DECBUFSZ-1; int cnt = 0; - int end = 0; uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE; decbuf[0] = 0; - if(read(input, decbuf, 2) < 2) { + if(read(input, decbuf, 2) != 2) { return base16384_err_read_file; } - if(decbuf[0] != (char)(0xfe)) cnt = 2; - while((end = read(input, decbuf+cnt, inputsize-cnt)) > 0 || cnt > 0) { - if(end > 0) { - cnt += end; - uint16_t next = is_next_end_fd(input); - if(errno) { - return base16384_err_read_file; - } - if(next&0xff00) { - decbuf[cnt++] = '='; - } + if(decbuf[0] != (char)(0xfe)) { + cnt = read(input, decbuf+2, inputsize-2)+2; + } else { + cnt = read(input, decbuf, inputsize); + } + if(cnt > 0) do { + uint16_t next = is_next_end_fd(input); + if(errno) { + return base16384_err_read_file; + } + if((uint16_t)(~next)) { + if(next&0xff00) decbuf[cnt++] = '='; decbuf[cnt++] = (char)(next&0x00ff); } - end = base16384_decode_unsafe(decbuf, cnt, encbuf); - if(write(output, encbuf, end) < end) { + #ifdef DEBUG + fprintf(stderr, "decode chunk: %d, last2: %c %02x\n", cnt, decbuf[cnt-2], (uint8_t)decbuf[cnt-1]); + #endif + cnt = base16384_decode_unsafe(decbuf, cnt, encbuf); + if(cnt && write(output, encbuf, cnt) != cnt) { return base16384_err_write_file; } if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) { @@ -421,7 +427,6 @@ base16384_err_t base16384_decode_fd_detailed(int input, int output, char* encbuf return base16384_err_invalid_decoding_checksum; } } - cnt = 0; - } + } while((cnt = read(input, decbuf, inputsize)) > 0); return base16384_err_ok; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 48a9ab2..bb82a5e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 2.8.12) if (POLICY CMP0048) - cmake_policy(SET CMP0048 NEW) + cmake_policy(SET CMP0048 NEW) endif (POLICY CMP0048) project(base16384_test VERSION 1.0.0) @@ -9,6 +9,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) file (GLOB_RECURSE C_FILES "*.c") foreach (C_FILE ${C_FILES}) get_filename_component(FILE_NAME ${C_FILE} NAME_WE) + message(STATUS "Add test ${FILE_NAME}") add_executable(${FILE_NAME} ${C_FILE}) target_link_libraries(${FILE_NAME} base16384_s) add_test(NAME do_${FILE_NAME} COMMAND ${FILE_NAME}) diff --git a/test/coder_test.c b/test/coder_test.c index fb5f06f..fe391f6 100644 --- a/test/coder_test.c +++ b/test/coder_test.c @@ -6,9 +6,11 @@ #include "base16384.h" -char encbuf[4096+16]; -char decbuf[4096/7*8+16]; -char tstbuf[4096+16]; +#define TEST_SIZE (4096) + +char encbuf[TEST_SIZE+16]; +char decbuf[TEST_SIZE/7*8+16]; +char tstbuf[TEST_SIZE+16]; #define loop_diff(target) \ for(i = start; i < end; i++) { \ @@ -44,18 +46,18 @@ char tstbuf[4096+16]; int main() { srand(time(NULL)); int i, n; - for(i = 0; i < 4096; i += sizeof(int)) { + for(i = 0; i <= TEST_SIZE; i += sizeof(int)) { *(int*)(&encbuf[i]) = rand(); } - fputs("testing base16384_encode/base16384_decode...\n", stderr); - for(i = 0; i < 4096; i++) { + fputs("testing base16384_en/decode...\n", stderr); + for(i = 0; i <= TEST_SIZE; i++) { n = base16384_encode(encbuf, i, decbuf); n = base16384_decode(decbuf, n, tstbuf); int decn = n; if (memcmp(encbuf, tstbuf, n)) return_error(i, n); } - fputs("testing base16384_encode_unsafe/base16384_decode_unsafe...\n", stderr); - for(i = 0; i < 4096; i++) { + fputs("testing base16384_en/ecode_unsafe...\n", stderr); + for(i = 0; i <= TEST_SIZE; i++) { n = base16384_encode_unsafe(encbuf, i, decbuf); n = base16384_decode_unsafe(decbuf, n, tstbuf); if ((n = memcmp(encbuf, tstbuf, n))) return_error(i, n); diff --git a/test/wrap_test.c b/test/wrap_test.c new file mode 100644 index 0000000..467914c --- /dev/null +++ b/test/wrap_test.c @@ -0,0 +1,173 @@ + +#ifdef _WIN32 + #include + #define ftruncate _chsize_s +#else + #define _POSIX1_SOURCE 2 + #include +#endif +#include +#include +#include +#include +#include +#include + +#include "base16384.h" +#include "binary.h" + +#define TEST_SIZE (4096) +#define TEST_INPUT_FILENAME "wrap_test_input.bin" +#define TEST_OUTPUT_FILENAME "wrap_test_output.bin" +#define TEST_VALIDATE_FILENAME "wrap_test_validate.bin" + +char encbuf[BASE16384_ENCBUFSZ]; +char decbuf[BASE16384_DECBUFSZ]; +char tstbuf[BASE16384_ENCBUFSZ]; + +#define ok(has_failed, reason) \ + if (has_failed) { \ + perror(reason); \ + return 1; \ + } + +#define loop_ok(has_failed, i, reason) \ + if (has_failed) { \ + fprintf(stderr, "loop @%d: ", i); \ + perror(reason); \ + return 1; \ + } + +#define reset_and_truncate(fd, i) { \ + fd = open(TEST_INPUT_FILENAME, O_RDWR); \ + ok(!fd, "open"); \ + loop_ok(lseek(fd, 0, SEEK_SET), i, "lseek"); \ + loop_ok(ftruncate(fd, i), i, "ftruncate"); \ +} + +#define base16384_loop_ok(err) \ + if (err) { \ + fprintf(stderr, "loop @%d: ", i); \ + base16384_perror(err); \ + return 1; \ + } + +#define validate_result() \ + uint64_t buf, sum_input = 0, sum_validate = 0; \ + fp = fopen(TEST_INPUT_FILENAME, "rb"); { \ + loop_ok(!fp, i, "fopen"); \ + while (fread(&buf, sizeof(sum_input), 1, fp) == 1) sum_input += buf; \ + buf = 0; \ + while (fread(&buf, 1, 1, fp) == 1) { \ + sum_input += buf; \ + sum_input = LEFTROTATE(sum_input, 4); \ + } \ + } fclose(fp); \ + fp = fopen(TEST_VALIDATE_FILENAME, "rb"); { \ + loop_ok(!fp, i, "fopen"); \ + while (fread(&buf, sizeof(sum_validate), 1, fp) == 1) sum_validate += buf; \ + buf = 0; \ + while (fread(&buf, 1, 1, fp) == 1) { \ + sum_validate += buf; \ + sum_validate = LEFTROTATE(sum_validate, 4); \ + } \ + } fclose(fp); \ + if (sum_input != sum_validate) { \ + fprintf(stderr, "loop @%d, expect: %016llx, got: %016llx: ", i, sum_input, sum_validate); \ + fputs(TEST_INPUT_FILENAME " and " TEST_VALIDATE_FILENAME " mismatch.", stderr); \ + return 1; \ + } + +#define init_input_file() \ + for(i = 0; i < TEST_SIZE; i += sizeof(int)) { \ + *(int*)(&encbuf[i]) = rand(); \ + } \ + fp = fopen(TEST_INPUT_FILENAME, "wb"); \ + ok(!fp, "fopen"); \ + ok(fwrite(encbuf, TEST_SIZE, 1, fp) != 1, "fwrite"); \ + ok(fclose(fp), "fclose"); + +int main() { + srand(time(NULL)); + + FILE* fp; + int fd, i; + base16384_err_t err; + + fputs("testing base16384_en/decode_file...\n", stderr); + init_input_file(); + for(i = TEST_SIZE; i > 0; i--) { + reset_and_truncate(fd, i); + loop_ok(close(fd), i, "close"); + + err = base16384_encode_file(TEST_INPUT_FILENAME, TEST_OUTPUT_FILENAME, encbuf, decbuf); + base16384_loop_ok(err); + err = base16384_decode_file(TEST_OUTPUT_FILENAME, TEST_VALIDATE_FILENAME, encbuf, decbuf); + base16384_loop_ok(err); + + validate_result(); + } + + fputs("testing base16384_en/decode_fp...\n", stderr); + init_input_file(); + for(i = TEST_SIZE; i > 0; i--) { + reset_and_truncate(fd, i); + loop_ok(close(fd), i, "close"); + + FILE* fpin = fopen(TEST_INPUT_FILENAME, "rb"); + loop_ok(!fpin, i, "fopen"); + + FILE* fpout = fopen(TEST_OUTPUT_FILENAME, "wb+"); + loop_ok(!fpout, i, "fopen"); + + err = base16384_encode_fp(fpin, fpout, encbuf, decbuf); + base16384_loop_ok(err); + + loop_ok(fclose(fpin), i, "fclose"); + + FILE* fpval = fopen(TEST_VALIDATE_FILENAME, "wb"); + loop_ok(!fpval, i, "fopen"); + + rewind(fpout); + + err = base16384_decode_fp(fpout, fpval, encbuf, decbuf); + base16384_loop_ok(err); + + loop_ok(fclose(fpout), i, "fclose"); + loop_ok(fclose(fpval), i, "fclose"); + + validate_result(); + } + + fputs("testing base16384_en/decode_fd...\n", stderr); + init_input_file(); + for(i = TEST_SIZE; i > 0; i--) { + reset_and_truncate(fd, i); + + int fdout = open(TEST_OUTPUT_FILENAME, O_RDWR|O_TRUNC|O_CREAT|O_APPEND); + loop_ok(!fdout, i, "open"); + + err = base16384_encode_fd(fd, fdout, encbuf, decbuf); + base16384_loop_ok(err); + loop_ok(close(fd), i, "close"); + + int fdval = open(TEST_VALIDATE_FILENAME, O_WRONLY|O_TRUNC|O_CREAT); + loop_ok(!fdval, i, "open"); + + loop_ok(lseek(fdout, 0, SEEK_SET), i, "lseek"); + + err = base16384_decode_fd(fdout, fdval, encbuf, decbuf); + base16384_loop_ok(err); + + loop_ok(close(fdout), i, "close"); + loop_ok(close(fdval), i, "close"); + + validate_result(); + } + + remove(TEST_INPUT_FILENAME); + remove(TEST_OUTPUT_FILENAME); + remove(TEST_VALIDATE_FILENAME); + + return 0; +} From a3f0a4ef6ef19ffc62a59fa03a6e6367c106c33b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Thu, 4 Apr 2024 21:06:13 +0900 Subject: [PATCH 15/35] feat(ci): add test on push --- .github/workflows/release.yml | 3 ++- .github/workflows/test.yml | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4e99f54..cc5d350 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,7 +8,7 @@ env: GITHUB_TOKEN: ${{ github.token }} jobs: - my-job: + release: name: Build on Push Tag 🚀 runs-on: ubuntu-latest steps: @@ -27,6 +27,7 @@ jobs: run: | gcc -g -Os -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone \ -fno-omit-frame-pointer -pg -mnop-mcount -D__cosmopolitan \ + -DBASE16384_VERSION="${{ github.ref }}" -DBASE16384_VERSION_DATE="`date +"%Y%b/%d"`"\ -o base16384.com.dbg base16384.c file.c base1432.c -fuse-ld=bfd -Wl,-T,ape.lds \ -include cosmopolitan.h crt.o ape.o cosmopolitan.a objcopy -S -O binary base16384.com.dbg base16384.com diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..0836093 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,24 @@ +name: test +on: [ push ] + +jobs: + test: + name: Run CMake Test 🧪 + runs-on: ubuntu-latest + steps: + + - name: Check out code + uses: actions/checkout@v2 + + - name: Set up Build tools + run: | + sudo apt-get update + sudo apt-get install -y gcc cmake + + - name: Build and Run Tests + run: | + mkdir build + cd build + cmake -DBUILD=test .. + make + make test From d27486f80d3c278e0e50fcdf5cd29f4e3eb78d66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Thu, 4 Apr 2024 21:12:17 +0900 Subject: [PATCH 16/35] chore(ci): make lint happy --- .github/workflows/release.yml | 6 +++--- .github/workflows/test.yml | 6 +++--- test/wrap_test.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cc5d350..3a53864 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,10 +13,10 @@ jobs: runs-on: ubuntu-latest steps: - - name: Check out code + - name: Checkout Code uses: actions/checkout@v2 - - name: Set up Build tools + - name: Setup Build Tools run: | sudo apt-get update sudo apt-get install -y gcc @@ -32,7 +32,7 @@ jobs: -include cosmopolitan.h crt.o ape.o cosmopolitan.a objcopy -S -O binary base16384.com.dbg base16384.com - - name: Upload binaries to release + - name: Upload Binaries to Release uses: svenstaro/upload-release-action@v2 with: repo_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0836093..5edd99e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,10 +7,10 @@ jobs: runs-on: ubuntu-latest steps: - - name: Check out code + - name: Checkout Code uses: actions/checkout@v2 - - name: Set up Build tools + - name: Setup Build Tools run: | sudo apt-get update sudo apt-get install -y gcc cmake @@ -21,4 +21,4 @@ jobs: cd build cmake -DBUILD=test .. make - make test + make test || make test --rerun-failed --output-on-failure diff --git a/test/wrap_test.c b/test/wrap_test.c index 467914c..aef1748 100644 --- a/test/wrap_test.c +++ b/test/wrap_test.c @@ -73,7 +73,7 @@ char tstbuf[BASE16384_ENCBUFSZ]; } \ } fclose(fp); \ if (sum_input != sum_validate) { \ - fprintf(stderr, "loop @%d, expect: %016llx, got: %016llx: ", i, sum_input, sum_validate); \ + fprintf(stderr, "loop @%d, expect: %016llx, got: %016llx: ", i, (unsigned long long)sum_input, (unsigned long long)sum_validate); \ fputs(TEST_INPUT_FILENAME " and " TEST_VALIDATE_FILENAME " mismatch.", stderr); \ return 1; \ } From d8587de86c87e2613dab4f0181136ed0738eac2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Thu, 4 Apr 2024 21:15:38 +0900 Subject: [PATCH 17/35] chore(ci): make lint happy --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5edd99e..b81fc5a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,4 +21,4 @@ jobs: cd build cmake -DBUILD=test .. make - make test || make test --rerun-failed --output-on-failure + make test || ctest --rerun-failed --output-on-failure From 72cb21287a7c32424d876310285e93c507189fac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Thu, 4 Apr 2024 21:29:43 +0900 Subject: [PATCH 18/35] chore(ci): make lint happy --- test/wrap_test.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/wrap_test.c b/test/wrap_test.c index aef1748..54cfb95 100644 --- a/test/wrap_test.c +++ b/test/wrap_test.c @@ -29,7 +29,8 @@ char tstbuf[BASE16384_ENCBUFSZ]; if (has_failed) { \ perror(reason); \ return 1; \ - } + } \ + fputs(reason " run successfully\n", stderr); #define loop_ok(has_failed, i, reason) \ if (has_failed) { \ @@ -85,7 +86,8 @@ char tstbuf[BASE16384_ENCBUFSZ]; fp = fopen(TEST_INPUT_FILENAME, "wb"); \ ok(!fp, "fopen"); \ ok(fwrite(encbuf, TEST_SIZE, 1, fp) != 1, "fwrite"); \ - ok(fclose(fp), "fclose"); + ok(fclose(fp), "fclose"); \ + fputs("input file created.", stderr); int main() { srand(time(NULL)); From fb9b5c033b29277fa3c8a913f4e398d2e3003a91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Thu, 4 Apr 2024 21:35:25 +0900 Subject: [PATCH 19/35] chore(ci): make lint happy --- test/wrap_test.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/wrap_test.c b/test/wrap_test.c index 54cfb95..e4c7391 100644 --- a/test/wrap_test.c +++ b/test/wrap_test.c @@ -29,8 +29,7 @@ char tstbuf[BASE16384_ENCBUFSZ]; if (has_failed) { \ perror(reason); \ return 1; \ - } \ - fputs(reason " run successfully\n", stderr); + } #define loop_ok(has_failed, i, reason) \ if (has_failed) { \ @@ -87,7 +86,7 @@ char tstbuf[BASE16384_ENCBUFSZ]; ok(!fp, "fopen"); \ ok(fwrite(encbuf, TEST_SIZE, 1, fp) != 1, "fwrite"); \ ok(fclose(fp), "fclose"); \ - fputs("input file created.", stderr); + fputs("input file created.\n", stderr); int main() { srand(time(NULL)); @@ -101,13 +100,15 @@ int main() { for(i = TEST_SIZE; i > 0; i--) { reset_and_truncate(fd, i); loop_ok(close(fd), i, "close"); - + fputs("base16384_encode_file\n", stderr); err = base16384_encode_file(TEST_INPUT_FILENAME, TEST_OUTPUT_FILENAME, encbuf, decbuf); base16384_loop_ok(err); + fputs("base16384_decode_file\n", stderr); err = base16384_decode_file(TEST_OUTPUT_FILENAME, TEST_VALIDATE_FILENAME, encbuf, decbuf); base16384_loop_ok(err); - + fputs("validate_result\n", stderr); validate_result(); + fputs("fin\n\n", stderr); } fputs("testing base16384_en/decode_fp...\n", stderr); From 2abcc1489a73fed7c39219798ee43d2a74d9c193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Thu, 4 Apr 2024 21:46:44 +0900 Subject: [PATCH 20/35] fix(file): incorrect munmap size --- file.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/file.c b/file.c index 62f3f34..c6953ff 100644 --- a/file.c +++ b/file.c @@ -173,11 +173,11 @@ base16384_err_t base16384_encode_file_detailed(const char* input, const char* ou int n = base16384_encode(input_file, (int)inputsize, decbuf); if(n && fwrite(decbuf, n, 1, fpo) <= 0) { goto_base16384_file_detailed_cleanup(encode, base16384_err_write_file, { - munmap(input_file, (size_t)inputsize); + munmap(input_file, (size_t)inputsize+16); close(fd); }); } - munmap(input_file, (size_t)inputsize); + munmap(input_file, (size_t)inputsize+16); close(fd); } #endif @@ -321,11 +321,11 @@ base16384_err_t base16384_decode_file_detailed(const char* input, const char* ou int n = base16384_decode(input_file+off, inputsize-off, encbuf); if(n && fwrite(encbuf, n, 1, fpo) <= 0) { goto_base16384_file_detailed_cleanup(decode, base16384_err_write_file, { - munmap(input_file, (size_t)inputsize); + munmap(input_file, (size_t)inputsize+16); close(fd); }); } - munmap(input_file, (size_t)inputsize); + munmap(input_file, (size_t)inputsize+16); close(fd); } #endif From b4511276385111ccd361943a0c5a56d9bb62a9e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Thu, 4 Apr 2024 21:52:16 +0900 Subject: [PATCH 21/35] chore(ci): make lint happy --- test/wrap_test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/test/wrap_test.c b/test/wrap_test.c index e4c7391..b6abb1b 100644 --- a/test/wrap_test.c +++ b/test/wrap_test.c @@ -98,6 +98,7 @@ int main() { fputs("testing base16384_en/decode_file...\n", stderr); init_input_file(); for(i = TEST_SIZE; i > 0; i--) { + fprintf(stderr, "loop@%d\n", i); reset_and_truncate(fd, i); loop_ok(close(fd), i, "close"); fputs("base16384_encode_file\n", stderr); From 2622a5ad692f9b3db35683dad9ac30cca1d87cd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Thu, 4 Apr 2024 23:58:05 +0900 Subject: [PATCH 22/35] feat(coder): add safe encode/decode --- .github/workflows/test.yml | 11 +- CMakeLists.txt | 2 +- base1432.c | 207 +++++++++++++++++++++++++++++++++++-- base1464.c | 179 ++++++++++++++++++++++++++++++++ base16384.h | 18 ++++ file.c | 6 +- test/coder_test.c | 33 +++--- test/wrap_test.c | 8 +- 8 files changed, 435 insertions(+), 29 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b81fc5a..ced3f8f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,10 +15,19 @@ jobs: sudo apt-get update sudo apt-get install -y gcc cmake - - name: Build and Run Tests + - name: Build and Run 64bit Tests run: | mkdir build cd build cmake -DBUILD=test .. make make test || ctest --rerun-failed --output-on-failure + + - name: Build and Run 32bit Tests + run: | + rm -rf build + mkdir build + cd build + cmake -DBUILD=test -DFORCE_32BIT=1 .. + make + make test || ctest --rerun-failed --output-on-failure diff --git a/CMakeLists.txt b/CMakeLists.txt index 9fd796a..0600cec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ endif () add_executable(base16384_b base16384.c) -IF (CMAKE_SIZEOF_VOID_P EQUAL 8) +IF ((NOT FORCE_32BIT) AND CMAKE_SIZEOF_VOID_P EQUAL 8) message(STATUS "Adding 64bit libraries...") add_definitions(-DIS_64BIT_PROCESSOR) add_library(base16384 SHARED file.c base1464.c) diff --git a/base1432.c b/base1432.c index df723e2..e991d2a 100644 --- a/base1432.c +++ b/base1432.c @@ -16,8 +16,113 @@ * along with this program. If not, see . */ +#include + #include "binary.h" +union remainder { + uint8_t buf[4]; + uint32_t val; +}; +typedef union remainder remainder; + +int base16384_encode_safe(const char* data, int dlen, char* buf) { + int outlen = dlen / 7 * 8; + int offset = dlen % 7; + switch(offset) { // 算上偏移标志字符占用的2字节 + case 0: break; + case 1: outlen += 4; break; + case 2: + case 3: outlen += 6; break; + case 4: + case 5: outlen += 8; break; + case 6: outlen += 10; break; + default: break; + } + uint32_t* vals = (uint32_t*)buf; + uint32_t n = 0; + int32_t i = 0; + for(; i < dlen - 7; i += 7) { + register uint32_t sum = 0; + register uint32_t shift = htobe32(*(uint32_t*)(data+i)); + sum |= (shift>>2) & 0x3fff0000; + sum |= (shift>>4) & 0x00003fff; + sum += 0x4e004e00; + vals[n++] = be32toh(sum); + shift <<= 26; + shift &= 0x3c000000; + sum = 0; + shift |= (htobe32(*(uint32_t*)(data+i+4))>>6)&0x03fffffc; + sum |= shift & 0x3fff0000; + shift >>= 2; + sum |= shift & 0x00003fff; + sum += 0x4e004e00; + vals[n++] = be32toh(sum); + } + remainder valbuf; + if(dlen - i == 7) { + register uint32_t sum = 0; + register uint32_t shift = htobe32(*(uint32_t*)(data+i)); + sum |= (shift>>2) & 0x3fff0000; + sum |= (shift>>4) & 0x00003fff; + sum += 0x4e004e00; + vals[n++] = be32toh(sum); + shift <<= 26; + shift &= 0x3c000000; + sum = 0; + memcpy(valbuf.buf, data+i+4, 3); + shift |= (htobe32(valbuf.val)>>6)&0x03fffffc; + sum |= shift & 0x3fff0000; + shift >>= 2; + sum |= shift & 0x00003fff; + sum += 0x4e004e00; + vals[n++] = be32toh(sum); + return outlen; + } + uint8_t o = offset; + if(o--) { + register uint32_t sum = 0x0000003f & (data[i] >> 2); + sum |= ((uint32_t)data[i] << 14) & 0x0000c000; + if(o--) { + sum |= ((uint32_t)data[i + 1] << 6) & 0x00003f00; + sum |= ((uint32_t)data[i + 1] << 20) & 0x00300000; + if(o--) { + sum |= ((uint32_t)data[i + 2] << 12) & 0x000f0000; + sum |= ((uint32_t)data[i + 2] << 28) & 0xf0000000; + if(o--) { + sum |= ((uint32_t)data[i + 3] << 20) & 0x0f000000; + sum += 0x004e004e; + // safe, because it will never go over 0x3dxx + #ifdef WORDS_BIGENDIAN + vals[n++] = __builtin_bswap32(sum); + #else + vals[n++] = sum; + #endif + sum = (((uint32_t)data[i + 3] << 2)) & 0x0000003c; + if(o--) { + sum |= (((uint32_t)data[i + 4] >> 6)) & 0x00000003; + sum |= ((uint32_t)data[i + 4] << 10) & 0x0000fc00; + if(o--) { + sum |= ((uint32_t)data[i + 5] << 2) & 0x00000300; + sum |= ((uint32_t)data[i + 5] << 16) & 0x003f0000; + } + } + } + } + } + sum += 0x004e004e; + // safe, because it will never go over 0x3dxx + #ifdef WORDS_BIGENDIAN + vals[n] = __builtin_bswap32(sum); + #else + vals[n] = sum; + #endif + buf[outlen - 2] = '='; + buf[outlen - 1] = offset; + } + return outlen; +} + int base16384_encode(const char* data, int dlen, char* buf) { int outlen = dlen / 7 * 8; int offset = dlen % 7; @@ -31,9 +136,6 @@ int base16384_encode(const char* data, int dlen, char* buf) { case 6: outlen += 10; break; default: break; } - #ifdef DEBUG - printf("outlen: %llu, offset: %u, malloc: %llu\n", outlen, offset, outlen + 8); - #endif uint32_t* vals = (uint32_t*)buf; uint32_t n = 0; int32_t i = 0; @@ -109,9 +211,6 @@ int base16384_encode_unsafe(const char* data, int dlen, char* buf) { case 6: outlen += 10; break; default: break; } - #ifdef DEBUG - printf("outlen: %llu, offset: %u, malloc: %llu\n", outlen, offset, outlen + 8); - #endif uint32_t* vals = (uint32_t*)buf; uint32_t n = 0; int32_t i = 0; @@ -139,6 +238,102 @@ int base16384_encode_unsafe(const char* data, int dlen, char* buf) { return outlen; } +int base16384_decode_safe(const char* data, int dlen, char* buf) { + int outlen = dlen; + int offset = 0; + if(data[dlen-2] == '=') { + offset = data[dlen-1]; + switch(offset) { // 算上偏移标志字符占用的2字节 + case 0: break; + case 1: outlen -= 4; break; + case 2: + case 3: outlen -= 6; break; + case 4: + case 5: outlen -= 8; break; + case 6: outlen -= 10; break; + default: break; + } + } + outlen = outlen / 8 * 7 + offset; + uint32_t* vals = (uint32_t*)data; + uint32_t n = 0; + int32_t i = 0; + for(; i < outlen - 7; i+=7) { // n实际每次自增2 + register uint32_t sum = 0; + register uint32_t shift = htobe32(vals[n++]) - 0x4e004e00; + shift <<= 2; + sum |= shift & 0xfffc0000; + shift <<= 2; + sum |= shift & 0x0003fff0; + shift = htobe32(vals[n++]) - 0x4e004e00; + sum |= shift >> 26; + *(uint32_t*)(buf+i) = be32toh(sum); + sum = 0; + shift <<= 6; + sum |= shift & 0xffc00000; + shift <<= 2; + sum |= shift & 0x003fff00; + *(uint32_t*)(buf+i+4) = be32toh(sum); + } + remainder valbuf; + if(outlen - i == 7) { + register uint32_t sum = 0; + register uint32_t shift = htobe32(vals[n++]) - 0x4e004e00; + shift <<= 2; + sum |= shift & 0xfffc0000; + shift <<= 2; + sum |= shift & 0x0003fff0; + shift = htobe32(vals[n]) - 0x4e004e00; + sum |= shift >> 26; + *(uint32_t*)(buf+i) = be32toh(sum); + sum = 0; + shift <<= 6; + sum |= shift & 0xffc00000; + shift <<= 2; + sum |= shift & 0x003fff00; + valbuf.val = be32toh(sum); + memcpy(buf+i+4, valbuf.buf, 3); + } else if(offset--) { + int cnt = dlen-2-(int)n*(int)sizeof(uint32_t); + if (cnt > 4) cnt = 4; + memcpy(valbuf.buf, &vals[n], cnt); + n++; + #ifdef WORDS_BIGENDIAN + register uint32_t sum = __builtin_bswap32(valbuf.val); + #else + register uint32_t sum = valbuf.val; + #endif + sum -= 0x0000004e; + buf[i++] = ((sum & 0x0000003f) << 2) | ((sum & 0x0000c000) >> 14); + if(offset--) { + sum -= 0x004e0000; + buf[i++] = ((sum & 0x00003f00) >> 6) | ((sum & 0x00300000) >> 20); + if(offset--) { + buf[i++] = ((sum & 0x000f0000) >> 12) | ((sum & 0xf0000000) >> 28); + if(offset--) { + buf[i] = (sum & 0x0f000000) >> 20; + memcpy(valbuf.buf, &vals[n], dlen-2-(int)n*(int)sizeof(uint32_t)); + #ifdef WORDS_BIGENDIAN + sum = __builtin_bswap32(valbuf.val); + #else + sum = valbuf.val; + #endif + sum -= 0x0000004e; + buf[i++] |= (sum & 0x0000003c) >> 2; + if(offset--) { + buf[i++] = ((sum & 0x00000003) << 6) | ((sum & 0x0000fc00) >> 10); + if(offset--) { + sum -= 0x004e0000; + buf[i] = ((sum & 0x00000300) >> 2) | ((sum & 0x003f0000) >> 16); + } + } + } + } + } + } + return outlen; +} + int base16384_decode(const char* data, int dlen, char* buf) { int outlen = dlen; int offset = 0; diff --git a/base1464.c b/base1464.c index 77d1ff3..23d3f69 100644 --- a/base1464.c +++ b/base1464.c @@ -16,8 +16,107 @@ * along with this program. If not, see . */ +#include + #include "binary.h" +union remainder { + uint8_t buf[8]; + uint64_t val; +}; +typedef union remainder remainder; + +int base16384_encode_safe(const char* data, int dlen, char* buf) { + int outlen = dlen / 7 * 8; + int offset = dlen % 7; + switch(offset) { // 算上偏移标志字符占用的2字节 + case 0: break; + case 1: outlen += 4; break; + case 2: + case 3: outlen += 6; break; + case 4: + case 5: outlen += 8; break; + case 6: outlen += 10; break; + default: break; + } + #ifdef DEBUG + printf("outlen: %llu, offset: %u, malloc: %llu\n", outlen, offset, outlen + 8); + #endif + uint64_t* vals = (uint64_t*)buf; + uint64_t n = 0; + int64_t i = 0; + for(; i < dlen - 7; i += 7) { + register uint64_t sum = 0; + register uint64_t shift = htobe64(*(uint64_t*)(data+i))>>2; + sum |= shift & 0x3fff000000000000; + shift >>= 2; + sum |= shift & 0x00003fff00000000; + shift >>= 2; + sum |= shift & 0x000000003fff0000; + shift >>= 2; + sum |= shift & 0x0000000000003fff; + sum += 0x4e004e004e004e00; + vals[n++] = be64toh(sum); + #ifdef DEBUG + printf("i: %llu, add sum: %016llx\n", i, sum); + #endif + } + remainder valbuf; + if(dlen - i == 7) { + memcpy(valbuf.buf, data+i, 7); + register uint64_t sum = 0; + register uint64_t shift = htobe64(valbuf.val)>>2; + sum |= shift & 0x3fff000000000000; + shift >>= 2; + sum |= shift & 0x00003fff00000000; + shift >>= 2; + sum |= shift & 0x000000003fff0000; + shift >>= 2; + sum |= shift & 0x0000000000003fff; + sum += 0x4e004e004e004e00; + vals[n++] = be64toh(sum); + return outlen; + } + int o = offset; + if(o--) { + register uint64_t sum = 0x000000000000003f & (data[i] >> 2); + sum |= ((uint64_t)data[i] << 14) & 0x000000000000c000; + if(o--) { + sum |= ((uint64_t)data[i + 1] << 6) & 0x0000000000003f00; + sum |= ((uint64_t)data[i + 1] << 20) & 0x0000000000300000; + if(o--) { + sum |= ((uint64_t)data[i + 2] << 12) & 0x00000000000f0000; + sum |= ((uint64_t)data[i + 2] << 28) & 0x00000000f0000000; + if(o--) { + sum |= ((uint64_t)data[i + 3] << 20) & 0x000000000f000000; + sum |= ((uint64_t)data[i + 3] << 34) & 0x0000003c00000000; + if(o--) { + sum |= ((uint64_t)data[i + 4] << 26) & 0x0000000300000000; + sum |= ((uint64_t)data[i + 4] << 42) & 0x0000fc0000000000; + if(o--) { + sum |= ((uint64_t)data[i + 5] << 34) & 0x0000030000000000; + sum |= ((uint64_t)data[i + 5] << 48) & 0x003f000000000000; + } + } + } + } + } + sum += 0x004e004e004e004e; + #ifdef WORDS_BIGENDIAN + valbuf.val = __builtin_bswap64(sum); + #else + valbuf.val = sum; + #endif + memcpy(&vals[n], valbuf.buf, outlen-2-(int)n*(int)sizeof(uint64_t)); + #ifdef DEBUG + printf("i: %llu, add sum: %016llx\n", i, sum); + #endif + buf[outlen - 2] = '='; + buf[outlen - 1] = offset; + } + return outlen; +} + int base16384_encode(const char* data, int dlen, char* buf) { int outlen = dlen / 7 * 8; int offset = dlen % 7; @@ -134,6 +233,86 @@ int base16384_encode_unsafe(const char* data, int dlen, char* buf) { return outlen; } +int base16384_decode_safe(const char* data, int dlen, char* buf) { + int outlen = dlen; + int offset = 0; + if(data[dlen-2] == '=') { + offset = data[dlen-1]; + switch(offset) { // 算上偏移标志字符占用的2字节 + case 0: break; + case 1: outlen -= 4; break; + case 2: + case 3: outlen -= 6; break; + case 4: + case 5: outlen -= 8; break; + case 6: outlen -= 10; break; + default: break; + } + } + outlen = outlen / 8 * 7 + offset; + uint64_t* vals = (uint64_t*)data; + uint64_t n = 0; + int64_t i = 0; + for(; i < outlen - 7; n++, i+=7) { + register uint64_t sum = 0; + register uint64_t shift = htobe64(vals[n]) - 0x4e004e004e004e00; + shift <<= 2; + sum |= shift & 0xfffc000000000000; + shift <<= 2; + sum |= shift & 0x0003fff000000000; + shift <<= 2; + sum |= shift & 0x0000000fffc00000; + shift <<= 2; + sum |= shift & 0x00000000003fff00; + *(uint64_t*)(buf+i) = be64toh(sum); + #ifdef DEBUG + printf("i: %llu, add sum: %016llx\n", i, sum); + #endif + } + remainder valbuf; + if(outlen - i == 7) { + register uint64_t sum = 0; + register uint64_t shift = htobe64(vals[n]) - 0x4e004e004e004e00; + shift <<= 2; + sum |= shift & 0xfffc000000000000; + shift <<= 2; + sum |= shift & 0x0003fff000000000; + shift <<= 2; + sum |= shift & 0x0000000fffc00000; + shift <<= 2; + sum |= shift & 0x00000000003fff00; + valbuf.val = be64toh(sum); + memcpy(buf+i, valbuf.buf, 7); + } else if(offset--) { + memcpy(valbuf.buf, &vals[n], dlen-2-(int)n*(int)sizeof(uint64_t)); + #ifdef WORDS_BIGENDIAN + register uint64_t sum = __builtin_bswap64(valbuf.val) - 0x000000000000004e; + #else + register uint64_t sum = valbuf.val - 0x000000000000004e; + #endif + buf[i++] = ((sum & 0x000000000000003f) << 2) | ((sum & 0x000000000000c000) >> 14); + if(offset--) { + sum -= 0x00000000004e0000; + buf[i++] = ((sum & 0x0000000000003f00) >> 6) | ((sum & 0x0000000000300000) >> 20); + if(offset--) { + buf[i++] = ((sum & 0x00000000000f0000) >> 12) | ((sum & 0x00000000f0000000) >> 28); + if(offset--) { + sum -= 0x0000004e00000000; + buf[i++] = ((sum & 0x000000000f000000) >> 20) | ((sum & 0x0000003c00000000) >> 34); + if(offset--) { + buf[i++] = ((sum & 0x0000000300000000) >> 26) | ((sum & 0x0000fc0000000000) >> 42); + if(offset--) { + sum -= 0x004e000000000000; + buf[i] = ((sum & 0x0000030000000000) >> 34) | ((sum & 0x003f000000000000) >> 48); + } + } + } + } + } + } + return outlen; +} + int base16384_decode(const char* data, int dlen, char* buf) { int outlen = dlen; int offset = 0; diff --git a/base16384.h b/base16384.h index 7ea5d88..5707ca3 100644 --- a/base16384.h +++ b/base16384.h @@ -116,6 +116,15 @@ static inline int base16384_decode_len(int dlen, int offset) { return _base16384_decode_len(dlen, offset) + 16; // 多出 16 字节用于 unsafe 循环覆盖 } +/** + * @brief safely encode data and write result into buf + * @param data data to encode, no data overread + * @param dlen the data length + * @param buf the output buffer, whose size can be exactly `_base16384_encode_len` + * @return the total length written +*/ +int base16384_encode_safe(const char* data, int dlen, char* buf); + /** * @brief encode data and write result into buf * @param data data to encode @@ -134,6 +143,15 @@ int base16384_encode(const char* data, int dlen, char* buf); */ int base16384_encode_unsafe(const char* data, int dlen, char* buf); +/** + * @brief safely decode data and write result into buf + * @param data data to decode, no data overread + * @param dlen the data length + * @param buf the output buffer, whose size can be exactly `_base16384_decode_len` + * @return the total length written +*/ +int base16384_decode_safe(const char* data, int dlen, char* buf); + /** * @brief decode data and write result into buf * @param data data to decode diff --git a/file.c b/file.c index c6953ff..049b18e 100644 --- a/file.c +++ b/file.c @@ -170,7 +170,7 @@ base16384_err_t base16384_encode_file_detailed(const char* input, const char* ou fputc(0xFE, fpo); fputc(0xFF, fpo); } - int n = base16384_encode(input_file, (int)inputsize, decbuf); + int n = base16384_encode_safe(input_file, (int)inputsize, decbuf); if(n && fwrite(decbuf, n, 1, fpo) <= 0) { goto_base16384_file_detailed_cleanup(encode, base16384_err_write_file, { munmap(input_file, (size_t)inputsize+16); @@ -317,8 +317,8 @@ base16384_err_t base16384_decode_file_detailed(const char* input, const char* ou if(input_file == MAP_FAILED) { goto_base16384_file_detailed_cleanup(decode, base16384_err_map_input_file, close(fd)); } - int off = skip_offset(input_file); - int n = base16384_decode(input_file+off, inputsize-off, encbuf); + int n = skip_offset(input_file); + n = base16384_decode_safe(input_file+n, inputsize-n, encbuf); if(n && fwrite(encbuf, n, 1, fpo) <= 0) { goto_base16384_file_detailed_cleanup(decode, base16384_err_write_file, { munmap(input_file, (size_t)inputsize+16); diff --git a/test/coder_test.c b/test/coder_test.c index fe391f6..10d7769 100644 --- a/test/coder_test.c +++ b/test/coder_test.c @@ -43,24 +43,31 @@ char tstbuf[TEST_SIZE+16]; return 1; \ } +#define test_batch(encode, decode) \ + fputs("testing base16384_"#encode"/base16384_"#decode"...\n", stderr); \ + for(i = 0; i <= TEST_SIZE; i++) { \ + n = base16384_##encode(encbuf, i, decbuf); \ + n = base16384_##decode(decbuf, n, tstbuf); \ + if (memcmp(encbuf, tstbuf, n)) return_error(i, n); \ + } + int main() { srand(time(NULL)); int i, n; for(i = 0; i <= TEST_SIZE; i += sizeof(int)) { *(int*)(&encbuf[i]) = rand(); } - fputs("testing base16384_en/decode...\n", stderr); - for(i = 0; i <= TEST_SIZE; i++) { - n = base16384_encode(encbuf, i, decbuf); - n = base16384_decode(decbuf, n, tstbuf); - int decn = n; - if (memcmp(encbuf, tstbuf, n)) return_error(i, n); - } - fputs("testing base16384_en/ecode_unsafe...\n", stderr); - for(i = 0; i <= TEST_SIZE; i++) { - n = base16384_encode_unsafe(encbuf, i, decbuf); - n = base16384_decode_unsafe(decbuf, n, tstbuf); - if ((n = memcmp(encbuf, tstbuf, n))) return_error(i, n); - } + + test_batch(encode, decode); + test_batch(encode, decode_unsafe); + test_batch(encode, decode_safe); + + test_batch(encode_unsafe, decode); + test_batch(encode_unsafe, decode_unsafe); + test_batch(encode_unsafe, decode_safe); + + test_batch(encode_safe, decode); + test_batch(encode_safe, decode_unsafe); + test_batch(encode_safe, decode_safe); return 0; } diff --git a/test/wrap_test.c b/test/wrap_test.c index b6abb1b..2aa7b5b 100644 --- a/test/wrap_test.c +++ b/test/wrap_test.c @@ -98,18 +98,16 @@ int main() { fputs("testing base16384_en/decode_file...\n", stderr); init_input_file(); for(i = TEST_SIZE; i > 0; i--) { - fprintf(stderr, "loop@%d\n", i); reset_and_truncate(fd, i); loop_ok(close(fd), i, "close"); - fputs("base16384_encode_file\n", stderr); + err = base16384_encode_file(TEST_INPUT_FILENAME, TEST_OUTPUT_FILENAME, encbuf, decbuf); base16384_loop_ok(err); - fputs("base16384_decode_file\n", stderr); + err = base16384_decode_file(TEST_OUTPUT_FILENAME, TEST_VALIDATE_FILENAME, encbuf, decbuf); base16384_loop_ok(err); - fputs("validate_result\n", stderr); + validate_result(); - fputs("fin\n\n", stderr); } fputs("testing base16384_en/decode_fp...\n", stderr); From 7c8080d1151e4bcf9058a251cdee7fb22bcf9aa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Fri, 5 Apr 2024 00:12:10 +0900 Subject: [PATCH 23/35] feat(test): add file_test.c --- file.c | 12 +-- test/file_test.c | 188 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 194 insertions(+), 6 deletions(-) create mode 100644 test/file_test.c diff --git a/file.c b/file.c index 049b18e..038dcd4 100644 --- a/file.c +++ b/file.c @@ -162,7 +162,7 @@ base16384_err_t base16384_encode_file_detailed(const char* input, const char* ou if(fd < 0) { goto_base16384_file_detailed_cleanup(encode, base16384_err_open_input_file, {}); } - char *input_file = mmap(NULL, (size_t)inputsize+16, PROT_READ, MAP_PRIVATE, fd, 0); + char *input_file = mmap(NULL, (size_t)inputsize, PROT_READ, MAP_PRIVATE, fd, 0); if(input_file == MAP_FAILED) { goto_base16384_file_detailed_cleanup(encode, base16384_err_map_input_file, close(fd)); } @@ -173,11 +173,11 @@ base16384_err_t base16384_encode_file_detailed(const char* input, const char* ou int n = base16384_encode_safe(input_file, (int)inputsize, decbuf); if(n && fwrite(decbuf, n, 1, fpo) <= 0) { goto_base16384_file_detailed_cleanup(encode, base16384_err_write_file, { - munmap(input_file, (size_t)inputsize+16); + munmap(input_file, (size_t)inputsize); close(fd); }); } - munmap(input_file, (size_t)inputsize+16); + munmap(input_file, (size_t)inputsize); close(fd); } #endif @@ -313,7 +313,7 @@ base16384_err_t base16384_decode_file_detailed(const char* input, const char* ou if(fd < 0) { goto_base16384_file_detailed_cleanup(decode, base16384_err_open_input_file, {}); } - char *input_file = mmap(NULL, (size_t)inputsize+16, PROT_READ, MAP_PRIVATE, fd, 0); + char *input_file = mmap(NULL, (size_t)inputsize, PROT_READ, MAP_PRIVATE, fd, 0); if(input_file == MAP_FAILED) { goto_base16384_file_detailed_cleanup(decode, base16384_err_map_input_file, close(fd)); } @@ -321,11 +321,11 @@ base16384_err_t base16384_decode_file_detailed(const char* input, const char* ou n = base16384_decode_safe(input_file+n, inputsize-n, encbuf); if(n && fwrite(encbuf, n, 1, fpo) <= 0) { goto_base16384_file_detailed_cleanup(decode, base16384_err_write_file, { - munmap(input_file, (size_t)inputsize+16); + munmap(input_file, (size_t)inputsize); close(fd); }); } - munmap(input_file, (size_t)inputsize+16); + munmap(input_file, (size_t)inputsize); close(fd); } #endif diff --git a/test/file_test.c b/test/file_test.c new file mode 100644 index 0000000..b3565d3 --- /dev/null +++ b/test/file_test.c @@ -0,0 +1,188 @@ + +#ifdef _WIN32 + #include + #define ftruncate _chsize_s +#else + #define _POSIX1_SOURCE 2 + #include +#endif +#include +#include +#include +#include +#include +#include + +#include "base16384.h" +#include "binary.h" + +#define TEST_SIZE (4096) +#define TEST_INPUT_FILENAME "wrap_test_input.bin" +#define TEST_OUTPUT_FILENAME "wrap_test_output.bin" +#define TEST_VALIDATE_FILENAME "wrap_test_validate.bin" + +char encbuf[BASE16384_ENCBUFSZ]; +char decbuf[BASE16384_DECBUFSZ]; +char tstbuf[BASE16384_ENCBUFSZ]; + +#define ok(has_failed, reason) \ + if (has_failed) { \ + perror(reason); \ + return 1; \ + } + +#define loop_ok(has_failed, i, reason) \ + if (has_failed) { \ + fprintf(stderr, "loop @%d: ", i); \ + perror(reason); \ + return 1; \ + } + +#define reset_and_truncate(fd, i) { \ + fd = open(TEST_INPUT_FILENAME, O_RDWR); \ + ok(!fd, "open"); \ + loop_ok(lseek(fd, 0, SEEK_SET), i, "lseek"); \ + loop_ok(ftruncate(fd, i), i, "ftruncate"); \ +} + +#define base16384_loop_ok(err) \ + if (err) { \ + fprintf(stderr, "loop @%d: ", i); \ + base16384_perror(err); \ + return 1; \ + } + +#define validate_result() \ + uint64_t buf, sum_input = 0, sum_validate = 0; \ + fp = fopen(TEST_INPUT_FILENAME, "rb"); { \ + loop_ok(!fp, i, "fopen"); \ + while (fread(&buf, sizeof(sum_input), 1, fp) == 1) sum_input += buf; \ + buf = 0; \ + while (fread(&buf, 1, 1, fp) == 1) { \ + sum_input += buf; \ + sum_input = LEFTROTATE(sum_input, 4); \ + } \ + } fclose(fp); \ + fp = fopen(TEST_VALIDATE_FILENAME, "rb"); { \ + loop_ok(!fp, i, "fopen"); \ + while (fread(&buf, sizeof(sum_validate), 1, fp) == 1) sum_validate += buf; \ + buf = 0; \ + while (fread(&buf, 1, 1, fp) == 1) { \ + sum_validate += buf; \ + sum_validate = LEFTROTATE(sum_validate, 4); \ + } \ + } fclose(fp); \ + if (sum_input != sum_validate) { \ + fprintf(stderr, "loop @%d, expect: %016llx, got: %016llx: ", i, (unsigned long long)sum_input, (unsigned long long)sum_validate); \ + fputs(TEST_INPUT_FILENAME " and " TEST_VALIDATE_FILENAME " mismatch.", stderr); \ + return 1; \ + } + +#define init_input_file() \ + for(i = 0; i < TEST_SIZE; i += sizeof(int)) { \ + *(int*)(&encbuf[i]) = rand(); \ + } \ + fp = fopen(TEST_INPUT_FILENAME, "wb"); \ + ok(!fp, "fopen"); \ + ok(fwrite(encbuf, TEST_SIZE, 1, fp) != 1, "fwrite"); \ + ok(fclose(fp), "fclose"); \ + fputs("input file created.\n", stderr); + +#define test_file_detailed(flag) \ + fputs("testing base16384_en/decode_file with flag "#flag"...\n", stderr); \ + init_input_file(); \ + for(i = TEST_SIZE; i > 0; i--) { \ + reset_and_truncate(fd, i); \ + loop_ok(close(fd), i, "close"); \ + \ + err = base16384_encode_file_detailed(TEST_INPUT_FILENAME, TEST_OUTPUT_FILENAME, encbuf, decbuf, flag); \ + base16384_loop_ok(err); \ + \ + err = base16384_decode_file_detailed(TEST_OUTPUT_FILENAME, TEST_VALIDATE_FILENAME, encbuf, decbuf, flag); \ + base16384_loop_ok(err); \ + \ + validate_result(); \ + } + +#define test_fp_detailed(flag) \ + fputs("testing base16384_en/decode_fp...\n", stderr); \ + init_input_file(); \ + for(i = TEST_SIZE; i > 0; i--) { \ + reset_and_truncate(fd, i); \ + loop_ok(close(fd), i, "close"); \ + \ + FILE* fpin = fopen(TEST_INPUT_FILENAME, "rb"); \ + loop_ok(!fpin, i, "fopen"); \ + \ + FILE* fpout = fopen(TEST_OUTPUT_FILENAME, "wb+"); \ + loop_ok(!fpout, i, "fopen"); \ + \ + err = base16384_encode_fp_detailed(fpin, fpout, encbuf, decbuf, flag); \ + base16384_loop_ok(err); \ + \ + loop_ok(fclose(fpin), i, "fclose"); \ + \ + FILE* fpval = fopen(TEST_VALIDATE_FILENAME, "wb"); \ + loop_ok(!fpval, i, "fopen"); \ + \ + rewind(fpout); \ + \ + err = base16384_decode_fp_detailed(fpout, fpval, encbuf, decbuf, flag); \ + base16384_loop_ok(err); \ + \ + loop_ok(fclose(fpout), i, "fclose"); \ + loop_ok(fclose(fpval), i, "fclose"); \ + \ + validate_result(); \ + } + +#define test_fd_detailed(flag) \ + fputs("testing base16384_en/decode_fd...\n", stderr); \ + init_input_file(); \ + for(i = TEST_SIZE; i > 0; i--) { \ + reset_and_truncate(fd, i); \ + \ + int fdout = open(TEST_OUTPUT_FILENAME, O_RDWR|O_TRUNC|O_CREAT|O_APPEND); \ + loop_ok(!fdout, i, "open"); \ + \ + err = base16384_encode_fd_detailed(fd, fdout, encbuf, decbuf, 0); \ + base16384_loop_ok(err); \ + loop_ok(close(fd), i, "close"); \ + \ + int fdval = open(TEST_VALIDATE_FILENAME, O_WRONLY|O_TRUNC|O_CREAT); \ + loop_ok(!fdval, i, "open"); \ + \ + loop_ok(lseek(fdout, 0, SEEK_SET), i, "lseek"); \ + \ + err = base16384_decode_fd_detailed(fdout, fdval, encbuf, decbuf, 0); \ + base16384_loop_ok(err); \ + \ + loop_ok(close(fdout), i, "close"); \ + loop_ok(close(fdval), i, "close"); \ + \ + validate_result(); \ + } + +#define test_detailed(name) \ + test_##name##_detailed(0); \ + test_##name##_detailed(BASE16384_FLAG_NOHEADER); \ + test_##name##_detailed(BASE16384_FLAG_SUM_CHECK_ON_REMAIN); \ + test_##name##_detailed(BASE16384_FLAG_NOHEADER|BASE16384_FLAG_SUM_CHECK_ON_REMAIN); + +int main() { + srand(time(NULL)); + + FILE* fp; + int fd, i; + base16384_err_t err; + + test_detailed(file); + test_detailed(fp); + test_detailed(fd); + + remove(TEST_INPUT_FILENAME); + remove(TEST_OUTPUT_FILENAME); + remove(TEST_VALIDATE_FILENAME); + + return 0; +} From cde0cacd07b9ef0c8f437354cb14d93e5e1b9227 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Fri, 5 Apr 2024 00:48:13 +0900 Subject: [PATCH 24/35] fix(file): base16384_decode_fd_detailed --- CMakeLists.txt | 4 ++++ base16384.h | 8 ++++++-- file.c | 34 +++++++++++++++++++--------------- test/file_test.c | 4 ++-- 4 files changed, 31 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0600cec..ca4b762 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,10 @@ if (${isBigEndian}) add_definitions(-DWORDS_BIGENDIAN) endif () +if (BUILD STREQUAL "test") + add_definitions(-DBASE16384_BUFSZ_FACTOR=1) +endif () + add_executable(base16384_b base16384.c) IF ((NOT FORCE_32BIT) AND CMAKE_SIZEOF_VOID_P EQUAL 8) diff --git a/base16384.h b/base16384.h index 5707ca3..339dabb 100644 --- a/base16384.h +++ b/base16384.h @@ -42,8 +42,12 @@ enum base16384_err_t { */ typedef enum base16384_err_t base16384_err_t; -#define _BASE16384_ENCBUFSZ (BUFSIZ*1024/7*7) -#define _BASE16384_DECBUFSZ (BUFSIZ*1024/8*8) +#ifndef BASE16384_BUFSZ_FACTOR + #define BASE16384_BUFSZ_FACTOR (1024) +#endif + +#define _BASE16384_ENCBUFSZ ((BUFSIZ*BASE16384_BUFSZ_FACTOR)/7*7) +#define _BASE16384_DECBUFSZ ((BUFSIZ*BASE16384_BUFSZ_FACTOR)/8*8) #define BASE16384_ENCBUFSZ (_BASE16384_ENCBUFSZ+16) #define BASE16384_DECBUFSZ (_BASE16384_DECBUFSZ+16) diff --git a/file.c b/file.c index 038dcd4..b095b44 100644 --- a/file.c +++ b/file.c @@ -393,40 +393,44 @@ base16384_err_t base16384_decode_fd_detailed(int input, int output, char* encbuf errno = EINVAL; return base16384_err_fopen_output_file; } - off_t inputsize = _BASE16384_DECBUFSZ-1; - int cnt = 0; + off_t inputsize = _BASE16384_DECBUFSZ; + int p = 0, n; uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE; + uint8_t remains[8]; decbuf[0] = 0; - if(read(input, decbuf, 2) != 2) { + if(read(input, remains, 2) != 2) { return base16384_err_read_file; } - if(decbuf[0] != (char)(0xfe)) { - cnt = read(input, decbuf+2, inputsize-2)+2; - } else { - cnt = read(input, decbuf, inputsize); - } - if(cnt > 0) do { + if(remains[0] != (uint8_t)(0xfe)) p = 2; + while((n = read(input, decbuf+p, inputsize-p)) > 0) { + if(p) { + memcpy(decbuf, remains, p); + n += p; + p = 0; + } uint16_t next = is_next_end_fd(input); if(errno) { return base16384_err_read_file; } if((uint16_t)(~next)) { - if(next&0xff00) decbuf[cnt++] = '='; - decbuf[cnt++] = (char)(next&0x00ff); + if(next&0xff00) { + decbuf[n++] = '='; + decbuf[n++] = (char)(next&0x00ff); + } else remains[p++] = (char)(next&0x00ff); } #ifdef DEBUG fprintf(stderr, "decode chunk: %d, last2: %c %02x\n", cnt, decbuf[cnt-2], (uint8_t)decbuf[cnt-1]); #endif - cnt = base16384_decode_unsafe(decbuf, cnt, encbuf); - if(cnt && write(output, encbuf, cnt) != cnt) { + n = base16384_decode_unsafe(decbuf, n, encbuf); + if(n && write(output, encbuf, n) != n) { return base16384_err_write_file; } if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) { - if (calc_and_check_sum(&sum, cnt, encbuf)) { + if (calc_and_check_sum(&sum, n, encbuf)) { errno = EINVAL; return base16384_err_invalid_decoding_checksum; } } - } while((cnt = read(input, decbuf, inputsize)) > 0); + } return base16384_err_ok; } diff --git a/test/file_test.c b/test/file_test.c index b3565d3..ce720fa 100644 --- a/test/file_test.c +++ b/test/file_test.c @@ -105,7 +105,7 @@ char tstbuf[BASE16384_ENCBUFSZ]; } #define test_fp_detailed(flag) \ - fputs("testing base16384_en/decode_fp...\n", stderr); \ + fputs("testing base16384_en/decode_fp with flag "#flag"...\n", stderr); \ init_input_file(); \ for(i = TEST_SIZE; i > 0; i--) { \ reset_and_truncate(fd, i); \ @@ -137,7 +137,7 @@ char tstbuf[BASE16384_ENCBUFSZ]; } #define test_fd_detailed(flag) \ - fputs("testing base16384_en/decode_fd...\n", stderr); \ + fputs("testing base16384_en/decode_fd with flag "#flag"...\n", stderr); \ init_input_file(); \ for(i = TEST_SIZE; i > 0; i--) { \ reset_and_truncate(fd, i); \ From 4b4993d66d95ebea5c9736b109b1f057eed0ad37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Fri, 5 Apr 2024 02:03:25 +0900 Subject: [PATCH 25/35] fix(file): large file process --- base16384.h | 2 +- binary.h | 53 ++++++++++++++++++++ file.c | 124 +++++++++++++++++++++-------------------------- test/file_test.c | 20 +++++--- test/wrap_test.c | 11 +++-- 5 files changed, 128 insertions(+), 82 deletions(-) diff --git a/base16384.h b/base16384.h index 339dabb..9a8e6fc 100644 --- a/base16384.h +++ b/base16384.h @@ -43,7 +43,7 @@ enum base16384_err_t { typedef enum base16384_err_t base16384_err_t; #ifndef BASE16384_BUFSZ_FACTOR - #define BASE16384_BUFSZ_FACTOR (1024) + #define BASE16384_BUFSZ_FACTOR (8) #endif #define _BASE16384_ENCBUFSZ ((BUFSIZ*BASE16384_BUFSZ_FACTOR)/7*7) diff --git a/binary.h b/binary.h index 7f180d7..1feaef5 100644 --- a/binary.h +++ b/binary.h @@ -87,4 +87,57 @@ // leftrotate function definition #define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (sizeof(x)*8 - (c)))) +static inline uint32_t calc_sum(uint32_t sum, size_t cnt, char* encbuf) { + uint32_t i; + #ifdef DEBUG + fprintf(stderr, "cnt: %zu, roundin: %08x, ", cnt, sum); + #endif + for(i = 0; i < cnt/sizeof(sum); i++) { + #ifdef DEBUG + if (!i) { + fprintf(stderr, "firstval: %08x, ", htobe32(((uint32_t*)encbuf)[i])); + } + #endif + sum += ~LEFTROTATE(htobe32(((uint32_t*)encbuf)[i]), encbuf[i*sizeof(sum)]%(8*sizeof(sum))); + } + #ifdef DEBUG + fprintf(stderr, "roundmid: %08x", sum); + #endif + size_t rem = cnt % sizeof(sum); + if(rem) { + uint32_t x = htobe32(((uint32_t*)encbuf)[i]) & (0xffffffff << (8*(sizeof(sum)-rem))); + sum += ~LEFTROTATE(x, encbuf[i*sizeof(sum)]%(8*sizeof(sum))); + #ifdef DEBUG + fprintf(stderr, ", roundrem:%08x\n", sum); + #endif + } + #ifdef DEBUG + else fprintf(stderr, "\n"); + #endif + return sum; +} + +static inline uint32_t calc_and_embed_sum(uint32_t sum, size_t cnt, char* encbuf) { + sum = calc_sum(sum, cnt, encbuf); + if(cnt%7) { // last encode + *(uint32_t*)(&encbuf[cnt]) = htobe32(sum); + } + return sum; +} + +static inline int calc_and_check_sum(uint32_t* s, size_t cnt, char* encbuf) { + uint32_t sum = calc_sum(*s, cnt, encbuf); + if(cnt%7) { // is last decode block + int shift = (int[]){0, 26, 20, 28, 22, 30, 24}[cnt%7]; + uint32_t sum_read = be32toh((*(uint32_t*)(&encbuf[cnt]))) >> shift; + sum >>= shift; + #ifdef DEBUG + fprintf(stderr, "cntrm: %lu, mysum: %08x, sumrd: %08x\n", cnt%7, sum, sum_read); + #endif + return sum != sum_read; + } + *s = sum; + return 0; +} + #endif diff --git a/file.c b/file.c index b095b44..87e6a5e 100644 --- a/file.c +++ b/file.c @@ -47,59 +47,6 @@ static inline off_t get_file_size(const char* filepath) { #define is_standard_io(filename) (*(uint16_t*)(filename) == *(uint16_t*)"-") -static inline uint32_t calc_sum(uint32_t sum, size_t cnt, char* encbuf) { - uint32_t i; - #ifdef DEBUG - fprintf(stderr, "cnt: %zu, roundin: %08x, ", cnt, sum); - #endif - for(i = 0; i < cnt/sizeof(sum); i++) { - #ifdef DEBUG - if (!i) { - fprintf(stderr, "firstval: %08x, ", htobe32(((uint32_t*)encbuf)[i])); - } - #endif - sum += ~LEFTROTATE(htobe32(((uint32_t*)encbuf)[i]), encbuf[i*sizeof(sum)]%(8*sizeof(sum))); - } - #ifdef DEBUG - fprintf(stderr, "roundmid: %08x", sum); - #endif - size_t rem = cnt % sizeof(sum); - if(rem) { - uint32_t x = htobe32(((uint32_t*)encbuf)[i]) & (0xffffffff << (8*(sizeof(sum)-rem))); - sum += ~LEFTROTATE(x, encbuf[i*sizeof(sum)]%(8*sizeof(sum))); - #ifdef DEBUG - fprintf(stderr, ", roundrem:%08x\n", sum); - #endif - } - #ifdef DEBUG - else fprintf(stderr, "\n"); - #endif - return sum; -} - -static inline uint32_t calc_and_embed_sum(uint32_t sum, size_t cnt, char* encbuf) { - sum = calc_sum(sum, cnt, encbuf); - if(cnt%7) { // last encode - *(uint32_t*)(&encbuf[cnt]) = htobe32(sum); - } - return sum; -} - -static inline int calc_and_check_sum(uint32_t* s, size_t cnt, char* encbuf) { - uint32_t sum = calc_sum(*s, cnt, encbuf); - if(cnt%7) { // is last decode block - int shift = (int[]){0, 26, 20, 28, 22, 30, 24}[cnt%7]; - uint32_t sum_read = be32toh((*(uint32_t*)(&encbuf[cnt]))) >> shift; - sum >>= shift; - #ifdef DEBUG - fprintf(stderr, "cntrm: %lu, mysum: %08x, sumrd: %08x\n", cnt%7, sum, sum_read); - #endif - return sum != sum_read; - } - *s = sum; - return 0; -} - #define goto_base16384_file_detailed_cleanup(method, reason, dobeforereturn) { \ errnobak = errno; \ retval = reason; \ @@ -112,13 +59,13 @@ base16384_err_t base16384_encode_file_detailed(const char* input, const char* ou FILE* fp = NULL; FILE* fpo; uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE; - int errnobak = 0; + int errnobak = 0, is_stdin = is_standard_io(input); base16384_err_t retval = base16384_err_ok; if(!input || !output || strlen(input) <= 0 || strlen(output) <= 0) { errno = EINVAL; return base16384_err_invalid_file_name; } - if(is_standard_io(input)) { // read from stdin + if(is_stdin) { // read from stdin inputsize = _BASE16384_ENCBUFSZ; fp = stdin; } else inputsize = get_file_size(input); @@ -150,8 +97,14 @@ base16384_err_t base16384_encode_file_detailed(const char* input, const char* ou #endif size_t cnt; while((cnt = fread(encbuf, sizeof(char), inputsize, fp)) > 0) { + int n; + while(cnt%7) { + n = fread(encbuf+cnt, sizeof(char), 1, fp); + if(n > 0) cnt++; + else break; + } if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) sum = calc_and_embed_sum(sum, cnt, encbuf); - int n = base16384_encode_unsafe(encbuf, cnt, decbuf); + n = base16384_encode_unsafe(encbuf, cnt, decbuf); if(n && fwrite(decbuf, n, 1, fpo) <= 0) { goto_base16384_file_detailed_cleanup(encode, base16384_err_write_file, {}); } @@ -183,7 +136,7 @@ base16384_err_t base16384_encode_file_detailed(const char* input, const char* ou #endif base16384_encode_file_detailed_cleanup: if(fpo && !is_standard_io(output)) fclose(fpo); - if(fp && !is_standard_io(input)) fclose(fp); + if(fp && !is_stdin) fclose(fp); if(errnobak) errno = errnobak; return retval; } @@ -195,16 +148,22 @@ base16384_err_t base16384_encode_fp_detailed(FILE* input, FILE* output, char* en if(!output) { return base16384_err_fopen_output_file; } - off_t inputsize = _BASE16384_ENCBUFSZ; - size_t cnt = 0; - uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE; if(!(flag&BASE16384_FLAG_NOHEADER)) { fputc(0xFE, output); fputc(0xFF, output); } + off_t inputsize = _BASE16384_ENCBUFSZ; + uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE; + size_t cnt; while((cnt = fread(encbuf, sizeof(char), inputsize, input)) > 0) { + int n; + while(cnt%7) { + n = fread(encbuf+cnt, sizeof(char), 1, input); + if(n > 0) cnt++; + else break; + } if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) sum = calc_and_embed_sum(sum, cnt, encbuf); - int n = base16384_encode_unsafe(encbuf, cnt, decbuf); + n = base16384_encode_unsafe(encbuf, cnt, decbuf); if(n && fwrite(decbuf, n, 1, output) <= 0) { return base16384_err_write_file; } @@ -224,8 +183,14 @@ base16384_err_t base16384_encode_fd_detailed(int input, int output, char* encbuf uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE; if(!(flag&BASE16384_FLAG_NOHEADER)) write(output, "\xfe\xff", 2); while((cnt = read(input, encbuf, inputsize)) > 0) { + int n; + while(cnt%7) { + n = read(input, encbuf+cnt, sizeof(char)); + if(n > 0) cnt++; + else break; + } if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) sum = calc_and_embed_sum(sum, cnt, encbuf); - int n = base16384_encode_unsafe(encbuf, cnt, decbuf); + n = base16384_encode_unsafe(encbuf, cnt, decbuf); if(n && write(output, decbuf, n) < n) { return base16384_err_write_file; } @@ -255,12 +220,12 @@ base16384_err_t base16384_decode_file_detailed(const char* input, const char* ou FILE* fpo; uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE; base16384_err_t retval = base16384_err_ok; - int errnobak = 0; + int errnobak = 0, is_stdin = is_standard_io(input); if(!input || !output || strlen(input) <= 0 || strlen(output) <= 0) { errno = EINVAL; return base16384_err_invalid_file_name; } - if(is_standard_io(input)) { // read from stdin + if(is_stdin) { // read from stdin inputsize = _BASE16384_DECBUFSZ; fp = stdin; } else inputsize = get_file_size(input); @@ -272,7 +237,9 @@ base16384_err_t base16384_decode_file_detailed(const char* input, const char* ou if(!fpo) { return base16384_err_fopen_output_file; } + int loop_count = 0; if(inputsize >= _BASE16384_DECBUFSZ) { // stdin or big file, use decbuf & fread + if(!is_stdin) loop_count = inputsize/_BASE16384_DECBUFSZ; inputsize = _BASE16384_DECBUFSZ; #if defined _WIN32 || defined __cosmopolitan } @@ -281,8 +248,6 @@ base16384_err_t base16384_decode_file_detailed(const char* input, const char* ou if(!fp) { goto_base16384_file_detailed_cleanup(decode, base16384_err_fopen_input_file, {}); } - int cnt = 0; - int end = 0; rm_head(fp); if(errno) { goto_base16384_file_detailed_cleanup(decode, base16384_err_read_file, {}); @@ -290,7 +255,15 @@ base16384_err_t base16384_decode_file_detailed(const char* input, const char* ou #ifdef DEBUG fprintf(stderr, "inputsize: %lld\n", inputsize); #endif + int cnt; while((cnt = fread(decbuf, sizeof(char), inputsize, fp)) > 0) { + int n; + while(cnt%8) { + n = fread(decbuf+cnt, sizeof(char), 1, fp); + if(n > 0) cnt++; + else break; + } + int end; if((end = is_next_end(fp))) { decbuf[cnt++] = '='; decbuf[cnt++] = end; @@ -331,7 +304,7 @@ base16384_err_t base16384_decode_file_detailed(const char* input, const char* ou #endif base16384_decode_file_detailed_cleanup: if(fpo && !is_standard_io(output)) fclose(fpo); - if(fp && !is_standard_io(input)) fclose(fp); + if(fp && !is_stdin) fclose(fp); if(errnobak) errno = errnobak; return retval; } @@ -346,18 +319,25 @@ base16384_err_t base16384_decode_fp_detailed(FILE* input, FILE* output, char* en return base16384_err_fopen_output_file; } off_t inputsize = _BASE16384_DECBUFSZ; - int cnt = 0; - int end = 0; uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE; rm_head(input); if(errno) { return base16384_err_read_file; } + int cnt; while((cnt = fread(decbuf, sizeof(char), inputsize, input)) > 0) { + int n; + while(cnt%8) { + n = fread(decbuf+cnt, sizeof(char), 1, input); + if(n > 0) cnt++; + else break; + } + int end; if((end = is_next_end(input))) { decbuf[cnt++] = '='; decbuf[cnt++] = end; } + if(errno) return base16384_err_read_file; cnt = base16384_decode_unsafe(decbuf, cnt, encbuf); if(cnt && fwrite(encbuf, cnt, 1, output) <= 0) { return base16384_err_write_file; @@ -408,6 +388,12 @@ base16384_err_t base16384_decode_fd_detailed(int input, int output, char* encbuf n += p; p = 0; } + int x; + while(n%8) { + x = read(input, decbuf+n, sizeof(char)); + if(x > 0) n++; + else break; + } uint16_t next = is_next_end_fd(input); if(errno) { return base16384_err_read_file; diff --git a/test/file_test.c b/test/file_test.c index ce720fa..2107bca 100644 --- a/test/file_test.c +++ b/test/file_test.c @@ -17,9 +17,9 @@ #include "binary.h" #define TEST_SIZE (4096) -#define TEST_INPUT_FILENAME "wrap_test_input.bin" -#define TEST_OUTPUT_FILENAME "wrap_test_output.bin" -#define TEST_VALIDATE_FILENAME "wrap_test_validate.bin" +#define TEST_INPUT_FILENAME "file_test_input.bin" +#define TEST_OUTPUT_FILENAME "file_test_output.bin" +#define TEST_VALIDATE_FILENAME "file_test_validate.bin" char encbuf[BASE16384_ENCBUFSZ]; char decbuf[BASE16384_DECBUFSZ]; @@ -56,18 +56,18 @@ char tstbuf[BASE16384_ENCBUFSZ]; uint64_t buf, sum_input = 0, sum_validate = 0; \ fp = fopen(TEST_INPUT_FILENAME, "rb"); { \ loop_ok(!fp, i, "fopen"); \ - while (fread(&buf, sizeof(sum_input), 1, fp) == 1) sum_input += buf; \ + while (fread(&buf, sizeof(sum_input), 1, fp) > 0) sum_input += buf; \ buf = 0; \ - while (fread(&buf, 1, 1, fp) == 1) { \ + while (fread(&buf, 1, 1, fp) > 0) { \ sum_input += buf; \ sum_input = LEFTROTATE(sum_input, 4); \ } \ } fclose(fp); \ fp = fopen(TEST_VALIDATE_FILENAME, "rb"); { \ loop_ok(!fp, i, "fopen"); \ - while (fread(&buf, sizeof(sum_validate), 1, fp) == 1) sum_validate += buf; \ + while (fread(&buf, sizeof(sum_validate), 1, fp) > 0) sum_validate += buf; \ buf = 0; \ - while (fread(&buf, 1, 1, fp) == 1) { \ + while (fread(&buf, 1, 1, fp) > 0) { \ sum_validate += buf; \ sum_validate = LEFTROTATE(sum_validate, 4); \ } \ @@ -165,9 +165,13 @@ char tstbuf[BASE16384_ENCBUFSZ]; #define test_detailed(name) \ test_##name##_detailed(0); \ + fputs("one test passed.\n", stderr); \ test_##name##_detailed(BASE16384_FLAG_NOHEADER); \ + fputs("one test passed.\n", stderr); \ test_##name##_detailed(BASE16384_FLAG_SUM_CHECK_ON_REMAIN); \ - test_##name##_detailed(BASE16384_FLAG_NOHEADER|BASE16384_FLAG_SUM_CHECK_ON_REMAIN); + fputs("one test passed.\n", stderr); \ + test_##name##_detailed(BASE16384_FLAG_NOHEADER|BASE16384_FLAG_SUM_CHECK_ON_REMAIN); \ + fputs("one test passed.\n", stderr); int main() { srand(time(NULL)); diff --git a/test/wrap_test.c b/test/wrap_test.c index 2aa7b5b..4bc5358 100644 --- a/test/wrap_test.c +++ b/test/wrap_test.c @@ -56,18 +56,18 @@ char tstbuf[BASE16384_ENCBUFSZ]; uint64_t buf, sum_input = 0, sum_validate = 0; \ fp = fopen(TEST_INPUT_FILENAME, "rb"); { \ loop_ok(!fp, i, "fopen"); \ - while (fread(&buf, sizeof(sum_input), 1, fp) == 1) sum_input += buf; \ + while (fread(&buf, sizeof(sum_input), 1, fp) > 0) sum_input += buf; \ buf = 0; \ - while (fread(&buf, 1, 1, fp) == 1) { \ + while (fread(&buf, 1, 1, fp) > 0) { \ sum_input += buf; \ sum_input = LEFTROTATE(sum_input, 4); \ } \ } fclose(fp); \ fp = fopen(TEST_VALIDATE_FILENAME, "rb"); { \ loop_ok(!fp, i, "fopen"); \ - while (fread(&buf, sizeof(sum_validate), 1, fp) == 1) sum_validate += buf; \ + while (fread(&buf, sizeof(sum_validate), 1, fp) > 0) sum_validate += buf; \ buf = 0; \ - while (fread(&buf, 1, 1, fp) == 1) { \ + while (fread(&buf, 1, 1, fp) > 0) { \ sum_validate += buf; \ sum_validate = LEFTROTATE(sum_validate, 4); \ } \ @@ -109,6 +109,7 @@ int main() { validate_result(); } + fputs("one test passed.\n", stderr); fputs("testing base16384_en/decode_fp...\n", stderr); init_input_file(); @@ -140,6 +141,7 @@ int main() { validate_result(); } + fputs("one test passed.\n", stderr); fputs("testing base16384_en/decode_fd...\n", stderr); init_input_file(); @@ -166,6 +168,7 @@ int main() { validate_result(); } + fputs("one test passed.\n", stderr); remove(TEST_INPUT_FILENAME); remove(TEST_OUTPUT_FILENAME); From 2c1db601a66ad27e0f8e19ad54048c84d70a1775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Fri, 5 Apr 2024 02:14:48 +0900 Subject: [PATCH 26/35] chore(test): add documents --- test/coder_test.c | 18 ++++++++++ test/file_test.c | 71 ++++++++++----------------------------- test/file_test.h | 85 +++++++++++++++++++++++++++++++++++++++++++++++ test/wrap_test.c | 71 ++++++++++----------------------------- 4 files changed, 139 insertions(+), 106 deletions(-) create mode 100644 test/file_test.h diff --git a/test/coder_test.c b/test/coder_test.c index 10d7769..d20674a 100644 --- a/test/coder_test.c +++ b/test/coder_test.c @@ -1,3 +1,21 @@ +/* test/coder_test.c + * This file is part of the base16384 distribution (https://github.com/fumiama/base16384). + * Copyright (c) 2022-2024 Fumiama Minamoto. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include #include #include diff --git a/test/file_test.c b/test/file_test.c index 2107bca..9382a81 100644 --- a/test/file_test.c +++ b/test/file_test.c @@ -1,3 +1,20 @@ +/* test/file_test.c + * This file is part of the base16384 distribution (https://github.com/fumiama/base16384). + * Copyright (c) 2022-2024 Fumiama Minamoto. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #ifdef _WIN32 #include @@ -15,6 +32,7 @@ #include "base16384.h" #include "binary.h" +#include "file_test.h" #define TEST_SIZE (4096) #define TEST_INPUT_FILENAME "file_test_input.bin" @@ -25,59 +43,6 @@ char encbuf[BASE16384_ENCBUFSZ]; char decbuf[BASE16384_DECBUFSZ]; char tstbuf[BASE16384_ENCBUFSZ]; -#define ok(has_failed, reason) \ - if (has_failed) { \ - perror(reason); \ - return 1; \ - } - -#define loop_ok(has_failed, i, reason) \ - if (has_failed) { \ - fprintf(stderr, "loop @%d: ", i); \ - perror(reason); \ - return 1; \ - } - -#define reset_and_truncate(fd, i) { \ - fd = open(TEST_INPUT_FILENAME, O_RDWR); \ - ok(!fd, "open"); \ - loop_ok(lseek(fd, 0, SEEK_SET), i, "lseek"); \ - loop_ok(ftruncate(fd, i), i, "ftruncate"); \ -} - -#define base16384_loop_ok(err) \ - if (err) { \ - fprintf(stderr, "loop @%d: ", i); \ - base16384_perror(err); \ - return 1; \ - } - -#define validate_result() \ - uint64_t buf, sum_input = 0, sum_validate = 0; \ - fp = fopen(TEST_INPUT_FILENAME, "rb"); { \ - loop_ok(!fp, i, "fopen"); \ - while (fread(&buf, sizeof(sum_input), 1, fp) > 0) sum_input += buf; \ - buf = 0; \ - while (fread(&buf, 1, 1, fp) > 0) { \ - sum_input += buf; \ - sum_input = LEFTROTATE(sum_input, 4); \ - } \ - } fclose(fp); \ - fp = fopen(TEST_VALIDATE_FILENAME, "rb"); { \ - loop_ok(!fp, i, "fopen"); \ - while (fread(&buf, sizeof(sum_validate), 1, fp) > 0) sum_validate += buf; \ - buf = 0; \ - while (fread(&buf, 1, 1, fp) > 0) { \ - sum_validate += buf; \ - sum_validate = LEFTROTATE(sum_validate, 4); \ - } \ - } fclose(fp); \ - if (sum_input != sum_validate) { \ - fprintf(stderr, "loop @%d, expect: %016llx, got: %016llx: ", i, (unsigned long long)sum_input, (unsigned long long)sum_validate); \ - fputs(TEST_INPUT_FILENAME " and " TEST_VALIDATE_FILENAME " mismatch.", stderr); \ - return 1; \ - } - #define init_input_file() \ for(i = 0; i < TEST_SIZE; i += sizeof(int)) { \ *(int*)(&encbuf[i]) = rand(); \ diff --git a/test/file_test.h b/test/file_test.h new file mode 100644 index 0000000..fd97f4d --- /dev/null +++ b/test/file_test.h @@ -0,0 +1,85 @@ +#ifndef _FILE_TEST_H_ +#define _FILE_TEST_H_ + +/* test/file_test.h + * This file is part of the base16384 distribution (https://github.com/fumiama/base16384). + * Copyright (c) 2022-2024 Fumiama Minamoto. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#define ok(has_failed, reason) \ + if (has_failed) { \ + perror(reason); \ + return 1; \ + } + +#define loop_ok(has_failed, i, reason) \ + if (has_failed) { \ + fprintf(stderr, "loop @%d: ", i); \ + perror(reason); \ + return 1; \ + } + +#define reset_and_truncate(fd, i) { \ + fd = open(TEST_INPUT_FILENAME, O_RDWR); \ + ok(!fd, "open"); \ + loop_ok(lseek(fd, 0, SEEK_SET), i, "lseek"); \ + loop_ok(ftruncate(fd, i), i, "ftruncate"); \ +} + +#define base16384_loop_ok(err) \ + if (err) { \ + fprintf(stderr, "loop @%d: ", i); \ + base16384_perror(err); \ + return 1; \ + } + +#define validate_result() \ + uint64_t buf, sum_input = 0, sum_validate = 0; \ + fp = fopen(TEST_INPUT_FILENAME, "rb"); { \ + loop_ok(!fp, i, "fopen"); \ + int cnt; \ + while ((cnt = fread(&buf, 1, sizeof(sum_input), fp)) > 0) { \ + int n; \ + buf = 0; \ + while(cnt < sizeof(sum_input)) { \ + n = fread((uint8_t*)(&buf)+cnt, 1, 1, fp); \ + if (n) cnt++; \ + else break; \ + } \ + sum_input += buf; \ + } \ + } fclose(fp); \ + fp = fopen(TEST_VALIDATE_FILENAME, "rb"); { \ + loop_ok(!fp, i, "fopen"); \ + int cnt; \ + while ((cnt = fread(&buf, 1, sizeof(sum_validate), fp)) > 0) { \ + int n; \ + buf = 0; \ + while(cnt < sizeof(sum_validate)) { \ + n = fread((uint8_t*)(&buf)+cnt, 1, 1, fp); \ + if (n) cnt++; \ + else break; \ + } \ + sum_validate += buf; \ + } \ + } fclose(fp); \ + if (sum_input != sum_validate) { \ + fprintf(stderr, "loop @%d, expect: %016llx, got: %016llx: ", i, (unsigned long long)sum_input, (unsigned long long)sum_validate); \ + fputs(TEST_INPUT_FILENAME " and " TEST_VALIDATE_FILENAME " mismatch.", stderr); \ + return 1; \ + } + +#endif \ No newline at end of file diff --git a/test/wrap_test.c b/test/wrap_test.c index 4bc5358..095c40d 100644 --- a/test/wrap_test.c +++ b/test/wrap_test.c @@ -1,3 +1,20 @@ +/* test/wrap_test.c + * This file is part of the base16384 distribution (https://github.com/fumiama/base16384). + * Copyright (c) 2022-2024 Fumiama Minamoto. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #ifdef _WIN32 #include @@ -15,6 +32,7 @@ #include "base16384.h" #include "binary.h" +#include "file_test.h" #define TEST_SIZE (4096) #define TEST_INPUT_FILENAME "wrap_test_input.bin" @@ -25,59 +43,6 @@ char encbuf[BASE16384_ENCBUFSZ]; char decbuf[BASE16384_DECBUFSZ]; char tstbuf[BASE16384_ENCBUFSZ]; -#define ok(has_failed, reason) \ - if (has_failed) { \ - perror(reason); \ - return 1; \ - } - -#define loop_ok(has_failed, i, reason) \ - if (has_failed) { \ - fprintf(stderr, "loop @%d: ", i); \ - perror(reason); \ - return 1; \ - } - -#define reset_and_truncate(fd, i) { \ - fd = open(TEST_INPUT_FILENAME, O_RDWR); \ - ok(!fd, "open"); \ - loop_ok(lseek(fd, 0, SEEK_SET), i, "lseek"); \ - loop_ok(ftruncate(fd, i), i, "ftruncate"); \ -} - -#define base16384_loop_ok(err) \ - if (err) { \ - fprintf(stderr, "loop @%d: ", i); \ - base16384_perror(err); \ - return 1; \ - } - -#define validate_result() \ - uint64_t buf, sum_input = 0, sum_validate = 0; \ - fp = fopen(TEST_INPUT_FILENAME, "rb"); { \ - loop_ok(!fp, i, "fopen"); \ - while (fread(&buf, sizeof(sum_input), 1, fp) > 0) sum_input += buf; \ - buf = 0; \ - while (fread(&buf, 1, 1, fp) > 0) { \ - sum_input += buf; \ - sum_input = LEFTROTATE(sum_input, 4); \ - } \ - } fclose(fp); \ - fp = fopen(TEST_VALIDATE_FILENAME, "rb"); { \ - loop_ok(!fp, i, "fopen"); \ - while (fread(&buf, sizeof(sum_validate), 1, fp) > 0) sum_validate += buf; \ - buf = 0; \ - while (fread(&buf, 1, 1, fp) > 0) { \ - sum_validate += buf; \ - sum_validate = LEFTROTATE(sum_validate, 4); \ - } \ - } fclose(fp); \ - if (sum_input != sum_validate) { \ - fprintf(stderr, "loop @%d, expect: %016llx, got: %016llx: ", i, (unsigned long long)sum_input, (unsigned long long)sum_validate); \ - fputs(TEST_INPUT_FILENAME " and " TEST_VALIDATE_FILENAME " mismatch.", stderr); \ - return 1; \ - } - #define init_input_file() \ for(i = 0; i < TEST_SIZE; i += sizeof(int)) { \ *(int*)(&encbuf[i]) = rand(); \ From e5f8c0fc463a31b67f4f6c675cbff6a330825c3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Fri, 5 Apr 2024 14:00:35 +0900 Subject: [PATCH 27/35] fix(file): check sum --- base1464.c | 33 --------------------- binary.h | 55 ++++++++++------------------------ file.c | 86 +++++++++++++++++++++++++++++++++--------------------- 3 files changed, 68 insertions(+), 106 deletions(-) diff --git a/base1464.c b/base1464.c index 23d3f69..1fbe6e4 100644 --- a/base1464.c +++ b/base1464.c @@ -39,9 +39,6 @@ int base16384_encode_safe(const char* data, int dlen, char* buf) { case 6: outlen += 10; break; default: break; } - #ifdef DEBUG - printf("outlen: %llu, offset: %u, malloc: %llu\n", outlen, offset, outlen + 8); - #endif uint64_t* vals = (uint64_t*)buf; uint64_t n = 0; int64_t i = 0; @@ -57,9 +54,6 @@ int base16384_encode_safe(const char* data, int dlen, char* buf) { sum |= shift & 0x0000000000003fff; sum += 0x4e004e004e004e00; vals[n++] = be64toh(sum); - #ifdef DEBUG - printf("i: %llu, add sum: %016llx\n", i, sum); - #endif } remainder valbuf; if(dlen - i == 7) { @@ -108,9 +102,6 @@ int base16384_encode_safe(const char* data, int dlen, char* buf) { valbuf.val = sum; #endif memcpy(&vals[n], valbuf.buf, outlen-2-(int)n*(int)sizeof(uint64_t)); - #ifdef DEBUG - printf("i: %llu, add sum: %016llx\n", i, sum); - #endif buf[outlen - 2] = '='; buf[outlen - 1] = offset; } @@ -130,9 +121,6 @@ int base16384_encode(const char* data, int dlen, char* buf) { case 6: outlen += 10; break; default: break; } - #ifdef DEBUG - printf("outlen: %llu, offset: %u, malloc: %llu\n", outlen, offset, outlen + 8); - #endif uint64_t* vals = (uint64_t*)buf; uint64_t n = 0; int64_t i = 0; @@ -148,9 +136,6 @@ int base16384_encode(const char* data, int dlen, char* buf) { sum |= shift & 0x0000000000003fff; sum += 0x4e004e004e004e00; vals[n++] = be64toh(sum); - #ifdef DEBUG - printf("i: %llu, add sum: %016llx\n", i, sum); - #endif } int o = offset; if(o--) { @@ -182,9 +167,6 @@ int base16384_encode(const char* data, int dlen, char* buf) { #else vals[n] = sum; #endif - #ifdef DEBUG - printf("i: %llu, add sum: %016llx\n", i, sum); - #endif buf[outlen - 2] = '='; buf[outlen - 1] = offset; } @@ -204,9 +186,6 @@ int base16384_encode_unsafe(const char* data, int dlen, char* buf) { case 6: outlen += 10; break; default: break; } - #ifdef DEBUG - printf("outlen: %llu, offset: %u, malloc: %llu\n", outlen, offset, outlen + 8); - #endif uint64_t* vals = (uint64_t*)buf; uint64_t n = 0; int64_t i = 0; @@ -222,9 +201,6 @@ int base16384_encode_unsafe(const char* data, int dlen, char* buf) { sum |= shift & 0x0000000000003fff; sum += 0x4e004e004e004e00; vals[n++] = be64toh(sum); - #ifdef DEBUG - printf("i: %llu, add sum: %016llx\n", i, sum); - #endif } if(offset) { buf[outlen - 2] = '='; @@ -265,9 +241,6 @@ int base16384_decode_safe(const char* data, int dlen, char* buf) { shift <<= 2; sum |= shift & 0x00000000003fff00; *(uint64_t*)(buf+i) = be64toh(sum); - #ifdef DEBUG - printf("i: %llu, add sum: %016llx\n", i, sum); - #endif } remainder valbuf; if(outlen - i == 7) { @@ -345,9 +318,6 @@ int base16384_decode(const char* data, int dlen, char* buf) { shift <<= 2; sum |= shift & 0x00000000003fff00; *(uint64_t*)(buf+i) = be64toh(sum); - #ifdef DEBUG - printf("i: %llu, add sum: %016llx\n", i, sum); - #endif } if(offset--) { // 这里有读取越界 @@ -411,9 +381,6 @@ int base16384_decode_unsafe(const char* data, int dlen, char* buf) { shift <<= 2; sum |= shift & 0x00000000003fff00; *(uint64_t*)(buf+i) = be64toh(sum); - #ifdef DEBUG - printf("i: %llu, add sum: %016llx\n", i, sum); - #endif } register uint64_t sum = 0; register uint64_t shift = htobe64(vals[n]); diff --git a/binary.h b/binary.h index 1feaef5..43b48ca 100644 --- a/binary.h +++ b/binary.h @@ -87,33 +87,15 @@ // leftrotate function definition #define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (sizeof(x)*8 - (c)))) -static inline uint32_t calc_sum(uint32_t sum, size_t cnt, char* encbuf) { - uint32_t i; - #ifdef DEBUG - fprintf(stderr, "cnt: %zu, roundin: %08x, ", cnt, sum); - #endif - for(i = 0; i < cnt/sizeof(sum); i++) { - #ifdef DEBUG - if (!i) { - fprintf(stderr, "firstval: %08x, ", htobe32(((uint32_t*)encbuf)[i])); - } - #endif - sum += ~LEFTROTATE(htobe32(((uint32_t*)encbuf)[i]), encbuf[i*sizeof(sum)]%(8*sizeof(sum))); +static inline uint32_t calc_sum(uint32_t sum, size_t cnt, const char* encbuf) { + size_t i; + uint32_t buf; + for(i = 0; i < cnt; i++) { + buf = (uint32_t)(encbuf[i])&0xff; + buf = ((buf<<(24-6))&0x03000000) | ((buf<<(16-4))&0x00030000) | ((buf<<(8-2))&0x00000300) | (buf&0x03); + sum += buf; + sum = ~LEFTROTATE(sum, 3); } - #ifdef DEBUG - fprintf(stderr, "roundmid: %08x", sum); - #endif - size_t rem = cnt % sizeof(sum); - if(rem) { - uint32_t x = htobe32(((uint32_t*)encbuf)[i]) & (0xffffffff << (8*(sizeof(sum)-rem))); - sum += ~LEFTROTATE(x, encbuf[i*sizeof(sum)]%(8*sizeof(sum))); - #ifdef DEBUG - fprintf(stderr, ", roundrem:%08x\n", sum); - #endif - } - #ifdef DEBUG - else fprintf(stderr, "\n"); - #endif return sum; } @@ -125,19 +107,14 @@ static inline uint32_t calc_and_embed_sum(uint32_t sum, size_t cnt, char* encbuf return sum; } -static inline int calc_and_check_sum(uint32_t* s, size_t cnt, char* encbuf) { - uint32_t sum = calc_sum(*s, cnt, encbuf); - if(cnt%7) { // is last decode block - int shift = (int[]){0, 26, 20, 28, 22, 30, 24}[cnt%7]; - uint32_t sum_read = be32toh((*(uint32_t*)(&encbuf[cnt]))) >> shift; - sum >>= shift; - #ifdef DEBUG - fprintf(stderr, "cntrm: %lu, mysum: %08x, sumrd: %08x\n", cnt%7, sum, sum_read); - #endif - return sum != sum_read; - } - *s = sum; - return 0; +static inline int check_sum(uint32_t sum, uint32_t sum_read_raw, int offset) { + int shift = (int[]){0, 26, 20, 28, 22, 30, 24}[offset%7]; + uint32_t sum_read = be32toh(sum_read_raw) >> shift; + sum >>= shift; + #ifdef DEBUG + fprintf(stderr, "offset: %d, mysum: %08x, sumrd: %08x\n", offset, sum, sum_read); + #endif + return sum != sum_read; } #endif diff --git a/file.c b/file.c index 87e6a5e..e950305 100644 --- a/file.c +++ b/file.c @@ -56,9 +56,7 @@ static inline off_t get_file_size(const char* filepath) { base16384_err_t base16384_encode_file_detailed(const char* input, const char* output, char* encbuf, char* decbuf, int flag) { off_t inputsize; - FILE* fp = NULL; - FILE* fpo; - uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE; + FILE *fp = NULL, *fpo; int errnobak = 0, is_stdin = is_standard_io(input); base16384_err_t retval = base16384_err_ok; if(!input || !output || strlen(input) <= 0 || strlen(output) <= 0) { @@ -91,11 +89,8 @@ base16384_err_t base16384_encode_file_detailed(const char* input, const char* ou fputc(0xFE, fpo); fputc(0xFF, fpo); } - #ifdef DEBUG - inputsize = 917504; - fprintf(stderr, "inputsize: %lld\n", inputsize); - #endif size_t cnt; + uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE; while((cnt = fread(encbuf, sizeof(char), inputsize, fp)) > 0) { int n; while(cnt%7) { @@ -252,10 +247,8 @@ base16384_err_t base16384_decode_file_detailed(const char* input, const char* ou if(errno) { goto_base16384_file_detailed_cleanup(decode, base16384_err_read_file, {}); } - #ifdef DEBUG - fprintf(stderr, "inputsize: %lld\n", inputsize); - #endif - int cnt; + int cnt, last_encbuf_cnt = 0, last_decbuf_cnt = 0, offset = 0; + size_t total_decoded_len = 0; while((cnt = fread(decbuf, sizeof(char), inputsize, fp)) > 0) { int n; while(cnt%8) { @@ -269,16 +262,23 @@ base16384_err_t base16384_decode_file_detailed(const char* input, const char* ou decbuf[cnt++] = end; } if(errno) goto_base16384_file_detailed_cleanup(decode, base16384_err_read_file, {}); + offset = decbuf[cnt-1]; + last_decbuf_cnt = cnt; cnt = base16384_decode_unsafe(decbuf, cnt, encbuf); if(cnt && fwrite(encbuf, cnt, 1, fpo) <= 0) { goto_base16384_file_detailed_cleanup(decode, base16384_err_write_file, {}); } - if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) { - if(calc_and_check_sum(&sum, cnt, encbuf)) { - errno = EINVAL; - goto_base16384_file_detailed_cleanup(decode, base16384_err_invalid_decoding_checksum, {}); - } - } + total_decoded_len += cnt; + if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) sum = calc_sum(sum, cnt, encbuf); + last_encbuf_cnt = cnt; + } + if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN + && total_decoded_len >= _BASE16384_ENCBUFSZ + && last_decbuf_cnt > 2 + && decbuf[last_decbuf_cnt-2] == '=' + && check_sum(sum, *(uint32_t*)(&encbuf[last_encbuf_cnt]), offset)) { + errno = EINVAL; + goto_base16384_file_detailed_cleanup(decode, base16384_err_invalid_decoding_checksum, {}); } #if !defined _WIN32 && !defined __cosmopolitan } else { // small file, use mmap & fwrite @@ -324,7 +324,8 @@ base16384_err_t base16384_decode_fp_detailed(FILE* input, FILE* output, char* en if(errno) { return base16384_err_read_file; } - int cnt; + int cnt, last_encbuf_cnt = 0, last_decbuf_cnt = 0, offset = 0; + size_t total_decoded_len = 0; while((cnt = fread(decbuf, sizeof(char), inputsize, input)) > 0) { int n; while(cnt%8) { @@ -338,16 +339,23 @@ base16384_err_t base16384_decode_fp_detailed(FILE* input, FILE* output, char* en decbuf[cnt++] = end; } if(errno) return base16384_err_read_file; + offset = decbuf[cnt-1]; + last_decbuf_cnt = cnt; cnt = base16384_decode_unsafe(decbuf, cnt, encbuf); if(cnt && fwrite(encbuf, cnt, 1, output) <= 0) { return base16384_err_write_file; } - if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) { - if (calc_and_check_sum(&sum, cnt, encbuf)) { - errno = EINVAL; - return base16384_err_invalid_decoding_checksum; - } - } + total_decoded_len += cnt; + if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) sum = calc_sum(sum, cnt, encbuf); + last_encbuf_cnt = cnt; + } + if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN + && total_decoded_len >= _BASE16384_ENCBUFSZ + && last_decbuf_cnt > 2 + && decbuf[last_decbuf_cnt-2] == '=' + && check_sum(sum, *(uint32_t*)(&encbuf[last_encbuf_cnt]), offset)) { + errno = EINVAL; + return base16384_err_invalid_decoding_checksum; } return base16384_err_ok; } @@ -373,15 +381,21 @@ base16384_err_t base16384_decode_fd_detailed(int input, int output, char* encbuf errno = EINVAL; return base16384_err_fopen_output_file; } + off_t inputsize = _BASE16384_DECBUFSZ; - int p = 0, n; uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE; uint8_t remains[8]; + decbuf[0] = 0; if(read(input, remains, 2) != 2) { return base16384_err_read_file; } + + int p = 0; if(remains[0] != (uint8_t)(0xfe)) p = 2; + + int n, last_encbuf_cnt = 0, last_decbuf_cnt = 0, offset = 0; + size_t total_decoded_len = 0; while((n = read(input, decbuf+p, inputsize-p)) > 0) { if(p) { memcpy(decbuf, remains, p); @@ -404,19 +418,23 @@ base16384_err_t base16384_decode_fd_detailed(int input, int output, char* encbuf decbuf[n++] = (char)(next&0x00ff); } else remains[p++] = (char)(next&0x00ff); } - #ifdef DEBUG - fprintf(stderr, "decode chunk: %d, last2: %c %02x\n", cnt, decbuf[cnt-2], (uint8_t)decbuf[cnt-1]); - #endif + offset = decbuf[n-1]; + last_decbuf_cnt = n; n = base16384_decode_unsafe(decbuf, n, encbuf); if(n && write(output, encbuf, n) != n) { return base16384_err_write_file; } - if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) { - if (calc_and_check_sum(&sum, n, encbuf)) { - errno = EINVAL; - return base16384_err_invalid_decoding_checksum; - } - } + total_decoded_len += n; + if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) sum = calc_sum(sum, n, encbuf); + last_encbuf_cnt = n; + } + if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN + && total_decoded_len >= _BASE16384_ENCBUFSZ + && last_decbuf_cnt > 2 + && decbuf[last_decbuf_cnt-2] == '=' + && check_sum(sum, *(uint32_t*)(&encbuf[last_encbuf_cnt]), offset)) { + errno = EINVAL; + return base16384_err_invalid_decoding_checksum; } return base16384_err_ok; } From cd15e63c86e8a17bdc6482c36dfde55d838706fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Fri, 5 Apr 2024 14:30:05 +0900 Subject: [PATCH 28/35] feat(checksum): add flag BASE16384_FLAG_DO_SUM_CHECK_FORCELY --- CMakeLists.txt | 2 +- base16384.1 | 21 ++++++++++++++++----- base16384.c | 8 +++++++- base16384.h | 2 ++ file.c | 8 ++++---- test/file_test.c | 22 +++++++++++++++------- test/wrap_test.c | 3 --- 7 files changed, 45 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ca4b762..9eec095 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ endif (POLICY CMP0048) project(base16384 VERSION 2.3.0) add_definitions(-DBASE16384_VERSION="${PROJECT_VERSION}") -add_definitions(-DBASE16384_VERSION_DATE="April 4th 2024") +add_definitions(-DBASE16384_VERSION_DATE="April 5th 2024") message(STATUS "Testing endian...") include(TestBigEndian) diff --git a/base16384.1 b/base16384.1 index 47c869a..d5dd9a5 100644 --- a/base16384.1 +++ b/base16384.1 @@ -1,4 +1,4 @@ -.TH BASE16384 1 "4 April 2024" "GNU" "User Commands" +.TH BASE16384 1 "5 April 2024" "GNU" "User Commands" .SH NAME base16384 \- Encode binary files to printable utf16be .SH SYNOPSIS @@ -40,16 +40,27 @@ Read data from \fIinputfile\fR and decode them into \fIoutputfile\fR. Show spend time. .TP 0.5i \fB\-n\fR -Do not write utf16be file header (0xFEFF) to the output. +Do not write utf16be file header +.B 0xFEFF +to the output. .TP 0.5i \fB\-c\fR -Embed or validate checksum in remainder when using stdin/stdout or inputsize > _BASE16384_ENCBUFSZ. +Embed or validate checksum in remainder when using \fIstdin\fR or \fIstdout\fR or inputsize > _BASE16384_ENCBUFSZ. +.TP 0.5i +\fB\-C\fR +Do +.B -c +forcely. .TP 0.5i \fBinputfile\fR -An absolute or relative file path. Specially, pass - to read from stdin. +An absolute or relative file path. Specially, pass +.B - +to read from \fIstdin\fR. .TP 0.5i \fBoutputfile\fR -An absolute or relative file path. Specially, pass - to write to stdout. +An absolute or relative file path. Specially, pass +.B - +to write to \fIstdout\fR. .SH "EXIT STATUS" .TP 0.5i \fB0\fR diff --git a/base16384.c b/base16384.c index f860f40..eb9102e 100644 --- a/base16384.c +++ b/base16384.c @@ -52,6 +52,7 @@ static base16384_err_t print_usage() { fputs(" -t\t\tshow spend time\n", stderr); fputs(" -n\t\tdon't write utf16be file header (0xFEFF)\n", stderr); fputs(" -c\t\tembed or validate checksum in remainder\n", stderr); + fputs(" -C\t\tdo -c forcely\n", stderr); fputs(" inputfile\tpass - to read from stdin\n", stderr); fputs(" outputfile\tpass - to write to stdout\n", stderr); return base16384_err_invalid_commandline_parameter; @@ -91,6 +92,9 @@ int main(int argc, char** argv) { case 'c': if(set_or_test_flag(use_checksum, 1)) return print_usage(); break; + case 'C': + if(set_or_test_flag(use_checksum, 2)) return print_usage(); + break; default: return print_usage(); break; @@ -111,7 +115,9 @@ int main(int argc, char** argv) { #define do_coding(method) base16384_##method##_file_detailed( \ argv[2], argv[3], encbuf, decbuf, \ - (no_header?BASE16384_FLAG_NOHEADER:0) | (use_checksum?BASE16384_FLAG_SUM_CHECK_ON_REMAIN:0) \ + (no_header?BASE16384_FLAG_NOHEADER:0) \ + | ((use_checksum&1)?BASE16384_FLAG_SUM_CHECK_ON_REMAIN:0) \ + | ((use_checksum&2)?BASE16384_FLAG_DO_SUM_CHECK_FORCELY:0) \ ) exitstat = is_encode?do_coding(encode):do_coding(decode); #undef do_coding diff --git a/base16384.h b/base16384.h index 9a8e6fc..2e1a34c 100644 --- a/base16384.h +++ b/base16384.h @@ -56,6 +56,8 @@ typedef enum base16384_err_t base16384_err_t; #define BASE16384_FLAG_NOHEADER (1<<0) // enable sum check when using stdin or inputsize > _BASE16384_ENCBUFSZ #define BASE16384_FLAG_SUM_CHECK_ON_REMAIN (1<<1) +// forcely do sumcheck without checking decoded data length +#define BASE16384_FLAG_DO_SUM_CHECK_FORCELY (1<<2) // initial sum value used in BASE16384_FLAG_SUM_CHECK_ON_REMAIN #define BASE16384_SIMPLE_SUM_INIT_VALUE (0x8e29c213) diff --git a/file.c b/file.c index e950305..b73601e 100644 --- a/file.c +++ b/file.c @@ -75,7 +75,7 @@ base16384_err_t base16384_encode_file_detailed(const char* input, const char* ou if(!fpo) { return base16384_err_fopen_output_file; } - if(inputsize >= _BASE16384_ENCBUFSZ) { // stdin or big file, use encbuf & fread + if(flag&BASE16384_FLAG_DO_SUM_CHECK_FORCELY || inputsize >= _BASE16384_ENCBUFSZ) { // stdin or big file, use encbuf & fread inputsize = _BASE16384_ENCBUFSZ; #if defined _WIN32 || defined __cosmopolitan } @@ -273,7 +273,7 @@ base16384_err_t base16384_decode_file_detailed(const char* input, const char* ou last_encbuf_cnt = cnt; } if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN - && total_decoded_len >= _BASE16384_ENCBUFSZ + && (flag&BASE16384_FLAG_DO_SUM_CHECK_FORCELY || total_decoded_len >= _BASE16384_ENCBUFSZ) && last_decbuf_cnt > 2 && decbuf[last_decbuf_cnt-2] == '=' && check_sum(sum, *(uint32_t*)(&encbuf[last_encbuf_cnt]), offset)) { @@ -350,7 +350,7 @@ base16384_err_t base16384_decode_fp_detailed(FILE* input, FILE* output, char* en last_encbuf_cnt = cnt; } if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN - && total_decoded_len >= _BASE16384_ENCBUFSZ + && (flag&BASE16384_FLAG_DO_SUM_CHECK_FORCELY || total_decoded_len >= _BASE16384_ENCBUFSZ) && last_decbuf_cnt > 2 && decbuf[last_decbuf_cnt-2] == '=' && check_sum(sum, *(uint32_t*)(&encbuf[last_encbuf_cnt]), offset)) { @@ -429,7 +429,7 @@ base16384_err_t base16384_decode_fd_detailed(int input, int output, char* encbuf last_encbuf_cnt = n; } if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN - && total_decoded_len >= _BASE16384_ENCBUFSZ + && (flag&BASE16384_FLAG_DO_SUM_CHECK_FORCELY || total_decoded_len >= _BASE16384_ENCBUFSZ) && last_decbuf_cnt > 2 && decbuf[last_decbuf_cnt-2] == '=' && check_sum(sum, *(uint32_t*)(&encbuf[last_encbuf_cnt]), offset)) { diff --git a/test/file_test.c b/test/file_test.c index 9382a81..b5ed8ed 100644 --- a/test/file_test.c +++ b/test/file_test.c @@ -130,13 +130,23 @@ char tstbuf[BASE16384_ENCBUFSZ]; #define test_detailed(name) \ test_##name##_detailed(0); \ - fputs("one test passed.\n", stderr); \ +\ test_##name##_detailed(BASE16384_FLAG_NOHEADER); \ - fputs("one test passed.\n", stderr); \ test_##name##_detailed(BASE16384_FLAG_SUM_CHECK_ON_REMAIN); \ - fputs("one test passed.\n", stderr); \ + test_##name##_detailed(BASE16384_FLAG_DO_SUM_CHECK_FORCELY); \ +\ test_##name##_detailed(BASE16384_FLAG_NOHEADER|BASE16384_FLAG_SUM_CHECK_ON_REMAIN); \ - fputs("one test passed.\n", stderr); + test_##name##_detailed(BASE16384_FLAG_NOHEADER|BASE16384_FLAG_DO_SUM_CHECK_FORCELY); \ +\ + test_##name##_detailed(BASE16384_FLAG_SUM_CHECK_ON_REMAIN|BASE16384_FLAG_DO_SUM_CHECK_FORCELY); \ +\ + test_##name##_detailed(BASE16384_FLAG_NOHEADER|BASE16384_FLAG_SUM_CHECK_ON_REMAIN|BASE16384_FLAG_DO_SUM_CHECK_FORCELY); + + +#define remove_test_files() \ + remove(TEST_INPUT_FILENAME); \ + remove(TEST_OUTPUT_FILENAME); \ + remove(TEST_VALIDATE_FILENAME); int main() { srand(time(NULL)); @@ -149,9 +159,7 @@ int main() { test_detailed(fp); test_detailed(fd); - remove(TEST_INPUT_FILENAME); - remove(TEST_OUTPUT_FILENAME); - remove(TEST_VALIDATE_FILENAME); + remove_test_files(); return 0; } diff --git a/test/wrap_test.c b/test/wrap_test.c index 095c40d..4d5df88 100644 --- a/test/wrap_test.c +++ b/test/wrap_test.c @@ -74,7 +74,6 @@ int main() { validate_result(); } - fputs("one test passed.\n", stderr); fputs("testing base16384_en/decode_fp...\n", stderr); init_input_file(); @@ -106,7 +105,6 @@ int main() { validate_result(); } - fputs("one test passed.\n", stderr); fputs("testing base16384_en/decode_fd...\n", stderr); init_input_file(); @@ -133,7 +131,6 @@ int main() { validate_result(); } - fputs("one test passed.\n", stderr); remove(TEST_INPUT_FILENAME); remove(TEST_OUTPUT_FILENAME); From 29e4019ed15fc6c05cac1596ca0a41240230b49e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Fri, 5 Apr 2024 16:27:21 +0900 Subject: [PATCH 29/35] fix(coder): incorrect hidden bits decoding in 32bit lib --- base1432.c | 18 +++++++++++++----- base1464.c | 10 ++++++---- base16384.h | 6 ++---- binary.h | 36 ++++++++++++++++++++---------------- file.c | 38 +++++++++++++++++++++++++++++--------- 5 files changed, 70 insertions(+), 38 deletions(-) diff --git a/base1432.c b/base1432.c index e991d2a..eb97e9d 100644 --- a/base1432.c +++ b/base1432.c @@ -255,7 +255,7 @@ int base16384_decode_safe(const char* data, int dlen, char* buf) { } } outlen = outlen / 8 * 7 + offset; - uint32_t* vals = (uint32_t*)data; + const uint32_t* vals = (const uint32_t*)data; uint32_t n = 0; int32_t i = 0; for(; i < outlen - 7; i+=7) { // n实际每次自增2 @@ -293,7 +293,7 @@ int base16384_decode_safe(const char* data, int dlen, char* buf) { sum |= shift & 0x003fff00; valbuf.val = be32toh(sum); memcpy(buf+i+4, valbuf.buf, 3); - } else if(offset--) { + } else if((*(uint8_t*)(&vals[n]) != '=') && offset--) { int cnt = dlen-2-(int)n*(int)sizeof(uint32_t); if (cnt > 4) cnt = 4; memcpy(valbuf.buf, &vals[n], cnt); @@ -312,6 +312,7 @@ int base16384_decode_safe(const char* data, int dlen, char* buf) { buf[i++] = ((sum & 0x000f0000) >> 12) | ((sum & 0xf0000000) >> 28); if(offset--) { buf[i] = (sum & 0x0f000000) >> 20; + if(*(uint8_t*)(&vals[n]) == '=') return outlen; memcpy(valbuf.buf, &vals[n], dlen-2-(int)n*(int)sizeof(uint32_t)); #ifdef WORDS_BIGENDIAN sum = __builtin_bswap32(valbuf.val); @@ -351,7 +352,7 @@ int base16384_decode(const char* data, int dlen, char* buf) { } } outlen = outlen / 8 * 7 + offset; - uint32_t* vals = (uint32_t*)data; + const uint32_t* vals = (const uint32_t*)data; uint32_t n = 0; int32_t i = 0; for(; i <= outlen - 7; i+=7) { // n实际每次自增2 @@ -371,6 +372,7 @@ int base16384_decode(const char* data, int dlen, char* buf) { sum |= shift & 0x003fff00; *(uint32_t*)(buf+i+4) = be32toh(sum); } + if(*(uint8_t*)(&vals[n]) == '=') return outlen; if(offset--) { // 这里有读取越界 #ifdef WORDS_BIGENDIAN @@ -387,6 +389,7 @@ int base16384_decode(const char* data, int dlen, char* buf) { buf[i++] = ((sum & 0x000f0000) >> 12) | ((sum & 0xf0000000) >> 28); if(offset--) { buf[i] = (sum & 0x0f000000) >> 20; + if(*(uint8_t*)(&vals[n]) == '=') return outlen; // 这里有读取越界 #ifdef WORDS_BIGENDIAN sum = __builtin_bswap32(vals[n]); @@ -426,7 +429,7 @@ int base16384_decode_unsafe(const char* data, int dlen, char* buf) { } } outlen = outlen / 8 * 7 + offset; - uint32_t* vals = (uint32_t*)data; + const uint32_t* vals = (const uint32_t*)data; uint32_t n = 0; int32_t i = 0; for(; i < outlen-7; i+=7) { // n实际每次自增2 @@ -448,6 +451,7 @@ int base16384_decode_unsafe(const char* data, int dlen, char* buf) { } register uint32_t sum = 0; register uint32_t shift = htobe32(vals[n++]); + if(((shift>>24)&0xff) == 0x3d) return outlen; if(((shift>>24)&0xff) < 0x4e) shift |= 0xff000000; if(((shift>> 8)&0xff) < 0x4e) shift |= 0x0000ff00; shift -= 0x4e004e00; @@ -455,7 +459,11 @@ int base16384_decode_unsafe(const char* data, int dlen, char* buf) { sum |= shift & 0xfffc0000; shift <<= 2; sum |= shift & 0x0003fff0; - shift = htobe32(vals[n++]); + shift = htobe32(vals[n]); + if(((shift>>24)&0xff) == 0x3d) { + *(uint32_t*)(buf+i) = be32toh(sum); + return outlen; + } if(((shift>>24)&0xff) < 0x4e) shift |= 0xff000000; if(((shift>> 8)&0xff) < 0x4e) shift |= 0x0000ff00; shift -= 0x4e004e00; diff --git a/base1464.c b/base1464.c index 1fbe6e4..a754676 100644 --- a/base1464.c +++ b/base1464.c @@ -226,7 +226,7 @@ int base16384_decode_safe(const char* data, int dlen, char* buf) { } } outlen = outlen / 8 * 7 + offset; - uint64_t* vals = (uint64_t*)data; + const uint64_t* vals = (const uint64_t*)data; uint64_t n = 0; int64_t i = 0; for(; i < outlen - 7; n++, i+=7) { @@ -256,7 +256,7 @@ int base16384_decode_safe(const char* data, int dlen, char* buf) { sum |= shift & 0x00000000003fff00; valbuf.val = be64toh(sum); memcpy(buf+i, valbuf.buf, 7); - } else if(offset--) { + } else if((*(uint8_t*)(&vals[n]) != '=') && offset--) { memcpy(valbuf.buf, &vals[n], dlen-2-(int)n*(int)sizeof(uint64_t)); #ifdef WORDS_BIGENDIAN register uint64_t sum = __builtin_bswap64(valbuf.val) - 0x000000000000004e; @@ -303,7 +303,7 @@ int base16384_decode(const char* data, int dlen, char* buf) { } } outlen = outlen / 8 * 7 + offset; - uint64_t* vals = (uint64_t*)data; + const uint64_t* vals = (const uint64_t*)data; uint64_t n = 0; int64_t i = 0; for(; i <= outlen - 7; n++, i+=7) { @@ -319,6 +319,7 @@ int base16384_decode(const char* data, int dlen, char* buf) { sum |= shift & 0x00000000003fff00; *(uint64_t*)(buf+i) = be64toh(sum); } + if(*(uint8_t*)(&vals[n]) == '=') return outlen; if(offset--) { // 这里有读取越界 #ifdef WORDS_BIGENDIAN @@ -366,7 +367,7 @@ int base16384_decode_unsafe(const char* data, int dlen, char* buf) { } } outlen = outlen / 8 * 7 + offset; - uint64_t* vals = (uint64_t*)data; + const uint64_t* vals = (const uint64_t*)data; uint64_t n = 0; int64_t i = 0; for(; i < outlen-7; n++, i+=7) { @@ -384,6 +385,7 @@ int base16384_decode_unsafe(const char* data, int dlen, char* buf) { } register uint64_t sum = 0; register uint64_t shift = htobe64(vals[n]); + if(((shift>>56)&0xff) == 0x3d) return outlen; if(((shift>>56)&0xff) < 0x4e) shift |= 0xff00000000000000; if(((shift>>40)&0xff) < 0x4e) shift |= 0x0000ff0000000000; if(((shift>>24)&0xff) < 0x4e) shift |= 0x00000000ff000000; diff --git a/base16384.h b/base16384.h index 2e1a34c..fe93fd7 100644 --- a/base16384.h +++ b/base16384.h @@ -54,12 +54,10 @@ typedef enum base16384_err_t base16384_err_t; // disable 0xFEFF file header in encode #define BASE16384_FLAG_NOHEADER (1<<0) -// enable sum check when using stdin or inputsize > _BASE16384_ENCBUFSZ +// enable sum check when using stdin or stdout or inputsize > _BASE16384_ENCBUFSZ #define BASE16384_FLAG_SUM_CHECK_ON_REMAIN (1<<1) -// forcely do sumcheck without checking decoded data length +// forcely do sumcheck without checking data length #define BASE16384_FLAG_DO_SUM_CHECK_FORCELY (1<<2) -// initial sum value used in BASE16384_FLAG_SUM_CHECK_ON_REMAIN -#define BASE16384_SIMPLE_SUM_INIT_VALUE (0x8e29c213) /** * @brief calculate the exact encoded size diff --git a/binary.h b/binary.h index 43b48ca..0a5f996 100644 --- a/binary.h +++ b/binary.h @@ -70,15 +70,15 @@ #define htobe64(x) (x) #endif #else - #define be16toh(x) _byteswap_ushort(x) - #define be32toh(x) _byteswap_ulong(x) + #define be16toh(x) _bitswap_ushort(x) + #define be32toh(x) _bitswap_ulong(x) #ifdef IS_64BIT_PROCESSOR - #define be64toh(x) _byteswap_uint64(x) + #define be64toh(x) _bitswap_uint64(x) #endif - #define htobe16(x) _byteswap_ushort(x) - #define htobe32(x) _byteswap_ulong(x) + #define htobe16(x) _bitswap_ushort(x) + #define htobe32(x) _bitswap_ulong(x) #ifdef IS_64BIT_PROCESSOR - #define htobe64(x) _byteswap_uint64(x) + #define htobe64(x) _bitswap_uint64(x) #endif #endif #endif @@ -87,6 +87,9 @@ // leftrotate function definition #define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (sizeof(x)*8 - (c)))) +// initial sum value used in BASE16384_FLAG_SUM_CHECK_ON_REMAIN +#define BASE16384_SIMPLE_SUM_INIT_VALUE (0x8e29c213) + static inline uint32_t calc_sum(uint32_t sum, size_t cnt, const char* encbuf) { size_t i; uint32_t buf; @@ -99,20 +102,21 @@ static inline uint32_t calc_sum(uint32_t sum, size_t cnt, const char* encbuf) { return sum; } -static inline uint32_t calc_and_embed_sum(uint32_t sum, size_t cnt, char* encbuf) { - sum = calc_sum(sum, cnt, encbuf); - if(cnt%7) { // last encode - *(uint32_t*)(&encbuf[cnt]) = htobe32(sum); - } - return sum; -} - static inline int check_sum(uint32_t sum, uint32_t sum_read_raw, int offset) { - int shift = (int[]){0, 26, 20, 28, 22, 30, 24}[offset%7]; + offset = offset%7; + if(!offset--) return 0; // no remain bits, pass + // offset 1: 0011 1111 1100 0000 remain: 3*2 bits + // offset 2: 0011 1111 1111 1111 0011 0000 0000 0000 remain: 6*2 bits + // offset 3: 0011 1111 1111 0000 remain: 2*2 bits + // offset 4: 0011 1111 1111 1111 0011 1100 0000 0000 remain: 5*2 bits + // offset 5: 0011 1111 1111 1100 remain: 1*2 bits + // offset 6: 0011 1111 1111 1111 0011 1111 0000 0000 remain: 4*2 bits + // encode: 0415263 (6-1) per 3bits, thus 0x021ab3 + int shift = sizeof(uint32_t)*8 - ((0x021ab3>>(offset*3))&0x07)*2; uint32_t sum_read = be32toh(sum_read_raw) >> shift; sum >>= shift; #ifdef DEBUG - fprintf(stderr, "offset: %d, mysum: %08x, sumrd: %08x\n", offset, sum, sum_read); + fprintf(stderr, "shift: %d, offset: %d, mysum: %08x, sumrd: %08x\n", shift, offset+1, sum, sum_read); #endif return sum != sum_read; } diff --git a/file.c b/file.c index b73601e..36fb7aa 100644 --- a/file.c +++ b/file.c @@ -54,6 +54,8 @@ static inline off_t get_file_size(const char* filepath) { goto base16384_##method##_file_detailed_cleanup; \ } +#define do_sum_check(flag) ((flag)&(BASE16384_FLAG_DO_SUM_CHECK_FORCELY|BASE16384_FLAG_SUM_CHECK_ON_REMAIN)) + base16384_err_t base16384_encode_file_detailed(const char* input, const char* output, char* encbuf, char* decbuf, int flag) { off_t inputsize; FILE *fp = NULL, *fpo; @@ -98,7 +100,15 @@ base16384_err_t base16384_encode_file_detailed(const char* input, const char* ou if(n > 0) cnt++; else break; } - if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) sum = calc_and_embed_sum(sum, cnt, encbuf); + if(do_sum_check(flag)) { + sum = calc_sum(sum, cnt, encbuf); + if(cnt%7) { // last encode + *(uint32_t*)(&encbuf[cnt]) = htobe32(sum); + #ifdef DEBUG + fprintf(stderr, "writesum: %08x\n", sum); + #endif + } + } n = base16384_encode_unsafe(encbuf, cnt, decbuf); if(n && fwrite(decbuf, n, 1, fpo) <= 0) { goto_base16384_file_detailed_cleanup(encode, base16384_err_write_file, {}); @@ -157,7 +167,12 @@ base16384_err_t base16384_encode_fp_detailed(FILE* input, FILE* output, char* en if(n > 0) cnt++; else break; } - if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) sum = calc_and_embed_sum(sum, cnt, encbuf); + if(do_sum_check(flag)) { + sum = calc_sum(sum, cnt, encbuf); + if(cnt%7) { // last encode + *(uint32_t*)(&encbuf[cnt]) = htobe32(sum); + } + } n = base16384_encode_unsafe(encbuf, cnt, decbuf); if(n && fwrite(decbuf, n, 1, output) <= 0) { return base16384_err_write_file; @@ -184,7 +199,12 @@ base16384_err_t base16384_encode_fd_detailed(int input, int output, char* encbuf if(n > 0) cnt++; else break; } - if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) sum = calc_and_embed_sum(sum, cnt, encbuf); + if(do_sum_check(flag)) { + sum = calc_sum(sum, cnt, encbuf); + if(cnt%7) { // last encode + *(uint32_t*)(&encbuf[cnt]) = htobe32(sum); + } + } n = base16384_encode_unsafe(encbuf, cnt, decbuf); if(n && write(output, decbuf, n) < n) { return base16384_err_write_file; @@ -269,10 +289,10 @@ base16384_err_t base16384_decode_file_detailed(const char* input, const char* ou goto_base16384_file_detailed_cleanup(decode, base16384_err_write_file, {}); } total_decoded_len += cnt; - if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) sum = calc_sum(sum, cnt, encbuf); + if(do_sum_check(flag)) sum = calc_sum(sum, cnt, encbuf); last_encbuf_cnt = cnt; } - if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN + if(do_sum_check(flag) && (flag&BASE16384_FLAG_DO_SUM_CHECK_FORCELY || total_decoded_len >= _BASE16384_ENCBUFSZ) && last_decbuf_cnt > 2 && decbuf[last_decbuf_cnt-2] == '=' @@ -346,10 +366,10 @@ base16384_err_t base16384_decode_fp_detailed(FILE* input, FILE* output, char* en return base16384_err_write_file; } total_decoded_len += cnt; - if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) sum = calc_sum(sum, cnt, encbuf); + if(do_sum_check(flag)) sum = calc_sum(sum, cnt, encbuf); last_encbuf_cnt = cnt; } - if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN + if(do_sum_check(flag) && (flag&BASE16384_FLAG_DO_SUM_CHECK_FORCELY || total_decoded_len >= _BASE16384_ENCBUFSZ) && last_decbuf_cnt > 2 && decbuf[last_decbuf_cnt-2] == '=' @@ -425,10 +445,10 @@ base16384_err_t base16384_decode_fd_detailed(int input, int output, char* encbuf return base16384_err_write_file; } total_decoded_len += n; - if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN) sum = calc_sum(sum, n, encbuf); + if(do_sum_check(flag)) sum = calc_sum(sum, n, encbuf); last_encbuf_cnt = n; } - if(flag&BASE16384_FLAG_SUM_CHECK_ON_REMAIN + if(do_sum_check(flag) && (flag&BASE16384_FLAG_DO_SUM_CHECK_FORCELY || total_decoded_len >= _BASE16384_ENCBUFSZ) && last_decbuf_cnt > 2 && decbuf[last_decbuf_cnt-2] == '=' From b9e02241bdd38fafb885e7de3ebbee928b1b132c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Fri, 5 Apr 2024 16:05:30 +0800 Subject: [PATCH 30/35] fix(test): buffer overflow & adapt to windows --- binary.h | 14 +++++++------- test/file_test.c | 4 ++-- test/wrap_test.c | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/binary.h b/binary.h index 0a5f996..46c7039 100644 --- a/binary.h +++ b/binary.h @@ -57,7 +57,7 @@ #define htobe64(x) htonll(x) #endif #endif - #ifdef _MSC_VER + #ifdef _WIN32 #ifdef WORDS_BIGENDIAN #define be16toh(x) (x) #define be32toh(x) (x) @@ -70,15 +70,15 @@ #define htobe64(x) (x) #endif #else - #define be16toh(x) _bitswap_ushort(x) - #define be32toh(x) _bitswap_ulong(x) + #define be16toh(x) _byteswap_ushort(x) + #define be32toh(x) _byteswap_ulong(x) #ifdef IS_64BIT_PROCESSOR - #define be64toh(x) _bitswap_uint64(x) + #define be64toh(x) _byteswap_uint64(x) #endif - #define htobe16(x) _bitswap_ushort(x) - #define htobe32(x) _bitswap_ulong(x) + #define htobe16(x) _byteswap_ushort(x) + #define htobe32(x) _byteswap_ulong(x) #ifdef IS_64BIT_PROCESSOR - #define htobe64(x) _bitswap_uint64(x) + #define htobe64(x) _byteswap_uint64(x) #endif #endif #endif diff --git a/test/file_test.c b/test/file_test.c index b5ed8ed..0e69266 100644 --- a/test/file_test.c +++ b/test/file_test.c @@ -44,12 +44,12 @@ char decbuf[BASE16384_DECBUFSZ]; char tstbuf[BASE16384_ENCBUFSZ]; #define init_input_file() \ - for(i = 0; i < TEST_SIZE; i += sizeof(int)) { \ + for(i = 0; i < BASE16384_ENCBUFSZ; i += sizeof(int)) { \ *(int*)(&encbuf[i]) = rand(); \ } \ fp = fopen(TEST_INPUT_FILENAME, "wb"); \ ok(!fp, "fopen"); \ - ok(fwrite(encbuf, TEST_SIZE, 1, fp) != 1, "fwrite"); \ + ok(fwrite(encbuf, BASE16384_ENCBUFSZ, 1, fp) != 1, "fwrite"); \ ok(fclose(fp), "fclose"); \ fputs("input file created.\n", stderr); diff --git a/test/wrap_test.c b/test/wrap_test.c index 4d5df88..2e87067 100644 --- a/test/wrap_test.c +++ b/test/wrap_test.c @@ -44,12 +44,12 @@ char decbuf[BASE16384_DECBUFSZ]; char tstbuf[BASE16384_ENCBUFSZ]; #define init_input_file() \ - for(i = 0; i < TEST_SIZE; i += sizeof(int)) { \ + for(i = 0; i < BASE16384_ENCBUFSZ; i += sizeof(int)) { \ *(int*)(&encbuf[i]) = rand(); \ } \ fp = fopen(TEST_INPUT_FILENAME, "wb"); \ ok(!fp, "fopen"); \ - ok(fwrite(encbuf, TEST_SIZE, 1, fp) != 1, "fwrite"); \ + ok(fwrite(encbuf, BASE16384_ENCBUFSZ, 1, fp) != 1, "fwrite"); \ ok(fclose(fp), "fclose"); \ fputs("input file created.\n", stderr); From f3eaa1937ad84c722feddc2768a82f872f67ae18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Fri, 5 Apr 2024 17:17:54 +0900 Subject: [PATCH 31/35] fix(release): adapt to cosmopolitan --- .github/workflows/release.yml | 3 ++- base1432.c | 7 ++++--- base1464.c | 7 ++++--- base16384.c | 8 +++++++- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3a53864..978571d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,6 +14,7 @@ jobs: steps: - name: Checkout Code + id: checkout uses: actions/checkout@v2 - name: Setup Build Tools @@ -27,7 +28,7 @@ jobs: run: | gcc -g -Os -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone \ -fno-omit-frame-pointer -pg -mnop-mcount -D__cosmopolitan \ - -DBASE16384_VERSION="${{ github.ref }}" -DBASE16384_VERSION_DATE="`date +"%Y%b/%d"`"\ + -DBASE16384_VERSION=\"${{ steps.checkout.outputs.VERSION }}\" -DBASE16384_VERSION_DATE=\"`date +"%Y%b/%d"`\"\ -o base16384.com.dbg base16384.c file.c base1432.c -fuse-ld=bfd -Wl,-T,ape.lds \ -include cosmopolitan.h crt.o ape.o cosmopolitan.a objcopy -S -O binary base16384.com.dbg base16384.com diff --git a/base1432.c b/base1432.c index eb97e9d..4ce6019 100644 --- a/base1432.c +++ b/base1432.c @@ -16,15 +16,16 @@ * along with this program. If not, see . */ +#ifndef __cosmopolitan #include +#endif #include "binary.h" -union remainder { +typedef union { uint8_t buf[4]; uint32_t val; -}; -typedef union remainder remainder; +} remainder; int base16384_encode_safe(const char* data, int dlen, char* buf) { int outlen = dlen / 7 * 8; diff --git a/base1464.c b/base1464.c index a754676..0641f05 100644 --- a/base1464.c +++ b/base1464.c @@ -16,15 +16,16 @@ * along with this program. If not, see . */ +#ifndef __cosmopolitan #include +#endif #include "binary.h" -union remainder { +typedef union { uint8_t buf[8]; uint64_t val; -}; -typedef union remainder remainder; +} remainder; int base16384_encode_safe(const char* data, int dlen, char* buf) { int outlen = dlen / 7 * 8; diff --git a/base16384.c b/base16384.c index eb9102e..05756b2 100644 --- a/base16384.c +++ b/base16384.c @@ -45,7 +45,13 @@ static base16384_err_t print_usage() { #ifndef BASE16384_VERSION_DATE #define BASE16384_VERSION_DATE "unknown date" #endif - fputs("Copyright (c) 2022-2024 Fumiama Minamoto.\nBase16384 "BASE16384_VERSION" ("BASE16384_VERSION_DATE"). Usage:\n", stderr); + fputs( + "Copyright (c) 2022-2024 Fumiama Minamoto.\nBase16384 " + BASE16384_VERSION + " (" + BASE16384_VERSION_DATE + "). Usage:\n", stderr + ); fputs("base16384 [-edtn] [inputfile] [outputfile]\n", stderr); fputs(" -e\t\tencode (default)\n", stderr); fputs(" -d\t\tdecode\n", stderr); From a4d6d318ef2f11cfb3ec7da4759d22679ffb16b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Fri, 5 Apr 2024 17:24:15 +0900 Subject: [PATCH 32/35] fix(release): adapt to cosmopolitan --- .github/workflows/release.yml | 1 + base1432.c | 6 +++--- base1464.c | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 978571d..445402b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,6 +16,7 @@ jobs: - name: Checkout Code id: checkout uses: actions/checkout@v2 + run: echo ::set-output name=VERSION::$( git describe --tags --abbrev=0 ) - name: Setup Build Tools run: | diff --git a/base1432.c b/base1432.c index 4ce6019..9089ab0 100644 --- a/base1432.c +++ b/base1432.c @@ -25,7 +25,7 @@ typedef union { uint8_t buf[4]; uint32_t val; -} remainder; +} base16384_union_remainder; int base16384_encode_safe(const char* data, int dlen, char* buf) { int outlen = dlen / 7 * 8; @@ -60,7 +60,7 @@ int base16384_encode_safe(const char* data, int dlen, char* buf) { sum += 0x4e004e00; vals[n++] = be32toh(sum); } - remainder valbuf; + base16384_union_remainder valbuf; if(dlen - i == 7) { register uint32_t sum = 0; register uint32_t shift = htobe32(*(uint32_t*)(data+i)); @@ -276,7 +276,7 @@ int base16384_decode_safe(const char* data, int dlen, char* buf) { sum |= shift & 0x003fff00; *(uint32_t*)(buf+i+4) = be32toh(sum); } - remainder valbuf; + base16384_union_remainder valbuf; if(outlen - i == 7) { register uint32_t sum = 0; register uint32_t shift = htobe32(vals[n++]) - 0x4e004e00; diff --git a/base1464.c b/base1464.c index 0641f05..1cfc786 100644 --- a/base1464.c +++ b/base1464.c @@ -25,7 +25,7 @@ typedef union { uint8_t buf[8]; uint64_t val; -} remainder; +} base16384_union_remainder; int base16384_encode_safe(const char* data, int dlen, char* buf) { int outlen = dlen / 7 * 8; @@ -56,7 +56,7 @@ int base16384_encode_safe(const char* data, int dlen, char* buf) { sum += 0x4e004e004e004e00; vals[n++] = be64toh(sum); } - remainder valbuf; + base16384_union_remainder valbuf; if(dlen - i == 7) { memcpy(valbuf.buf, data+i, 7); register uint64_t sum = 0; @@ -243,7 +243,7 @@ int base16384_decode_safe(const char* data, int dlen, char* buf) { sum |= shift & 0x00000000003fff00; *(uint64_t*)(buf+i) = be64toh(sum); } - remainder valbuf; + base16384_union_remainder valbuf; if(outlen - i == 7) { register uint64_t sum = 0; register uint64_t shift = htobe64(vals[n]) - 0x4e004e004e004e00; From 3ca3c3c459aa88871592d95417bcd5bc866c4be6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Fri, 5 Apr 2024 17:25:44 +0900 Subject: [PATCH 33/35] fix(release): adapt to cosmopolitan --- .github/workflows/release.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 445402b..ff6d184 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,12 +16,11 @@ jobs: - name: Checkout Code id: checkout uses: actions/checkout@v2 - run: echo ::set-output name=VERSION::$( git describe --tags --abbrev=0 ) - name: Setup Build Tools run: | sudo apt-get update - sudo apt-get install -y gcc + sudo apt-get install -y gcc git wget https://justine.lol/cosmopolitan/cosmopolitan-amalgamation-1.0.zip unzip cosmopolitan-amalgamation-1.0.zip @@ -29,7 +28,7 @@ jobs: run: | gcc -g -Os -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone \ -fno-omit-frame-pointer -pg -mnop-mcount -D__cosmopolitan \ - -DBASE16384_VERSION=\"${{ steps.checkout.outputs.VERSION }}\" -DBASE16384_VERSION_DATE=\"`date +"%Y%b/%d"`\"\ + -DBASE16384_VERSION=\"`git describe --tags --abbrev=0`\" -DBASE16384_VERSION_DATE=\"`date +"%Y%b/%d"`\"\ -o base16384.com.dbg base16384.c file.c base1432.c -fuse-ld=bfd -Wl,-T,ape.lds \ -include cosmopolitan.h crt.o ape.o cosmopolitan.a objcopy -S -O binary base16384.com.dbg base16384.com From 688a4ecef2ea446e4ad40406fc440ed5d2701e56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Fri, 5 Apr 2024 17:56:35 +0900 Subject: [PATCH 34/35] fix(debian): some symbols or patterns disappeared --- CMakeLists.txt | 8 ++++---- base16384.h | 4 +--- wrap.c | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 wrap.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 9eec095..6fdd0ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,12 +24,12 @@ add_executable(base16384_b base16384.c) IF ((NOT FORCE_32BIT) AND CMAKE_SIZEOF_VOID_P EQUAL 8) message(STATUS "Adding 64bit libraries...") add_definitions(-DIS_64BIT_PROCESSOR) - add_library(base16384 SHARED file.c base1464.c) - add_library(base16384_s STATIC file.c base1464.c) + add_library(base16384 SHARED wrap.c file.c base1464.c) + add_library(base16384_s STATIC wrap.c file.c base1464.c) ELSE () message(STATUS "Adding 32bit libraries...") - add_library(base16384 SHARED file.c base1432.c) - add_library(base16384_s STATIC file.c base1432.c) + add_library(base16384 SHARED wrap.c file.c base1432.c) + add_library(base16384_s STATIC wrap.c file.c base1432.c) ENDIF () set_target_properties(base16384_b PROPERTIES OUTPUT_NAME base16384) diff --git a/base16384.h b/base16384.h index fe93fd7..b5be8a5 100644 --- a/base16384.h +++ b/base16384.h @@ -244,9 +244,7 @@ base16384_err_t base16384_decode_fp_detailed(base16384_typed_flag_params(FILE*)) base16384_err_t base16384_decode_fd_detailed(base16384_typed_flag_params(int)); #define BASE16384_WRAP_DECL(method, name, type) \ - static inline base16384_err_t base16384_##method##_##name(base16384_typed_params(type)) { \ - return base16384_##method##_##name##_detailed(input, output, encbuf, decbuf, 0); \ - } + base16384_err_t base16384_##method##_##name(base16384_typed_params(type)); BASE16384_WRAP_DECL(encode, file, const char*); BASE16384_WRAP_DECL(encode, fp, FILE*); diff --git a/wrap.c b/wrap.c new file mode 100644 index 0000000..5358b5f --- /dev/null +++ b/wrap.c @@ -0,0 +1,38 @@ +/* wrap.c + * This file is part of the base16384 distribution (https://github.com/fumiama/base16384). + * Copyright (c) 2022-2024 Fumiama Minamoto. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "base16384.h" + +#define base16384_typed_params(type) type input, type output, char* encbuf, char* decbuf + +#define BASE16384_WRAP_DECL(method, name, type) \ + base16384_err_t base16384_##method##_##name(base16384_typed_params(type)) { \ + return base16384_##method##_##name##_detailed(input, output, encbuf, decbuf, 0); \ + } + + BASE16384_WRAP_DECL(encode, file, const char*); + BASE16384_WRAP_DECL(encode, fp, FILE*); + BASE16384_WRAP_DECL(encode, fd, int); + + BASE16384_WRAP_DECL(decode, file, const char*); + BASE16384_WRAP_DECL(decode, fp, FILE*); + BASE16384_WRAP_DECL(decode, fd, int); + +#undef BASE16384_WRAP_DECL + +#undef base16384_typed_params From 5219ed7f26e1e86e16d3a902ff0b22697d9a7ffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Fri, 5 Apr 2024 17:57:50 +0900 Subject: [PATCH 35/35] fix(debian): some symbols or patterns disappeared --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ff6d184..c7b915b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -29,7 +29,7 @@ jobs: gcc -g -Os -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone \ -fno-omit-frame-pointer -pg -mnop-mcount -D__cosmopolitan \ -DBASE16384_VERSION=\"`git describe --tags --abbrev=0`\" -DBASE16384_VERSION_DATE=\"`date +"%Y%b/%d"`\"\ - -o base16384.com.dbg base16384.c file.c base1432.c -fuse-ld=bfd -Wl,-T,ape.lds \ + -o base16384.com.dbg base16384.c file.c wrap.c base1432.c -fuse-ld=bfd -Wl,-T,ape.lds \ -include cosmopolitan.h crt.o ape.o cosmopolitan.a objcopy -S -O binary base16384.com.dbg base16384.com