1
0
mirror of https://github.com/fumiama/base16384.git synced 2026-06-21 06:30:25 +08:00

Merge branch 'master' of https://github.com/fumiama/base16384 into debian

This commit is contained in:
源文雨
2024-04-08 00:42:36 +09:00
14 changed files with 439 additions and 106 deletions

View File

@@ -2,10 +2,10 @@ cmake_minimum_required(VERSION 2.8.12)
if (POLICY CMP0048) if (POLICY CMP0048)
cmake_policy(SET CMP0048 NEW) cmake_policy(SET CMP0048 NEW)
endif (POLICY CMP0048) endif (POLICY CMP0048)
project(base16384 VERSION 2.3.0) project(base16384 VERSION 2.3.1)
add_definitions(-DBASE16384_VERSION="${PROJECT_VERSION}") add_definitions(-DBASE16384_VERSION="${PROJECT_VERSION}")
add_definitions(-DBASE16384_VERSION_DATE="April 5th 2024") add_definitions(-DBASE16384_VERSION_DATE="April 7th 2024")
message(STATUS "Testing endian...") message(STATUS "Testing endian...")
include(TestBigEndian) include(TestBigEndian)

File diff suppressed because one or more lines are too long

View File

@@ -30,7 +30,7 @@ typedef union {
int base16384_encode_safe(const char* data, int dlen, char* buf) { int base16384_encode_safe(const char* data, int dlen, char* buf) {
int outlen = dlen / 7 * 8; int outlen = dlen / 7 * 8;
int offset = dlen % 7; int offset = dlen % 7;
switch(offset) { // 算上偏移标志字符占用的2字节 switch(offset) { // also count 0x3dxx
case 0: break; case 0: break;
case 1: outlen += 4; break; case 1: outlen += 4; break;
case 2: case 2:
@@ -127,7 +127,7 @@ int base16384_encode_safe(const char* data, int dlen, char* buf) {
int base16384_encode(const char* data, int dlen, char* buf) { int base16384_encode(const char* data, int dlen, char* buf) {
int outlen = dlen / 7 * 8; int outlen = dlen / 7 * 8;
int offset = dlen % 7; int offset = dlen % 7;
switch(offset) { // 算上偏移标志字符占用的2字节 switch(offset) { // also count 0x3dxx
case 0: break; case 0: break;
case 1: outlen += 4; break; case 1: outlen += 4; break;
case 2: case 2:
@@ -202,7 +202,7 @@ int base16384_encode(const char* data, int dlen, char* buf) {
int base16384_encode_unsafe(const char* data, int dlen, char* buf) { int base16384_encode_unsafe(const char* data, int dlen, char* buf) {
int outlen = dlen / 7 * 8; int outlen = dlen / 7 * 8;
int offset = dlen % 7; int offset = dlen % 7;
switch(offset) { // 算上偏移标志字符占用的2字节 switch(offset) { // also count 0x3dxx
case 0: break; case 0: break;
case 1: outlen += 4; break; case 1: outlen += 4; break;
case 2: case 2:
@@ -244,7 +244,7 @@ int base16384_decode_safe(const char* data, int dlen, char* buf) {
int offset = 0; int offset = 0;
if(data[dlen-2] == '=') { if(data[dlen-2] == '=') {
offset = data[dlen-1]; offset = data[dlen-1];
switch(offset) { // 算上偏移标志字符占用的2字节 switch(offset) { // also count 0x3dxx
case 0: break; case 0: break;
case 1: outlen -= 4; break; case 1: outlen -= 4; break;
case 2: case 2:
@@ -259,7 +259,7 @@ int base16384_decode_safe(const char* data, int dlen, char* buf) {
const uint32_t* vals = (const uint32_t*)data; const uint32_t* vals = (const uint32_t*)data;
uint32_t n = 0; uint32_t n = 0;
int32_t i = 0; int32_t i = 0;
for(; i < outlen - 7; i+=7) { // n实际每次自增2 for(; i < outlen - 7; i+=7) { // n += 2 in one loop
register uint32_t sum = 0; register uint32_t sum = 0;
register uint32_t shift = htobe32(vals[n++]) - 0x4e004e00; register uint32_t shift = htobe32(vals[n++]) - 0x4e004e00;
shift <<= 2; shift <<= 2;
@@ -341,7 +341,7 @@ int base16384_decode(const char* data, int dlen, char* buf) {
int offset = 0; int offset = 0;
if(data[dlen-2] == '=') { if(data[dlen-2] == '=') {
offset = data[dlen-1]; offset = data[dlen-1];
switch(offset) { // 算上偏移标志字符占用的2字节 switch(offset) { // also count 0x3dxx
case 0: break; case 0: break;
case 1: outlen -= 4; break; case 1: outlen -= 4; break;
case 2: case 2:
@@ -356,7 +356,7 @@ int base16384_decode(const char* data, int dlen, char* buf) {
const uint32_t* vals = (const uint32_t*)data; const uint32_t* vals = (const uint32_t*)data;
uint32_t n = 0; uint32_t n = 0;
int32_t i = 0; int32_t i = 0;
for(; i <= outlen - 7; i+=7) { // n实际每次自增2 for(; i <= outlen - 7; i+=7) { // n += 2 in one loop
register uint32_t sum = 0; register uint32_t sum = 0;
register uint32_t shift = htobe32(vals[n++]) - 0x4e004e00; register uint32_t shift = htobe32(vals[n++]) - 0x4e004e00;
shift <<= 2; shift <<= 2;
@@ -375,7 +375,7 @@ int base16384_decode(const char* data, int dlen, char* buf) {
} }
if(*(uint8_t*)(&vals[n]) == '=') return outlen; if(*(uint8_t*)(&vals[n]) == '=') return outlen;
if(offset--) { if(offset--) {
// 这里有读取越界 // here comes a read overlap
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
register uint32_t sum = __builtin_bswap32(vals[n++]); register uint32_t sum = __builtin_bswap32(vals[n++]);
#else #else
@@ -391,7 +391,7 @@ int base16384_decode(const char* data, int dlen, char* buf) {
if(offset--) { if(offset--) {
buf[i] = (sum & 0x0f000000) >> 20; buf[i] = (sum & 0x0f000000) >> 20;
if(*(uint8_t*)(&vals[n]) == '=') return outlen; if(*(uint8_t*)(&vals[n]) == '=') return outlen;
// 这里有读取越界 // here comes a read overlap
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
sum = __builtin_bswap32(vals[n]); sum = __builtin_bswap32(vals[n]);
#else #else
@@ -418,7 +418,7 @@ int base16384_decode_unsafe(const char* data, int dlen, char* buf) {
int offset = 0; int offset = 0;
if(data[dlen-2] == '=') { if(data[dlen-2] == '=') {
offset = data[dlen-1]; offset = data[dlen-1];
switch(offset) { // 算上偏移标志字符占用的2字节 switch(offset) { // also count 0x3dxx
case 0: break; case 0: break;
case 1: outlen -= 4; break; case 1: outlen -= 4; break;
case 2: case 2:
@@ -433,7 +433,7 @@ int base16384_decode_unsafe(const char* data, int dlen, char* buf) {
const uint32_t* vals = (const uint32_t*)data; const uint32_t* vals = (const uint32_t*)data;
uint32_t n = 0; uint32_t n = 0;
int32_t i = 0; int32_t i = 0;
for(; i < outlen-7; i+=7) { // n实际每次自增2 for(; i < outlen-7; i+=7) { // n += 2 in one loop
register uint32_t sum = 0; register uint32_t sum = 0;
register uint32_t shift = htobe32(vals[n++]) - 0x4e004e00; register uint32_t shift = htobe32(vals[n++]) - 0x4e004e00;
shift <<= 2; shift <<= 2;

View File

@@ -30,7 +30,7 @@ typedef union {
int base16384_encode_safe(const char* data, int dlen, char* buf) { int base16384_encode_safe(const char* data, int dlen, char* buf) {
int outlen = dlen / 7 * 8; int outlen = dlen / 7 * 8;
int offset = dlen % 7; int offset = dlen % 7;
switch(offset) { // 算上偏移标志字符占用的2字节 switch(offset) { // also count 0x3dxx
case 0: break; case 0: break;
case 1: outlen += 4; break; case 1: outlen += 4; break;
case 2: case 2:
@@ -112,7 +112,7 @@ int base16384_encode_safe(const char* data, int dlen, char* buf) {
int base16384_encode(const char* data, int dlen, char* buf) { int base16384_encode(const char* data, int dlen, char* buf) {
int outlen = dlen / 7 * 8; int outlen = dlen / 7 * 8;
int offset = dlen % 7; int offset = dlen % 7;
switch(offset) { // 算上偏移标志字符占用的2字节 switch(offset) { // also count 0x3dxx
case 0: break; case 0: break;
case 1: outlen += 4; break; case 1: outlen += 4; break;
case 2: case 2:
@@ -127,7 +127,7 @@ int base16384_encode(const char* data, int dlen, char* buf) {
int64_t i = 0; int64_t i = 0;
for(; i <= dlen - 7; i += 7) { for(; i <= dlen - 7; i += 7) {
register uint64_t sum = 0; register uint64_t sum = 0;
register uint64_t shift = htobe64(*(uint64_t*)(data+i))>>2; // 这里有读取越界 register uint64_t shift = htobe64(*(uint64_t*)(data+i))>>2; // here comes a read overlap
sum |= shift & 0x3fff000000000000; sum |= shift & 0x3fff000000000000;
shift >>= 2; shift >>= 2;
sum |= shift & 0x00003fff00000000; sum |= shift & 0x00003fff00000000;
@@ -177,7 +177,7 @@ int base16384_encode(const char* data, int dlen, char* buf) {
int base16384_encode_unsafe(const char* data, int dlen, char* buf) { int base16384_encode_unsafe(const char* data, int dlen, char* buf) {
int outlen = dlen / 7 * 8; int outlen = dlen / 7 * 8;
int offset = dlen % 7; int offset = dlen % 7;
switch(offset) { // 算上偏移标志字符占用的2字节 switch(offset) { // also count 0x3dxx
case 0: break; case 0: break;
case 1: outlen += 4; break; case 1: outlen += 4; break;
case 2: case 2:
@@ -192,7 +192,7 @@ int base16384_encode_unsafe(const char* data, int dlen, char* buf) {
int64_t i = 0; int64_t i = 0;
for(; i < dlen; i += 7) { for(; i < dlen; i += 7) {
register uint64_t sum = 0; register uint64_t sum = 0;
register uint64_t shift = htobe64(*(uint64_t*)(data+i))>>2; // 这里有读取越界 register uint64_t shift = htobe64(*(uint64_t*)(data+i))>>2; // here comes a read overlap
sum |= shift & 0x3fff000000000000; sum |= shift & 0x3fff000000000000;
shift >>= 2; shift >>= 2;
sum |= shift & 0x00003fff00000000; sum |= shift & 0x00003fff00000000;
@@ -215,7 +215,7 @@ int base16384_decode_safe(const char* data, int dlen, char* buf) {
int offset = 0; int offset = 0;
if(data[dlen-2] == '=') { if(data[dlen-2] == '=') {
offset = data[dlen-1]; offset = data[dlen-1];
switch(offset) { // 算上偏移标志字符占用的2字节 switch(offset) { // also count 0x3dxx
case 0: break; case 0: break;
case 1: outlen -= 4; break; case 1: outlen -= 4; break;
case 2: case 2:
@@ -264,20 +264,20 @@ int base16384_decode_safe(const char* data, int dlen, char* buf) {
#else #else
register uint64_t sum = valbuf.val - 0x000000000000004e; register uint64_t sum = valbuf.val - 0x000000000000004e;
#endif #endif
buf[i++] = ((sum & 0x000000000000003f) << 2) | ((sum & 0x000000000000c000) >> 14); buf[i++] = (char)(((sum & 0x000000000000003f) << 2) | ((sum & 0x000000000000c000) >> 14));
if(offset--) { if(offset--) {
sum -= 0x00000000004e0000; sum -= 0x00000000004e0000;
buf[i++] = ((sum & 0x0000000000003f00) >> 6) | ((sum & 0x0000000000300000) >> 20); buf[i++] = (char)(((sum & 0x0000000000003f00) >> 6) | ((sum & 0x0000000000300000) >> 20));
if(offset--) { if(offset--) {
buf[i++] = ((sum & 0x00000000000f0000) >> 12) | ((sum & 0x00000000f0000000) >> 28); buf[i++] = (char)(((sum & 0x00000000000f0000) >> 12) | ((sum & 0x00000000f0000000) >> 28));
if(offset--) { if(offset--) {
sum -= 0x0000004e00000000; sum -= 0x0000004e00000000;
buf[i++] = ((sum & 0x000000000f000000) >> 20) | ((sum & 0x0000003c00000000) >> 34); buf[i++] = (char)(((sum & 0x000000000f000000) >> 20) | ((sum & 0x0000003c00000000) >> 34));
if(offset--) { if(offset--) {
buf[i++] = ((sum & 0x0000000300000000) >> 26) | ((sum & 0x0000fc0000000000) >> 42); buf[i++] = (char)(((sum & 0x0000000300000000) >> 26) | ((sum & 0x0000fc0000000000) >> 42));
if(offset--) { if(offset--) {
sum -= 0x004e000000000000; sum -= 0x004e000000000000;
buf[i] = ((sum & 0x0000030000000000) >> 34) | ((sum & 0x003f000000000000) >> 48); buf[i] = (char)(((sum & 0x0000030000000000) >> 34) | ((sum & 0x003f000000000000) >> 48));
} }
} }
} }
@@ -292,7 +292,7 @@ int base16384_decode(const char* data, int dlen, char* buf) {
int offset = 0; int offset = 0;
if(data[dlen-2] == '=') { if(data[dlen-2] == '=') {
offset = data[dlen-1]; offset = data[dlen-1];
switch(offset) { // 算上偏移标志字符占用的2字节 switch(offset) { // also count 0x3dxx
case 0: break; case 0: break;
case 1: outlen -= 4; break; case 1: outlen -= 4; break;
case 2: case 2:
@@ -322,26 +322,26 @@ int base16384_decode(const char* data, int dlen, char* buf) {
} }
if(*(uint8_t*)(&vals[n]) == '=') return outlen; if(*(uint8_t*)(&vals[n]) == '=') return outlen;
if(offset--) { if(offset--) {
// 这里有读取越界 // here comes a read overlap
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
register uint64_t sum = __builtin_bswap64(vals[n]) - 0x000000000000004e; register uint64_t sum = __builtin_bswap64(vals[n]) - 0x000000000000004e;
#else #else
register uint64_t sum = vals[n] - 0x000000000000004e; register uint64_t sum = vals[n] - 0x000000000000004e;
#endif #endif
buf[i++] = ((sum & 0x000000000000003f) << 2) | ((sum & 0x000000000000c000) >> 14); buf[i++] = (char)(((sum & 0x000000000000003f) << 2) | ((sum & 0x000000000000c000) >> 14));
if(offset--) { if(offset--) {
sum -= 0x00000000004e0000; sum -= 0x00000000004e0000;
buf[i++] = ((sum & 0x0000000000003f00) >> 6) | ((sum & 0x0000000000300000) >> 20); buf[i++] = (char)(((sum & 0x0000000000003f00) >> 6) | ((sum & 0x0000000000300000) >> 20));
if(offset--) { if(offset--) {
buf[i++] = ((sum & 0x00000000000f0000) >> 12) | ((sum & 0x00000000f0000000) >> 28); buf[i++] = (char)(((sum & 0x00000000000f0000) >> 12) | ((sum & 0x00000000f0000000) >> 28));
if(offset--) { if(offset--) {
sum -= 0x0000004e00000000; sum -= 0x0000004e00000000;
buf[i++] = ((sum & 0x000000000f000000) >> 20) | ((sum & 0x0000003c00000000) >> 34); buf[i++] = (char)(((sum & 0x000000000f000000) >> 20) | ((sum & 0x0000003c00000000) >> 34));
if(offset--) { if(offset--) {
buf[i++] = ((sum & 0x0000000300000000) >> 26) | ((sum & 0x0000fc0000000000) >> 42); buf[i++] = (char)(((sum & 0x0000000300000000) >> 26) | ((sum & 0x0000fc0000000000) >> 42));
if(offset--) { if(offset--) {
sum -= 0x004e000000000000; sum -= 0x004e000000000000;
buf[i] = ((sum & 0x0000030000000000) >> 34) | ((sum & 0x003f000000000000) >> 48); buf[i] = (char)(((sum & 0x0000030000000000) >> 34) | ((sum & 0x003f000000000000) >> 48));
} }
} }
} }
@@ -356,7 +356,7 @@ int base16384_decode_unsafe(const char* data, int dlen, char* buf) {
int offset = 0; int offset = 0;
if(data[dlen-2] == '=') { if(data[dlen-2] == '=') {
offset = data[dlen-1]; offset = data[dlen-1];
switch(offset) { // 算上偏移标志字符占用的2字节 switch(offset) { // also count 0x3dxx
case 0: break; case 0: break;
case 1: outlen -= 4; break; case 1: outlen -= 4; break;
case 2: case 2:

View File

@@ -1,9 +1,9 @@
.TH BASE16384 1 "5 April 2024" "GNU" "User Commands" .TH BASE16384 1 "7 April 2024" "GNU" "User Commands"
.SH NAME .SH NAME
base16384 \- Encode binary files to printable utf16be base16384 \- Encode binary files to printable utf16be
.SH SYNOPSIS .SH SYNOPSIS
.B base16384 .B base16384
-[edtn] <\fIinputfile\fR> <\fIoutputfile\fR> -[ed][t][n][cC] <\fIinputfile\fR> <\fIoutputfile\fR>
.SH DESCRIPTION .SH DESCRIPTION
.LP .LP
There are There are

View File

@@ -27,11 +27,11 @@
#endif #endif
#include "base16384.h" #include "base16384.h"
char encbuf[BASE16384_ENCBUFSZ]; static char encbuf[BASE16384_ENCBUFSZ];
char decbuf[BASE16384_DECBUFSZ]; static char decbuf[BASE16384_DECBUFSZ];
#ifndef _WIN32 #ifndef _WIN32
unsigned long get_start_ms() { static unsigned long get_start_ms() {
struct timespec ts; struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts); clock_gettime(CLOCK_MONOTONIC, &ts);
return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000); return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000);
@@ -52,11 +52,11 @@ static base16384_err_t print_usage() {
BASE16384_VERSION_DATE BASE16384_VERSION_DATE
"). Usage:\n", stderr "). Usage:\n", stderr
); );
fputs("base16384 [-edtn] [inputfile] [outputfile]\n", stderr); fputs("base16384 -[ed][t][n][cC] [inputfile] [outputfile]\n", stderr);
fputs(" -e\t\tencode (default)\n", stderr); fputs(" -e\t\tencode (default)\n", stderr);
fputs(" -d\t\tdecode\n", stderr); fputs(" -d\t\tdecode\n", stderr);
fputs(" -t\t\tshow spend time\n", stderr); fputs(" -t\t\tshow spend time\n", stderr);
fputs(" -n\t\tdon't write utf16be file header (0xFEFF)\n", stderr); fputs(" -n\t\tdonot write utf16be file header (0xFEFF)\n", stderr);
fputs(" -c\t\tembed or validate checksum in remainder\n", stderr); fputs(" -c\t\tembed or validate checksum in remainder\n", stderr);
fputs(" -C\t\tdo -c forcely\n", stderr); fputs(" -C\t\tdo -c forcely\n", stderr);
fputs(" inputfile\tpass - to read from stdin\n", stderr); fputs(" inputfile\tpass - to read from stdin\n", stderr);

View File

@@ -23,6 +23,12 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#endif #endif
#ifdef _MSC_VER
#include <BaseTsd.h>
#ifndef ssize_t
typedef SSIZE_T ssize_t;
#endif
#endif
enum base16384_err_t { enum base16384_err_t {
base16384_err_ok, base16384_err_ok,
@@ -59,6 +65,39 @@ typedef enum base16384_err_t base16384_err_t;
// forcely do sumcheck without checking data length // forcely do sumcheck without checking data length
#define BASE16384_FLAG_DO_SUM_CHECK_FORCELY (1<<2) #define BASE16384_FLAG_DO_SUM_CHECK_FORCELY (1<<2)
/**
* @brief custom reader function interface
* @param client_data the data pointer defined by the client
* @param buffer to where put data
* @param count read bytes count
* @return the size read
*/
typedef ssize_t (*base16384_reader_t)(const void *client_data, void *buffer, size_t count);
/**
* @brief custom writer function interface
* @param client_data the data pointer defined by the client
* @param buffer from where read data
* @param count write bytes count
* @return the size written
*/
typedef ssize_t (*base16384_writer_t)(const void *client_data, const void *buffer, size_t count);
union base16384_io_function_t {
base16384_reader_t reader;
base16384_writer_t writer;
};
typedef union base16384_io_function_t base16384_io_function_t;
struct base16384_stream_t {
base16384_io_function_t f;
void *client_data;
};
/**
* @brief for stream encode/decode
*/
typedef struct base16384_stream_t base16384_stream_t;
/** /**
* @brief calculate the exact encoded size * @brief calculate the exact encoded size
* @param dlen the data length to encode * @param dlen the data length to encode
@@ -67,7 +106,7 @@ typedef enum base16384_err_t base16384_err_t;
static inline int _base16384_encode_len(int dlen) { static inline int _base16384_encode_len(int dlen) {
int outlen = dlen / 7 * 8; int outlen = dlen / 7 * 8;
int offset = dlen % 7; int offset = dlen % 7;
switch(offset) { // 算上偏移标志字符占用的 2 字节 switch(offset) { // also count 0x3dxx
case 0: break; case 0: break;
case 1: outlen += 4; break; case 1: outlen += 4; break;
case 2: case 2:
@@ -97,7 +136,7 @@ static inline int base16384_encode_len(int dlen) {
*/ */
static inline int _base16384_decode_len(int dlen, int offset) { static inline int _base16384_decode_len(int dlen, int offset) {
int outlen = dlen; int outlen = dlen;
switch(offset) { // 算上偏移标志字符占用的 2 字节 switch(offset) { // also count 0x3dxx
case 0: break; case 0: break;
case 1: outlen -= 4; break; case 1: outlen -= 4; break;
case 2: case 2:
@@ -210,6 +249,17 @@ base16384_err_t base16384_encode_fp_detailed(base16384_typed_flag_params(FILE*))
*/ */
base16384_err_t base16384_encode_fd_detailed(base16384_typed_flag_params(int)); base16384_err_t base16384_encode_fd_detailed(base16384_typed_flag_params(int));
/**
* @brief encode custom input reader to custom output writer
* @param input custom input reader
* @param output custom output writer
* @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_stream_detailed(base16384_typed_flag_params(base16384_stream_t*));
/** /**
* @brief decode input file to output file * @brief decode input file to output file
* @param input filename or `-` to specify stdin * @param input filename or `-` to specify stdin
@@ -243,16 +293,29 @@ base16384_err_t base16384_decode_fp_detailed(base16384_typed_flag_params(FILE*))
*/ */
base16384_err_t base16384_decode_fd_detailed(base16384_typed_flag_params(int)); base16384_err_t base16384_decode_fd_detailed(base16384_typed_flag_params(int));
/**
* @brief decode custom input reader to custom output writer
* @param input custom input reader
* @param output custom output writer
* @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_stream_detailed(base16384_typed_flag_params(base16384_stream_t*));
#define BASE16384_WRAP_DECL(method, name, type) \ #define BASE16384_WRAP_DECL(method, name, type) \
base16384_err_t base16384_##method##_##name(base16384_typed_params(type)); base16384_err_t base16384_##method##_##name(base16384_typed_params(type));
BASE16384_WRAP_DECL(encode, file, const char*); BASE16384_WRAP_DECL(encode, file, const char*);
BASE16384_WRAP_DECL(encode, fp, FILE*); BASE16384_WRAP_DECL(encode, fp, FILE*);
BASE16384_WRAP_DECL(encode, fd, int); BASE16384_WRAP_DECL(encode, fd, int);
BASE16384_WRAP_DECL(encode, stream, base16384_stream_t*);
BASE16384_WRAP_DECL(decode, file, const char*); BASE16384_WRAP_DECL(decode, file, const char*);
BASE16384_WRAP_DECL(decode, fp, FILE*); BASE16384_WRAP_DECL(decode, fp, FILE*);
BASE16384_WRAP_DECL(decode, fd, int); BASE16384_WRAP_DECL(decode, fd, int);
BASE16384_WRAP_DECL(decode, stream, base16384_stream_t*);
#undef BASE16384_WRAP_DECL #undef BASE16384_WRAP_DECL

View File

@@ -90,7 +90,11 @@
// initial sum value used in BASE16384_FLAG_SUM_CHECK_ON_REMAIN // initial sum value used in BASE16384_FLAG_SUM_CHECK_ON_REMAIN
#define BASE16384_SIMPLE_SUM_INIT_VALUE (0x8e29c213) #define BASE16384_SIMPLE_SUM_INIT_VALUE (0x8e29c213)
#ifdef _MSC_VER
static inline uint32_t calc_sum(uint32_t sum, int cnt, const char* encbuf) {
#else
static inline uint32_t calc_sum(uint32_t sum, size_t cnt, const char* encbuf) { static inline uint32_t calc_sum(uint32_t sum, size_t cnt, const char* encbuf) {
#endif
size_t i; size_t i;
uint32_t buf; uint32_t buf;
for(i = 0; i < cnt; i++) { for(i = 0; i < cnt; i++) {

168
file.c
View File

@@ -16,6 +16,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef _MSC_VER
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#endif
#ifndef __cosmopolitan #ifndef __cosmopolitan
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
@@ -57,14 +63,14 @@ static inline off_t get_file_size(const char* filepath) {
#define do_sum_check(flag) ((flag)&(BASE16384_FLAG_DO_SUM_CHECK_FORCELY|BASE16384_FLAG_SUM_CHECK_ON_REMAIN)) #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) { 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;
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) { if(!input || !output || strlen(input) <= 0 || strlen(output) <= 0) {
errno = EINVAL; errno = EINVAL;
return base16384_err_invalid_file_name; return base16384_err_invalid_file_name;
} }
base16384_err_t retval = base16384_err_ok;
off_t inputsize;
FILE *fp = NULL, *fpo;
int errnobak = 0, is_stdin = is_standard_io(input);
if(is_stdin) { // read from stdin if(is_stdin) { // read from stdin
inputsize = _BASE16384_ENCBUFSZ; inputsize = _BASE16384_ENCBUFSZ;
fp = stdin; fp = stdin;
@@ -91,7 +97,11 @@ base16384_err_t base16384_encode_file_detailed(const char* input, const char* ou
fputc(0xFE, fpo); fputc(0xFE, fpo);
fputc(0xFF, fpo); fputc(0xFF, fpo);
} }
size_t cnt; #ifdef _MSC_VER
int cnt;
#else
size_t cnt;
#endif
uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE; uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE;
while((cnt = fread(encbuf, sizeof(char), inputsize, fp)) > 0) { while((cnt = fread(encbuf, sizeof(char), inputsize, fp)) > 0) {
int n; int n;
@@ -159,7 +169,11 @@ base16384_err_t base16384_encode_fp_detailed(FILE* input, FILE* output, char* en
} }
off_t inputsize = _BASE16384_ENCBUFSZ; off_t inputsize = _BASE16384_ENCBUFSZ;
uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE; uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE;
size_t cnt; #ifdef _MSC_VER
int cnt;
#else
size_t cnt;
#endif
while((cnt = fread(encbuf, sizeof(char), inputsize, input)) > 0) { while((cnt = fread(encbuf, sizeof(char), inputsize, input)) > 0) {
int n; int n;
while(cnt%7) { while(cnt%7) {
@@ -213,10 +227,45 @@ base16384_err_t base16384_encode_fd_detailed(int input, int output, char* encbuf
return base16384_err_ok; return base16384_err_ok;
} }
#define rm_head(fp) {\ #define call_reader(cd, buf, n) (input->f.reader((cd)->client_data, (buf), (n)))
int ch = fgetc(fp);\ #define call_writer(cd, buf, n) (output->f.writer((cd)->client_data, (buf), (n)))
if(ch == 0xFE) fgetc(fp);\
else ungetc(ch, fp);\ base16384_err_t base16384_encode_stream_detailed(base16384_stream_t* input, base16384_stream_t* output, char* encbuf, char* decbuf, int flag) {
if(!input || !input->f.reader) {
return base16384_err_fopen_input_file;
}
if(!output || !output->f.writer) {
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)) call_writer(output, "\xfe\xff", 2);
while((cnt = call_reader(input, encbuf, inputsize)) > 0) {
ssize_t n;
while(cnt%7) {
n = call_reader(input, encbuf+cnt, sizeof(char));
if(n > 0) cnt++;
else break;
}
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 && call_writer(output, decbuf, n) < n) {
return base16384_err_write_file;
}
}
return base16384_err_ok;
}
static inline void rm_head(FILE* fp) {
int ch = fgetc(fp);
if(ch == 0xFE) fgetc(fp);
else ungetc(ch, fp);
} }
#define skip_offset(input_file) ((input_file[0]==(char)0xFE)?2:0) #define skip_offset(input_file) ((input_file[0]==(char)0xFE)?2:0)
@@ -230,16 +279,16 @@ static inline int is_next_end(FILE* fp) {
} }
base16384_err_t base16384_decode_file_detailed(const char* input, const char* output, char* encbuf, char* decbuf, int flag) { base16384_err_t base16384_decode_file_detailed(const char* input, const char* output, char* encbuf, char* decbuf, int flag) {
if(!input || !output || strlen(input) <= 0 || strlen(output) <= 0) {
errno = EINVAL;
return base16384_err_invalid_file_name;
}
off_t inputsize; off_t inputsize;
FILE* fp = NULL; FILE* fp = NULL;
FILE* fpo; FILE* fpo;
uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE; uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE;
base16384_err_t retval = base16384_err_ok; base16384_err_t retval = base16384_err_ok;
int errnobak = 0, is_stdin = is_standard_io(input); 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_stdin) { // read from stdin if(is_stdin) { // read from stdin
inputsize = _BASE16384_DECBUFSZ; inputsize = _BASE16384_DECBUFSZ;
fp = stdin; fp = stdin;
@@ -264,9 +313,11 @@ base16384_err_t base16384_decode_file_detailed(const char* input, const char* ou
goto_base16384_file_detailed_cleanup(decode, base16384_err_fopen_input_file, {}); goto_base16384_file_detailed_cleanup(decode, base16384_err_fopen_input_file, {});
} }
rm_head(fp); rm_head(fp);
#ifndef _WIN32 // windows is crazy and always throws EINVAL
if(errno) { if(errno) {
goto_base16384_file_detailed_cleanup(decode, base16384_err_read_file, {}); goto_base16384_file_detailed_cleanup(decode, base16384_err_read_file, {});
} }
#endif
int cnt, last_encbuf_cnt = 0, last_decbuf_cnt = 0, offset = 0; int cnt, last_encbuf_cnt = 0, last_decbuf_cnt = 0, offset = 0;
size_t total_decoded_len = 0; size_t total_decoded_len = 0;
while((cnt = fread(decbuf, sizeof(char), inputsize, fp)) > 0) { while((cnt = fread(decbuf, sizeof(char), inputsize, fp)) > 0) {
@@ -281,7 +332,9 @@ base16384_err_t base16384_decode_file_detailed(const char* input, const char* ou
decbuf[cnt++] = '='; decbuf[cnt++] = '=';
decbuf[cnt++] = end; decbuf[cnt++] = end;
} }
#ifndef _WIN32 // windows is crazy and always throws EINVAL
if(errno) goto_base16384_file_detailed_cleanup(decode, base16384_err_read_file, {}); if(errno) goto_base16384_file_detailed_cleanup(decode, base16384_err_read_file, {});
#endif
offset = decbuf[cnt-1]; offset = decbuf[cnt-1];
last_decbuf_cnt = cnt; last_decbuf_cnt = cnt;
cnt = base16384_decode_unsafe(decbuf, cnt, encbuf); cnt = base16384_decode_unsafe(decbuf, cnt, encbuf);
@@ -341,9 +394,11 @@ base16384_err_t base16384_decode_fp_detailed(FILE* input, FILE* output, char* en
off_t inputsize = _BASE16384_DECBUFSZ; off_t inputsize = _BASE16384_DECBUFSZ;
uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE; uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE;
rm_head(input); rm_head(input);
#ifndef _WIN32 // windows is crazy and always throws EINVAL
if(errno) { if(errno) {
return base16384_err_read_file; return base16384_err_read_file;
} }
#endif
int cnt, last_encbuf_cnt = 0, last_decbuf_cnt = 0, offset = 0; int cnt, last_encbuf_cnt = 0, last_decbuf_cnt = 0, offset = 0;
size_t total_decoded_len = 0; size_t total_decoded_len = 0;
while((cnt = fread(decbuf, sizeof(char), inputsize, input)) > 0) { while((cnt = fread(decbuf, sizeof(char), inputsize, input)) > 0) {
@@ -358,7 +413,9 @@ base16384_err_t base16384_decode_fp_detailed(FILE* input, FILE* output, char* en
decbuf[cnt++] = '='; decbuf[cnt++] = '=';
decbuf[cnt++] = end; decbuf[cnt++] = end;
} }
#ifndef _WIN32 // windows is crazy and always throws EINVAL
if(errno) return base16384_err_read_file; if(errno) return base16384_err_read_file;
#endif
offset = decbuf[cnt-1]; offset = decbuf[cnt-1];
last_decbuf_cnt = cnt; last_decbuf_cnt = cnt;
cnt = base16384_decode_unsafe(decbuf, cnt, encbuf); cnt = base16384_decode_unsafe(decbuf, cnt, encbuf);
@@ -429,9 +486,11 @@ base16384_err_t base16384_decode_fd_detailed(int input, int output, char* encbuf
else break; else break;
} }
uint16_t next = is_next_end_fd(input); uint16_t next = is_next_end_fd(input);
#ifndef _WIN32 // windows is crazy and always throws EINVAL
if(errno) { if(errno) {
return base16384_err_read_file; return base16384_err_read_file;
} }
#endif
if((uint16_t)(~next)) { if((uint16_t)(~next)) {
if(next&0xff00) { if(next&0xff00) {
decbuf[n++] = '='; decbuf[n++] = '=';
@@ -458,3 +517,84 @@ base16384_err_t base16384_decode_fd_detailed(int input, int output, char* encbuf
} }
return base16384_err_ok; return base16384_err_ok;
} }
static inline uint16_t is_next_end_stream(base16384_stream_t* input) {
uint8_t ch = 0;
if(call_reader(input, &ch, 1) != 1) return (uint16_t)EOF;
uint16_t ret = (uint16_t)ch & 0x00ff;
if(ch == '=') {
if(call_reader(input, &ch, 1) != 1) return (uint16_t)EOF;
ret <<= 8;
ret |= (uint16_t)ch & 0x00ff;
}
return ret;
}
base16384_err_t base16384_decode_stream_detailed(base16384_stream_t* input, base16384_stream_t* output, char* encbuf, char* decbuf, int flag) {
if(!input || !input->f.reader) {
errno = EINVAL;
return base16384_err_fopen_input_file;
}
if(!output || !output->f.writer) {
errno = EINVAL;
return base16384_err_fopen_output_file;
}
off_t inputsize = _BASE16384_DECBUFSZ;
uint32_t sum = BASE16384_SIMPLE_SUM_INIT_VALUE;
uint8_t remains[8];
decbuf[0] = 0;
if(call_reader(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 = call_reader(input, decbuf+p, inputsize-p)) > 0) {
if(p) {
memcpy(decbuf, remains, p);
n += p;
p = 0;
}
int x;
while(n%8) {
x = call_reader(input, decbuf+n, sizeof(char));
if(x > 0) n++;
else break;
}
uint16_t next = is_next_end_stream(input);
#ifndef _WIN32 // windows is crazy and always throws EINVAL
if(errno) {
return base16384_err_read_file;
}
#endif
if((uint16_t)(~next)) {
if(next&0xff00) {
decbuf[n++] = '=';
decbuf[n++] = (char)(next&0x00ff);
} else remains[p++] = (char)(next&0x00ff);
}
offset = decbuf[n-1];
last_decbuf_cnt = n;
n = base16384_decode_unsafe(decbuf, n, encbuf);
if(n && call_writer(output, encbuf, n) != n) {
return base16384_err_write_file;
}
total_decoded_len += n;
if(do_sum_check(flag)) sum = calc_sum(sum, n, encbuf);
last_encbuf_cnt = n;
}
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] == '='
&& check_sum(sum, *(uint32_t*)(&encbuf[last_encbuf_cnt]), offset)) {
errno = EINVAL;
return base16384_err_invalid_decoding_checksum;
}
return base16384_err_ok;
}

View File

@@ -26,9 +26,9 @@
#define TEST_SIZE (4096) #define TEST_SIZE (4096)
char encbuf[TEST_SIZE+16]; static char encbuf[TEST_SIZE+16];
char decbuf[TEST_SIZE/7*8+16]; static char decbuf[TEST_SIZE/7*8+16];
char tstbuf[TEST_SIZE+16]; static char tstbuf[TEST_SIZE+16];
#define loop_diff(target) \ #define loop_diff(target) \
for(i = start; i < end; i++) { \ for(i = start; i < end; i++) { \

View File

@@ -39,19 +39,9 @@
#define TEST_OUTPUT_FILENAME "file_test_output.bin" #define TEST_OUTPUT_FILENAME "file_test_output.bin"
#define TEST_VALIDATE_FILENAME "file_test_validate.bin" #define TEST_VALIDATE_FILENAME "file_test_validate.bin"
char encbuf[BASE16384_ENCBUFSZ]; static char encbuf[BASE16384_ENCBUFSZ];
char decbuf[BASE16384_DECBUFSZ]; static char decbuf[BASE16384_DECBUFSZ];
char tstbuf[BASE16384_ENCBUFSZ]; static char tstbuf[BASE16384_ENCBUFSZ];
#define init_input_file() \
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, BASE16384_ENCBUFSZ, 1, fp) != 1, "fwrite"); \
ok(fclose(fp), "fclose"); \
fputs("input file created.\n", stderr);
#define test_file_detailed(flag) \ #define test_file_detailed(flag) \
fputs("testing base16384_en/decode_file with flag "#flag"...\n", stderr); \ fputs("testing base16384_en/decode_file with flag "#flag"...\n", stderr); \
@@ -107,19 +97,58 @@ char tstbuf[BASE16384_ENCBUFSZ];
for(i = TEST_SIZE; i > 0; i--) { \ for(i = TEST_SIZE; i > 0; i--) { \
reset_and_truncate(fd, i); \ reset_and_truncate(fd, i); \
\ \
int fdout = open(TEST_OUTPUT_FILENAME, O_RDWR|O_TRUNC|O_CREAT|O_APPEND); \ int fdout = open(TEST_OUTPUT_FILENAME, O_RDWR|O_TRUNC|O_CREAT|O_APPEND, 0644); \
loop_ok(!fdout, i, "open"); \ loop_ok(!fdout, i, "open"); \
\ \
err = base16384_encode_fd_detailed(fd, fdout, encbuf, decbuf, 0); \ err = base16384_encode_fd_detailed(fd, fdout, encbuf, decbuf, flag); \
base16384_loop_ok(err); \ base16384_loop_ok(err); \
loop_ok(close(fd), i, "close"); \ loop_ok(close(fd), i, "close"); \
\ \
int fdval = open(TEST_VALIDATE_FILENAME, O_WRONLY|O_TRUNC|O_CREAT); \ int fdval = open(TEST_VALIDATE_FILENAME, O_WRONLY|O_TRUNC|O_CREAT, 0644); \
loop_ok(!fdval, i, "open"); \ loop_ok(!fdval, i, "open"); \
\ \
loop_ok(lseek(fdout, 0, SEEK_SET), i, "lseek"); \ loop_ok(lseek(fdout, 0, SEEK_SET), i, "lseek"); \
\ \
err = base16384_decode_fd_detailed(fdout, fdval, encbuf, decbuf, 0); \ err = base16384_decode_fd_detailed(fdout, fdval, encbuf, decbuf, flag); \
base16384_loop_ok(err); \
\
loop_ok(close(fdout), i, "close"); \
loop_ok(close(fdval), i, "close"); \
\
validate_result(); \
}
#define test_stream_detailed(flag) \
fputs("testing base16384_en/decode_stream with flag "#flag"...\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, 0644); \
loop_ok(!fdout, i, "open"); \
\
err = base16384_encode_stream_detailed(&(base16384_stream_t){ \
.client_data = (void*)(uintptr_t)fd, \
.f.reader = base16384_test_file_reader, \
}, &(base16384_stream_t){ \
.client_data = (void*)(uintptr_t)fdout, \
.f.writer = base16384_test_file_writer, \
}, encbuf, decbuf, flag); \
base16384_loop_ok(err); \
loop_ok(close(fd), i, "close"); \
\
int fdval = open(TEST_VALIDATE_FILENAME, O_WRONLY|O_TRUNC|O_CREAT, 0644); \
loop_ok(!fdval, i, "open"); \
\
loop_ok(lseek(fdout, 0, SEEK_SET), i, "lseek"); \
\
err = base16384_decode_stream_detailed(&(base16384_stream_t){ \
.client_data = (void*)(uintptr_t)fdout, \
.f.reader = base16384_test_file_reader, \
}, &(base16384_stream_t){ \
.client_data = (void*)(uintptr_t)fdval, \
.f.writer = base16384_test_file_writer, \
}, encbuf, decbuf, flag); \
base16384_loop_ok(err); \ base16384_loop_ok(err); \
\ \
loop_ok(close(fdout), i, "close"); \ loop_ok(close(fdout), i, "close"); \
@@ -142,12 +171,6 @@ char tstbuf[BASE16384_ENCBUFSZ];
\ \
test_##name##_detailed(BASE16384_FLAG_NOHEADER|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() { int main() {
srand(time(NULL)); srand(time(NULL));
@@ -155,9 +178,12 @@ int main() {
int fd, i; int fd, i;
base16384_err_t err; base16384_err_t err;
init_test_files();
test_detailed(file); test_detailed(file);
test_detailed(fp); test_detailed(fp);
test_detailed(fd); test_detailed(fd);
test_detailed(stream);
remove_test_files(); remove_test_files();

View File

@@ -19,6 +19,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef _MSC_VER
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#endif
#include <stdint.h>
#define ok(has_failed, reason) \ #define ok(has_failed, reason) \
if (has_failed) { \ if (has_failed) { \
perror(reason); \ perror(reason); \
@@ -82,4 +90,66 @@
return 1; \ return 1; \
} }
#define init_input_file() \
fprintf(stderr, "fill encbufsz: %d\n", BASE16384_ENCBUFSZ);\
for(i = 0; i < BASE16384_ENCBUFSZ/sizeof(uint16_t); i++) { \
((uint16_t*)encbuf)[i] = (uint16_t)rand(); \
} \
fp = fopen(TEST_INPUT_FILENAME, "wb"); \
ok(!fp, "fopen"); \
ok(fwrite(encbuf, BASE16384_ENCBUFSZ, 1, fp) != 1, "fwrite"); \
ok(fclose(fp), "fclose"); \
fputs("input file created.\n", stderr);
#define init_test_files() {\
fd = open(TEST_INPUT_FILENAME, O_RDWR|O_TRUNC|O_CREAT, 0644); \
ok(fd<0, "open"); \
ok(close(fd), "close"); \
fd = open(TEST_OUTPUT_FILENAME, O_RDWR|O_TRUNC|O_CREAT, 0644); \
ok(fd<0, "open"); \
ok(close(fd), "close"); \
fd = open(TEST_VALIDATE_FILENAME, O_RDWR|O_TRUNC|O_CREAT, 0644); \
ok(fd<0, "open"); \
ok(close(fd), "close");
#define remove_test_files() \
remove(TEST_INPUT_FILENAME); \
remove(TEST_OUTPUT_FILENAME); \
remove(TEST_VALIDATE_FILENAME); \
}
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
static ssize_t base16384_test_file_reader(const void *client_data, void *buffer, size_t count) {
int fd = (int)((uintptr_t)client_data);
ssize_t ret = read(fd, buffer, count);
if(ret < 0) return ret;
ssize_t i;
for(i = 0; i < ret; i++) {
((uint8_t*)(buffer))[i] = ~((uint8_t*)(buffer))[i];
}
return ret;
}
static ssize_t base16384_test_file_writer(const void *client_data, const void *buffer, size_t count) {
int fd = (int)((uintptr_t)client_data);
if(count <= 0) {
errno = EINVAL;
return -100;
}
uint8_t* wbuf = (uint8_t*)malloc(count);
if(!wbuf) return -200;
ssize_t i;
for(i = 0; i < count; i++) {
wbuf[i] = ~((uint8_t*)(buffer))[i];
}
ssize_t ret = write(fd, buffer, count);
int errnobak = errno;
free(wbuf);
errno = errnobak;
return ret;
}
#endif #endif

View File

@@ -39,19 +39,9 @@
#define TEST_OUTPUT_FILENAME "wrap_test_output.bin" #define TEST_OUTPUT_FILENAME "wrap_test_output.bin"
#define TEST_VALIDATE_FILENAME "wrap_test_validate.bin" #define TEST_VALIDATE_FILENAME "wrap_test_validate.bin"
char encbuf[BASE16384_ENCBUFSZ]; static char encbuf[BASE16384_ENCBUFSZ];
char decbuf[BASE16384_DECBUFSZ]; static char decbuf[BASE16384_DECBUFSZ];
char tstbuf[BASE16384_ENCBUFSZ]; static char tstbuf[BASE16384_ENCBUFSZ];
#define init_input_file() \
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, BASE16384_ENCBUFSZ, 1, fp) != 1, "fwrite"); \
ok(fclose(fp), "fclose"); \
fputs("input file created.\n", stderr);
int main() { int main() {
srand(time(NULL)); srand(time(NULL));
@@ -60,6 +50,8 @@ int main() {
int fd, i; int fd, i;
base16384_err_t err; base16384_err_t err;
init_test_files();
fputs("testing base16384_en/decode_file...\n", stderr); fputs("testing base16384_en/decode_file...\n", stderr);
init_input_file(); init_input_file();
for(i = TEST_SIZE; i > 0; i--) { for(i = TEST_SIZE; i > 0; i--) {
@@ -111,14 +103,14 @@ int main() {
for(i = TEST_SIZE; i > 0; i--) { for(i = TEST_SIZE; i > 0; i--) {
reset_and_truncate(fd, i); reset_and_truncate(fd, i);
int fdout = open(TEST_OUTPUT_FILENAME, O_RDWR|O_TRUNC|O_CREAT|O_APPEND); int fdout = open(TEST_OUTPUT_FILENAME, O_RDWR|O_TRUNC|O_CREAT|O_APPEND, 0644);
loop_ok(!fdout, i, "open"); loop_ok(!fdout, i, "open");
err = base16384_encode_fd(fd, fdout, encbuf, decbuf); err = base16384_encode_fd(fd, fdout, encbuf, decbuf);
base16384_loop_ok(err); base16384_loop_ok(err);
loop_ok(close(fd), i, "close"); loop_ok(close(fd), i, "close");
int fdval = open(TEST_VALIDATE_FILENAME, O_WRONLY|O_TRUNC|O_CREAT); int fdval = open(TEST_VALIDATE_FILENAME, O_WRONLY|O_TRUNC|O_CREAT, 0644);
loop_ok(!fdval, i, "open"); loop_ok(!fdval, i, "open");
loop_ok(lseek(fdout, 0, SEEK_SET), i, "lseek"); loop_ok(lseek(fdout, 0, SEEK_SET), i, "lseek");
@@ -132,9 +124,45 @@ int main() {
validate_result(); validate_result();
} }
remove(TEST_INPUT_FILENAME); fputs("testing base16384_en/decode_stream...\n", stderr);
remove(TEST_OUTPUT_FILENAME); init_input_file();
remove(TEST_VALIDATE_FILENAME); 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, 0644);
loop_ok(!fdout, i, "open");
err = base16384_encode_stream(&(base16384_stream_t){
.client_data = (void*)(uintptr_t)fd,
.f.reader = base16384_test_file_reader,
}, &(base16384_stream_t){
.client_data = (void*)(uintptr_t)fdout,
.f.writer = base16384_test_file_writer,
}, encbuf, decbuf);
base16384_loop_ok(err);
loop_ok(close(fd), i, "close");
int fdval = open(TEST_VALIDATE_FILENAME, O_WRONLY|O_TRUNC|O_CREAT, 0644);
loop_ok(!fdval, i, "open");
loop_ok(lseek(fdout, 0, SEEK_SET), i, "lseek");
err = base16384_decode_stream(&(base16384_stream_t){
.client_data = (void*)(uintptr_t)fdout,
.f.reader = base16384_test_file_reader,
}, &(base16384_stream_t){
.client_data = (void*)(uintptr_t)fdval,
.f.writer = base16384_test_file_writer,
}, encbuf, decbuf);
base16384_loop_ok(err);
loop_ok(close(fdout), i, "close");
loop_ok(close(fdval), i, "close");
validate_result();
}
remove_test_files();
return 0; return 0;
} }

2
wrap.c
View File

@@ -28,10 +28,12 @@
BASE16384_WRAP_DECL(encode, file, const char*); BASE16384_WRAP_DECL(encode, file, const char*);
BASE16384_WRAP_DECL(encode, fp, FILE*); BASE16384_WRAP_DECL(encode, fp, FILE*);
BASE16384_WRAP_DECL(encode, fd, int); BASE16384_WRAP_DECL(encode, fd, int);
BASE16384_WRAP_DECL(encode, stream, base16384_stream_t*);
BASE16384_WRAP_DECL(decode, file, const char*); BASE16384_WRAP_DECL(decode, file, const char*);
BASE16384_WRAP_DECL(decode, fp, FILE*); BASE16384_WRAP_DECL(decode, fp, FILE*);
BASE16384_WRAP_DECL(decode, fd, int); BASE16384_WRAP_DECL(decode, fd, int);
BASE16384_WRAP_DECL(decode, stream, base16384_stream_t*);
#undef BASE16384_WRAP_DECL #undef BASE16384_WRAP_DECL