ascii85_native 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/ascii85_native/ascii85_native.c +65 -48
- data/ext/ascii85_native/ascii85_native.h +14 -13
- data/lib/ascii85_native.rb +73 -19
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5fbe80d98b9dc9e8d4a04542b578609ce16839be238ad35dd238a001dc02aaa8
|
4
|
+
data.tar.gz: 817069f8f96a4b699f0e8f31bc66ece1f79b190678334dcad478aac0fa910590
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b6161b062e5a9641c394d31331a79f6fa4bf96d6fc9e65460f3025c71a0eb09fa5b43faf06f7e973920a0454e864672b2ce395a4afd621899ee95752627ebae
|
7
|
+
data.tar.gz: db9217c98eca4134c50c2d9a01f509dbbc089610165bc062ccbe54d347488b54a9269831d7f3fa8761bfb4e6662fa0dd98be93bfb16cb54e2fc98b39659d613c
|
@@ -1,77 +1,94 @@
|
|
1
|
-
//
|
2
|
-
//
|
3
|
-
// Ascii85 C++ implementation pulled from https://github.com/larskholte/a85
|
4
|
-
// Original C++ Code License: Copy and use as you please. No attribution necessary.
|
5
|
-
//
|
6
|
-
// Adapted to C language
|
1
|
+
// ascii85_native.c
|
7
2
|
|
3
|
+
#include "stdlib.h"
|
8
4
|
#include "ascii85_native.h"
|
9
5
|
|
10
|
-
int
|
11
|
-
return (
|
6
|
+
int a85_encoded_size(int input_length, bool append_null) {
|
7
|
+
return (input_length * 5 + 3) / 4 + !!append_null;
|
12
8
|
}
|
13
9
|
|
14
|
-
void
|
15
|
-
// Go to end of
|
16
|
-
|
17
|
-
|
10
|
+
void a85_encode(const u8* input, int input_length, char* output, bool append_null) {
|
11
|
+
// Go to end of input and output buffers
|
12
|
+
input += input_length;
|
13
|
+
output += a85_encoded_size(input_length,append_null);
|
18
14
|
// Append null if requested
|
19
15
|
if (append_null) {
|
20
|
-
*(--
|
16
|
+
*(--output) = 0;
|
21
17
|
}
|
22
18
|
// If number of bytes is not divisible by 4, act as if null bytes were added to end of buffer
|
23
|
-
int rem =
|
19
|
+
int rem = input_length & 3;
|
24
20
|
if (rem) {
|
25
21
|
u32 val = 0;
|
26
22
|
for (int i = 4 - rem; i < 4; i++) {
|
27
|
-
val |= *(--
|
23
|
+
val |= *(--input) << (8 * i);
|
28
24
|
}
|
29
25
|
int i;
|
30
26
|
for (i = 0; i < 4 - rem; i++) {
|
31
27
|
val /= 85;
|
32
28
|
}
|
33
29
|
for (; i <= 4; i++) {
|
34
|
-
*(--
|
30
|
+
*(--output) = val % 85 + 33;
|
35
31
|
val /= 85;
|
36
32
|
}
|
37
|
-
|
33
|
+
input_length &= ~3;
|
38
34
|
}
|
39
|
-
while (
|
35
|
+
while (input_length) {
|
40
36
|
// Process chunks of 4 bytes as 32-bit values
|
41
|
-
u32 val = *(--
|
42
|
-
val |= *(--
|
43
|
-
val |= *(--
|
44
|
-
val |= *(--
|
37
|
+
u32 val = *(--input);
|
38
|
+
val |= *(--input) << 8;
|
39
|
+
val |= *(--input) << 16;
|
40
|
+
val |= *(--input) << 24;
|
45
41
|
// Convert to base 85
|
46
|
-
*(--
|
42
|
+
*(--output) = val % 85 + 33;
|
47
43
|
val /= 85;
|
48
|
-
*(--
|
44
|
+
*(--output) = val % 85 + 33;
|
49
45
|
val /= 85;
|
50
|
-
*(--
|
46
|
+
*(--output) = val % 85 + 33;
|
51
47
|
val /= 85;
|
52
|
-
*(--
|
48
|
+
*(--output) = val % 85 + 33;
|
53
49
|
val /= 85;
|
54
|
-
*(--
|
55
|
-
|
50
|
+
*(--output) = val % 85 + 33;
|
51
|
+
input_length -= 4;
|
56
52
|
}
|
57
53
|
}
|
58
54
|
|
59
|
-
int
|
60
|
-
return (
|
55
|
+
int a85_decoded_size(int input_length) {
|
56
|
+
return ((input_length * 4) / 5);
|
61
57
|
}
|
62
58
|
|
63
|
-
void
|
64
|
-
|
59
|
+
void a85_filter_before_decode(const char* input, int input_length, char* output) {
|
60
|
+
int input_remaining = input_length;
|
61
|
+
while (input_remaining) {
|
62
|
+
if ( !(*input == 0 || (*input >= 10 && *input <= 13)) ) {
|
63
|
+
*output = *input;
|
64
|
+
output++;
|
65
|
+
}
|
66
|
+
input++;
|
67
|
+
input_remaining--;
|
68
|
+
}
|
69
|
+
//*output = '\0';
|
70
|
+
}
|
71
|
+
|
72
|
+
void a85_decode(const char* input, int input_length, u8* output) {
|
73
|
+
// this is now done from the ruby side
|
74
|
+
//char* filtered_input;
|
75
|
+
//filtered_input = (char*)malloc(input_length*sizeof(char));
|
76
|
+
//a85_filter_before_decode(input, input_length, filtered_input);
|
77
|
+
//int filtered_length = strlen(filtered_input);
|
78
|
+
|
79
|
+
while (input_length) {
|
80
|
+
|
81
|
+
if (*input == 0) { break; }
|
65
82
|
|
66
|
-
|
83
|
+
if (*input >= 10 && *input <= 13) { input++; input_length--; continue; }
|
67
84
|
|
68
|
-
if (
|
85
|
+
if (input_length < 5) {
|
69
86
|
// Determine represented value in base 85
|
70
87
|
u32 val = 0;
|
71
88
|
int factor = 52200625; // 85^4
|
72
89
|
int i;
|
73
|
-
for (i = 0; i <
|
74
|
-
val += (*(
|
90
|
+
for (i = 0; i < input_length; i++) {
|
91
|
+
val += (*(input++) - 33) * factor;
|
75
92
|
factor /= 85;
|
76
93
|
}
|
77
94
|
for (; i < 5; i++) {
|
@@ -79,25 +96,25 @@ void from_a85(const char* text, int textlen, u8* data) {
|
|
79
96
|
factor /= 85;
|
80
97
|
}
|
81
98
|
int shift = 24;
|
82
|
-
for (i = 0; i <
|
83
|
-
*(
|
99
|
+
for (i = 0; i < input_length - 1; i++) {
|
100
|
+
*(output++) = val >> shift;
|
84
101
|
shift -= 8;
|
85
102
|
}
|
86
103
|
break;
|
87
104
|
}
|
88
105
|
|
89
106
|
// Determine represented value in base 85
|
90
|
-
u32 val = (*(
|
91
|
-
val += (*(
|
92
|
-
val += (*(
|
93
|
-
val += (*(
|
94
|
-
val += (*(
|
107
|
+
u32 val = (*(input++) - 33) * 52200625; // 85^4
|
108
|
+
val += (*(input++) - 33) * 614125; // 85^3
|
109
|
+
val += (*(input++) - 33) * 7225; // 85^2
|
110
|
+
val += (*(input++) - 33) * 85; // 85^1
|
111
|
+
val += (*(input++) - 33); // 85^0
|
95
112
|
|
96
113
|
// Write out in big-endian order
|
97
|
-
*(
|
98
|
-
*(
|
99
|
-
*(
|
100
|
-
*(
|
101
|
-
|
114
|
+
*(output++) = val >> 24;
|
115
|
+
*(output++) = val >> 16;
|
116
|
+
*(output++) = val >> 8;
|
117
|
+
*(output++) = val;
|
118
|
+
input_length -= 5;
|
102
119
|
}
|
103
120
|
}
|
@@ -1,9 +1,4 @@
|
|
1
|
-
//
|
2
|
-
//
|
3
|
-
// Ascii85 C++ implementation pulled from https://github.com/larskholte/a85
|
4
|
-
// Original C++ Code License: Copy and use as you please. No attribution necessary.
|
5
|
-
//
|
6
|
-
// Adapted to C language
|
1
|
+
// ascii85_native.h
|
7
2
|
|
8
3
|
#include <stdint.h>
|
9
4
|
|
@@ -11,17 +6,23 @@ typedef _Bool bool;
|
|
11
6
|
typedef uint8_t u8;
|
12
7
|
typedef uint32_t u32;
|
13
8
|
|
14
|
-
// Returns size of buffer required for
|
15
|
-
int
|
9
|
+
// Returns size of char buffer required for output of a85_encode().
|
10
|
+
int a85_encoded_size(int input_length, bool append_null);
|
16
11
|
|
17
12
|
// Translates the given binary data of the given size to Ascii85.
|
18
13
|
// Can translate in-place.
|
19
14
|
// Optionally appends a null character.
|
20
|
-
void
|
15
|
+
void a85_encode(const u8* input, int input_length, char* output, bool append_null);
|
21
16
|
|
22
|
-
// Returns the size of buffer required for
|
23
|
-
|
17
|
+
// Returns the size of u8 buffer required for the output of a85_decode().
|
18
|
+
// In reality, the number of decoded characters could be far less due to
|
19
|
+
// ignored characters being thrown out (see a85_filter_before_decode())
|
20
|
+
int a85_decoded_size(int input_length);
|
24
21
|
|
25
|
-
// Translates the given Ascii85
|
22
|
+
// Translates the given Ascii85 input to binary output.
|
26
23
|
// Can translate in-place.
|
27
|
-
void
|
24
|
+
void a85_decode(const char* input, int input_length, u8* output);
|
25
|
+
|
26
|
+
// Removes unused / ignored characters from the ascii85 input
|
27
|
+
// TODO: identify and remove <~ and ~> delimiters
|
28
|
+
void a85_filter_before_decode(const char* input, int input_length, char* output);
|
data/lib/ascii85_native.rb
CHANGED
@@ -5,23 +5,28 @@ require 'ffi'
|
|
5
5
|
module Ascii85Native
|
6
6
|
extend FFI::Library
|
7
7
|
|
8
|
+
ffi_lib 'c'
|
8
9
|
ffi_lib File.join(File.dirname(__FILE__), 'ascii85_native.so')
|
9
10
|
|
10
|
-
#void
|
11
|
-
attach_function :
|
11
|
+
#void a85_encode(const u8* data, int binlen, char* text, bool append_null);
|
12
|
+
attach_function :a85_encode, [:buffer_in, :int, :buffer_out, :bool], :void
|
12
13
|
|
13
|
-
#int
|
14
|
-
attach_function :
|
14
|
+
#int a85_encoded_size(int binlen, bool append_null);
|
15
|
+
attach_function :a85_encoded_size, [:int, :bool], :int
|
15
16
|
|
16
|
-
#
|
17
|
-
attach_function :
|
17
|
+
#int a85_decoded_size(int textlen)
|
18
|
+
attach_function :a85_decoded_size, [:int], :int
|
18
19
|
|
19
|
-
#
|
20
|
-
attach_function :
|
20
|
+
#void a85_decode(const char* text, int textlen, u8* data);
|
21
|
+
attach_function :a85_filter_before_decode, [:buffer_in, :int, :buffer_out], :void
|
21
22
|
|
23
|
+
#void a85_decode(const char* text, int textlen, u8* data);
|
24
|
+
attach_function :a85_decode, [:buffer_in, :int, :buffer_out], :void
|
25
|
+
|
26
|
+
attach_function :strlen, [:string], :int
|
22
27
|
|
23
28
|
def self.encode(input, include_delimiter=false)
|
24
|
-
if input.nil?
|
29
|
+
if input.nil? || input.size == 0
|
25
30
|
return '<~~>' if include_delimiter
|
26
31
|
return ''
|
27
32
|
end
|
@@ -35,10 +40,10 @@ module Ascii85Native
|
|
35
40
|
|
36
41
|
FFI::MemoryPointer.new(:uint8, input_data.size) do |in_uint8|
|
37
42
|
in_uint8.write_array_of_type(FFI::TYPE_UINT8, :put_uint8, input_data)
|
38
|
-
out_size = self.
|
43
|
+
out_size = self.a85_encoded_size(input_data.size, true)
|
39
44
|
|
40
45
|
FFI::MemoryPointer.new(:uint8, out_size) do |output|
|
41
|
-
self.
|
46
|
+
self.a85_encode(in_uint8, input_data.size, output, true)
|
42
47
|
if include_delimiter
|
43
48
|
return '<~' + (output.read_string() || '') + '~>'
|
44
49
|
else
|
@@ -49,21 +54,70 @@ module Ascii85Native
|
|
49
54
|
end
|
50
55
|
|
51
56
|
|
52
|
-
def self.decode(input)
|
53
|
-
return "" if input.nil?
|
57
|
+
def self.decode(input, force_delimiter=true)
|
58
|
+
return "" if input.nil? || input.size == 0
|
54
59
|
|
55
|
-
if
|
60
|
+
if force_delimiter
|
56
61
|
input = input[2..-3]
|
62
|
+
else
|
63
|
+
start_slice = find_start_slice(input)
|
64
|
+
end_slice = find_end_slice(input)
|
65
|
+
input = input[start_slice..end_slice] if start_slice != 0 || end_slice != -1
|
57
66
|
end
|
58
67
|
|
59
68
|
FFI::MemoryPointer.new(:char, input.size) do |in_char|
|
60
|
-
|
61
|
-
|
69
|
+
FFI::MemoryPointer.new(:char, input.size) do |filtered_char|
|
70
|
+
in_char.write_string(input)
|
62
71
|
|
63
|
-
|
64
|
-
self.
|
65
|
-
|
72
|
+
self.a85_filter_before_decode(in_char, input.size, filtered_char)
|
73
|
+
filtered_length = self.strlen(filtered_char.read_string())
|
74
|
+
puts "filtered_length: #{filtered_length}"
|
75
|
+
|
76
|
+
out_size = self.a85_decoded_size(filtered_length)
|
77
|
+
|
78
|
+
FFI::MemoryPointer.new(:uint8, out_size) do |output|
|
79
|
+
self.a85_decode(filtered_char, filtered_length, output)
|
80
|
+
return output.read_string()
|
81
|
+
end
|
66
82
|
end
|
67
83
|
end
|
68
84
|
end
|
85
|
+
|
86
|
+
def self.find_start_slice(input)
|
87
|
+
start_slice = 0
|
88
|
+
cursor = 0
|
89
|
+
|
90
|
+
input.size.times do |i|
|
91
|
+
if ['\n', '\r', ' '].include?(input[cursor])
|
92
|
+
cursor += 1
|
93
|
+
next
|
94
|
+
elsif input[cursor] == '<' && input[cursor+1] == '~'
|
95
|
+
start_slice = cursor + 2
|
96
|
+
break
|
97
|
+
else
|
98
|
+
break # input is not delimited
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
return start_slice
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.find_end_slice(input)
|
106
|
+
end_slice = -1
|
107
|
+
cursor = -1
|
108
|
+
|
109
|
+
input.size.times do |i|
|
110
|
+
if ['\n', '\r', ' '].include?(input[cursor])
|
111
|
+
cursor -= 1
|
112
|
+
next
|
113
|
+
elsif input[cursor] == '>' && input[cursor-1] == '~'
|
114
|
+
end_slice = cursor - 2
|
115
|
+
break
|
116
|
+
else
|
117
|
+
break # input is not delimited
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
return end_slice
|
122
|
+
end
|
69
123
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ascii85_native
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jason Crossfield
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-06-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|
@@ -82,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
82
82
|
- !ruby/object:Gem::Version
|
83
83
|
version: '0'
|
84
84
|
requirements: []
|
85
|
-
rubygems_version: 3.
|
85
|
+
rubygems_version: 3.2.15
|
86
86
|
signing_key:
|
87
87
|
specification_version: 4
|
88
88
|
summary: Ascii85 Encoder / Decoder with Native C Extensions
|