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 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