ascii85_native 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 29b779e3fe160aeafcecd06d79f661f9a4b0a992dd053af39515eacfa7e2f367
4
- data.tar.gz: bbc6085d316adaea46f93095dbf738aea1441fb682c32736152c0674c33f7df2
3
+ metadata.gz: 5fbe80d98b9dc9e8d4a04542b578609ce16839be238ad35dd238a001dc02aaa8
4
+ data.tar.gz: 817069f8f96a4b699f0e8f31bc66ece1f79b190678334dcad478aac0fa910590
5
5
  SHA512:
6
- metadata.gz: 0a4267955d024d17a5a540961e583bb498c4c70eddc9073d680925e3a8b9c10aeaed73a9ea07dbef6455c6dec62d308c61e465739312e67c5ff575f75de3bc4e
7
- data.tar.gz: af7a04720ee115222ad4897af241ee305486bc2494aa9925acdddaefcb10aa8c5be8bcc723e92818237c04385207137a678cef777a8362dd8b7b9dff8db9c359
6
+ metadata.gz: 4b6161b062e5a9641c394d31331a79f6fa4bf96d6fc9e65460f3025c71a0eb09fa5b43faf06f7e973920a0454e864672b2ce395a4afd621899ee95752627ebae
7
+ data.tar.gz: db9217c98eca4134c50c2d9a01f509dbbc089610165bc062ccbe54d347488b54a9269831d7f3fa8761bfb4e6662fa0dd98be93bfb16cb54e2fc98b39659d613c
@@ -1,77 +1,94 @@
1
- // a85.cpp
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 size_for_a85(int binlen, bool append_null) {
11
- return (binlen * 5 + 3) / 4 + !!append_null;
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 to_a85(const u8* data, int binlen, char* text, bool append_null) {
15
- // Go to end of data and text buffers
16
- data += binlen;
17
- text += size_for_a85(binlen,append_null);
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
- *(--text) = 0;
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 = binlen & 3;
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 |= *(--data) << (8 * i);
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
- *(--text) = val % 85 + 33;
30
+ *(--output) = val % 85 + 33;
35
31
  val /= 85;
36
32
  }
37
- binlen &= ~3;
33
+ input_length &= ~3;
38
34
  }
39
- while (binlen) {
35
+ while (input_length) {
40
36
  // Process chunks of 4 bytes as 32-bit values
41
- u32 val = *(--data);
42
- val |= *(--data) << 8;
43
- val |= *(--data) << 16;
44
- val |= *(--data) << 24;
37
+ u32 val = *(--input);
38
+ val |= *(--input) << 8;
39
+ val |= *(--input) << 16;
40
+ val |= *(--input) << 24;
45
41
  // Convert to base 85
46
- *(--text) = val % 85 + 33;
42
+ *(--output) = val % 85 + 33;
47
43
  val /= 85;
48
- *(--text) = val % 85 + 33;
44
+ *(--output) = val % 85 + 33;
49
45
  val /= 85;
50
- *(--text) = val % 85 + 33;
46
+ *(--output) = val % 85 + 33;
51
47
  val /= 85;
52
- *(--text) = val % 85 + 33;
48
+ *(--output) = val % 85 + 33;
53
49
  val /= 85;
54
- *(--text) = val % 85 + 33;
55
- binlen -= 4;
50
+ *(--output) = val % 85 + 33;
51
+ input_length -= 4;
56
52
  }
57
53
  }
58
54
 
59
- int size_for_bin(int textlen) {
60
- return (textlen * 4) / 5;
55
+ int a85_decoded_size(int input_length) {
56
+ return ((input_length * 4) / 5);
61
57
  }
62
58
 
63
- void from_a85(const char* text, int textlen, u8* data) {
64
- while (textlen) {
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
- while (*text == 0 || (*text >= 10 && *text <= 13)) { text++; textlen--; }
83
+ if (*input >= 10 && *input <= 13) { input++; input_length--; continue; }
67
84
 
68
- if (textlen < 5) {
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 < textlen; i++) {
74
- val += (*(text++) - 33) * factor;
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 < textlen - 1; i++) {
83
- *(data++) = val >> shift;
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 = (*(text++) - 33) * 52200625; // 85^4
91
- val += (*(text++) - 33) * 614125; // 85^3
92
- val += (*(text++) - 33) * 7225; // 85^2
93
- val += (*(text++) - 33) * 85; // 85^1
94
- val += (*(text++) - 33); // 85^0
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
- *(data++) = val >> 24;
98
- *(data++) = val >> 16;
99
- *(data++) = val >> 8;
100
- *(data++) = val;
101
- textlen -= 5;
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
- // a85.h
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 to_a85 function.
15
- int size_for_a85(int binlen, bool append_null);
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 to_a85(const u8* data, int binlen, char* text, bool append_null);
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 from_a85 function.
23
- int size_for_bin(int textlen);
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 text to binary data.
22
+ // Translates the given Ascii85 input to binary output.
26
23
  // Can translate in-place.
27
- void from_a85(const char* text, int textlen, u8* data);
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);
@@ -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 to_a85(const u8* data, int binlen, char* text, bool append_null);
11
- attach_function :to_a85, [:buffer_in, :int, :buffer_out, :bool], :void
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 size_for_a85(int binlen, bool append_null);
14
- attach_function :size_for_a85, [:int, :bool], :int
14
+ #int a85_encoded_size(int binlen, bool append_null);
15
+ attach_function :a85_encoded_size, [:int, :bool], :int
15
16
 
16
- #void from_a85(const char* text, int textlen, u8* data);
17
- attach_function :from_a85, [:buffer_in, :int, :buffer_out], :void
17
+ #int a85_decoded_size(int textlen)
18
+ attach_function :a85_decoded_size, [:int], :int
18
19
 
19
- #int size_for_bin(int textlen)
20
- attach_function :size_for_bin, [:int], :int
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.size_for_a85(input_data.size, true)
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.to_a85(in_uint8, input_data.size, output, true)
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 input[0] == '<' && input[1] == '~' && input[-2] == '~' && input[-1] == '>'
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
- in_char.write_string(input)
61
- out_size = self.size_for_bin(input.size)
69
+ FFI::MemoryPointer.new(:char, input.size) do |filtered_char|
70
+ in_char.write_string(input)
62
71
 
63
- FFI::MemoryPointer.new(:uint8, out_size) do |output|
64
- self.from_a85(in_char, input.size, output)
65
- return output.read_string()
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.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-05-05 00:00:00.000000000 Z
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.1.2
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