Skip to content

Commit b90b649

Browse files
committed
feature: implement base85 like Go's encoding/ascii85
1 parent 5b90850 commit b90b649

10 files changed

+642
-1
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
t/servroot
22
*.o
33
librestybaseencoding.so
4+
modp_b85_gen
5+
bm.lua

Makefile

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ ${OBJ} : %.o : %.c
1212
${LIB} : ${OBJ}
1313
$(CC) $^ $(LDFLAGS) -o $@
1414

15+
modp_b85_gen: modp_b85_gen.o arraytoc.o
16+
1517
clean:
16-
rm -f $(LIB) *.o
18+
rm -f $(LIB) modp_b85_gen *.o
1719

1820
test: $(LIB)
1921
prove -r t/

README.md

+19
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ Table of Contents
2929
* [decode_base64](#decode_base64)
3030
* [encode_base64url](#encode_base64url)
3131
* [decode_base64url](#decode_base64url)
32+
* [encode_base85](#encode_base85)
33+
* [encode_base85](#encode_base85)
3234

3335
## MUST READ
3436

@@ -147,3 +149,20 @@ Read the 'Must Read' section for more info.
147149

148150
[Back to TOC](#table-of-contents)
149151

152+
### encode_base85
153+
`syntax: encoded = encode_base85(raw)`
154+
155+
Encode given string into base85 format with/without padding '='.
156+
Note that there is not a standard but too many variants of so-called base85.
157+
This module's implementation should be compatiable with Go's encoding/ascii85
158+
module (not in the level of API argument, but in the level of encode/decode rules).
159+
160+
[Back to TOC](#table-of-contents)
161+
162+
### encode_base85
163+
`syntax: raw, err = decode_base85(encoded)`
164+
165+
Decode base85 format string into its raw value. If the given string is not valid base85 encoded, the `raw` will be `nil` and `err` will be `"invalid input"`.
166+
167+
[Back to TOC](#table-of-contents)
168+

arraytoc.c

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#include "arraytoc.h"
2+
#include <stdio.h>
3+
4+
/* dump uint32_t as hex digits */
5+
void uint32_array_to_c_hex(const uint32_t* ary, size_t sz, const char* name)
6+
{
7+
size_t i = 0;
8+
9+
printf("static const uint32_t %s[%d] = {\n ", name, (int)sz);
10+
for (;;) {
11+
printf("0x%08x", ary[i]);
12+
++i;
13+
if (i == sz)
14+
break;
15+
if (i % 6 == 0) {
16+
printf(",\n ");
17+
} else {
18+
printf(", ");
19+
}
20+
}
21+
printf("\n};\n");
22+
}
23+
24+
/**
25+
* prints char array as a c program snippet
26+
*/
27+
void char_array_to_c(const char* ary, size_t sz, const char* name)
28+
{
29+
uint8_t tmp;
30+
size_t i = 0;
31+
32+
printf("static const uint8_t %s[%d] = {\n ", name, (int)sz);
33+
34+
for (;;) {
35+
if (ary[i] == 0) {
36+
printf("'\\0'");
37+
} else if (ary[i] == '\n') {
38+
printf("'\\n'");
39+
} else if (ary[i] == '\t') {
40+
printf("'\\t'");
41+
} else if (ary[i] == '\r') {
42+
printf("'\\r'");
43+
} else if (ary[i] == '\'') {
44+
printf("'\\''");
45+
} else if (ary[i] == '\\') {
46+
printf("'\\\\'");
47+
} else if (ary[i] < 32 || ary[i] > 126) {
48+
tmp = (uint8_t)ary[i];
49+
printf("0x%02x", tmp);
50+
} else {
51+
printf("'%c'", (char)ary[i]);
52+
}
53+
++i;
54+
if (i == sz)
55+
break;
56+
if (i % 10 == 0) {
57+
printf(",\n ");
58+
} else {
59+
printf(", ");
60+
}
61+
}
62+
printf("\n};\n");
63+
}
64+
65+
/**
66+
* prints an uint array as a c program snippet
67+
*/
68+
void uint32_array_to_c(const uint32_t* ary, size_t sz, const char* name)
69+
{
70+
size_t i = 0;
71+
72+
printf("static const uint32_t %s[%d] = {\n ", name, (int)sz);
73+
for (;;) {
74+
printf("%u", ary[i]);
75+
++i;
76+
if (i == sz)
77+
break;
78+
if (i % 12 == 0) {
79+
printf(",\n ");
80+
} else {
81+
printf(", ");
82+
}
83+
}
84+
printf("\n};\n");
85+
}

arraytoc.h

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#ifndef COM_MODP_STRINGENCODERS_ARRAYTOC
2+
#define COM_MODP_STRINGENCODERS_ARRAYTOC
3+
4+
#include "modp_stdint.h"
5+
6+
#ifdef __cplusplus
7+
#define BEGIN_C extern "C" {
8+
#define END_C }
9+
#else
10+
#define BEGIN_C
11+
#define END_C
12+
#endif
13+
14+
BEGIN_C
15+
16+
/** \brief output a uint32_t array into source code
17+
*
18+
*
19+
* \param[in] ary the input array
20+
* \param[in] size number of elements in array
21+
* \param[in] name the name of the struct for the source code
22+
*
23+
*/
24+
void uint32_array_to_c(const uint32_t* ary, size_t size, const char* name);
25+
26+
/** \brief output an uint32_t array into source code as hex values
27+
*
28+
* \param[in] ary the input array
29+
* \param[in] size number of elements in array
30+
* \param[in] name the name of the struct for source code
31+
*
32+
*/
33+
void uint32_array_to_c_hex(const uint32_t* ary, size_t size, const char* name);
34+
35+
/** \brief output a char array into source code
36+
*
37+
* \param[in] ary the input array
38+
* \param[in] size number of elements in array
39+
* \param[in] name the name of the struct for source code
40+
*/
41+
void char_array_to_c(const char* ary, size_t size, const char* name);
42+
43+
#endif

lib/resty/base_encoding.lua

+47
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
local error = error
22
local tostring = tostring
33
local type = type
4+
local ceil = math.ceil
45
local floor = math.floor
6+
local str_rep = string.rep
57
local base = require "resty.core.base"
68
local get_string_buf = base.get_string_buf
79
local ffi = require "ffi"
@@ -48,6 +50,8 @@ size_t modp_b16_encode(char* dest, const char* str, size_t len,
4850
size_t modp_b16_decode(char* dest, const char* src, size_t len);
4951
size_t modp_b2_encode(char* dest, const char* str, size_t len);
5052
size_t modp_b2_decode(char* dest, const char* str, size_t len);
53+
size_t modp_b85_encode(char* dest, const char* str, size_t len);
54+
size_t modp_b85_decode(char* dest, const char* str, size_t len);
5155
]])
5256

5357

@@ -291,4 +295,47 @@ function _M.decode_base2(s)
291295
end
292296

293297

298+
local function base85_encoded_length(len)
299+
return len / 4 * 5
300+
end
301+
302+
303+
function _M.encode_base85(s)
304+
s = check_encode_str(s)
305+
306+
local slen = #s
307+
if slen == 0 then
308+
return ""
309+
end
310+
311+
local dlen = base85_encoded_length(slen)
312+
local dst = get_string_buf(dlen)
313+
local r_dlen = encoding.modp_b85_encode(dst, s, slen)
314+
return ffi_string(dst, r_dlen)
315+
end
316+
317+
318+
local function base85_decoded_length(len)
319+
return ceil(len / 5) * 4
320+
end
321+
322+
323+
function _M.decode_base85(s)
324+
check_decode_str(s, 1)
325+
326+
local slen = #s
327+
if slen == 0 then
328+
return ""
329+
end
330+
331+
local dlen = base85_decoded_length(slen)
332+
local dst = get_string_buf(dlen)
333+
local r_dlen = encoding.modp_b85_decode(dst, s, slen)
334+
if r_dlen == -1 then
335+
return nil, "invalid input"
336+
end
337+
return ffi_string(dst, r_dlen)
338+
end
339+
340+
294341
return _M

0 commit comments

Comments
 (0)