1 |
|
package io.sunshower.encodings; |
2 |
|
|
3 |
|
import java.io.IOException; |
4 |
|
import java.io.OutputStream; |
5 |
|
import java.util.Arrays; |
6 |
|
import java.util.BitSet; |
7 |
|
|
|
|
| 62.1% |
Uncovered Elements: 58 (153) |
Complexity: 43 |
Complexity Density: 0.47 |
|
8 |
|
public class Base58 implements Encoding { |
9 |
|
|
10 |
|
private final char zero; |
11 |
|
private final char[] alphabet; |
12 |
|
|
|
|
| 50% |
Uncovered Elements: 2 (4) |
Complexity: 2 |
Complexity Density: 1 |
|
13 |
|
public enum Alphabets { |
14 |
|
Default("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"), |
15 |
|
Ripple("rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"), |
16 |
|
Flickr("123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"); |
17 |
|
|
18 |
|
final char[] data; |
19 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
20 |
3 |
Alphabets(String input) {... |
21 |
3 |
this.data = input.toCharArray(); |
22 |
|
} |
23 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
24 |
0 |
public char[] getAlphabet() {... |
25 |
0 |
return Arrays.copyOf(data, data.length); |
26 |
|
} |
27 |
|
} |
28 |
|
|
29 |
|
final int[] indexes; |
30 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
31 |
11 |
private Base58(Alphabets alphabet) {... |
32 |
11 |
this(alphabet.data); |
33 |
|
} |
34 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (8) |
Complexity: 2 |
Complexity Density: 0.33 |
|
35 |
11 |
private Base58(char[] alphabet) {... |
36 |
11 |
this.alphabet = alphabet; |
37 |
11 |
this.zero = alphabet[0]; |
38 |
11 |
indexes = new int[128]; |
39 |
11 |
Arrays.fill(indexes, -1); |
40 |
649 |
for (int i = 0; i < alphabet.length; i++) { |
41 |
638 |
indexes[alphabet[i]] = i; |
42 |
|
} |
43 |
|
} |
44 |
|
|
|
|
| 0% |
Uncovered Elements: 9 (9) |
Complexity: 2 |
Complexity Density: 0.29 |
|
45 |
0 |
@Override... |
46 |
|
public boolean test(byte[] input) { |
47 |
0 |
final BitSet fst = new BitSet(); |
48 |
0 |
for (char b : alphabet) { |
49 |
0 |
fst.set(b); |
50 |
|
} |
51 |
|
|
52 |
0 |
for (byte b : input) { |
53 |
0 |
if (!fst.get(b)) { |
54 |
0 |
return false; |
55 |
|
} |
56 |
|
} |
57 |
0 |
return true; |
58 |
|
} |
59 |
|
|
|
|
| 81.8% |
Uncovered Elements: 2 (11) |
Complexity: 3 |
Complexity Density: 0.43 |
|
60 |
200003 |
@Override... |
61 |
|
public boolean test(String input) { |
62 |
|
|
63 |
200003 |
final BitSet fst = new BitSet(); |
64 |
200003 |
for (char b : alphabet) { |
65 |
11600174 |
fst.set(b); |
66 |
|
} |
67 |
|
|
68 |
4397281 |
for (int i = 0; i < input.length(); i++) { |
69 |
4197278 |
if (!fst.get(input.charAt(i))) { |
70 |
0 |
return false; |
71 |
|
} |
72 |
|
} |
73 |
200003 |
return true; |
74 |
|
} |
75 |
|
|
|
|
| 0% |
Uncovered Elements: 35 (35) |
Complexity: 11 |
Complexity Density: 0.52 |
|
76 |
0 |
@Override... |
77 |
|
public void encode(byte[] input, OutputStream os) throws IOException { |
78 |
0 |
int length = input.length; |
79 |
0 |
int zeros = 0, i, j, carry; |
80 |
0 |
while (zeros < length && input[zeros] == 0) { |
81 |
0 |
zeros++; |
82 |
|
} |
83 |
|
|
84 |
0 |
int size = (length - zeros) * 138 / 100 + 1; |
85 |
|
|
86 |
0 |
byte[] result = new byte[size]; |
87 |
|
|
88 |
0 |
int max = size - 1; |
89 |
|
|
90 |
0 |
for (i = zeros; i < length; i++) { |
91 |
0 |
j = size - 1; |
92 |
0 |
for (carry = input[i]; j > max || carry != 0; j--) { |
93 |
0 |
carry = carry + 256 * input[j]; |
94 |
0 |
result[j] = (byte) (carry % 58); |
95 |
0 |
carry /= 58; |
96 |
|
} |
97 |
0 |
max = j; |
98 |
|
} |
99 |
|
|
100 |
0 |
for (j = 0; j < size && result[j] == 0; j++) ; |
101 |
|
|
102 |
0 |
if (zeros != 0) { |
103 |
0 |
for (i = 0; i < zeros; i++) { |
104 |
0 |
os.write(zero); |
105 |
|
} |
106 |
|
} |
107 |
|
|
108 |
0 |
for (i = zeros; j < size; i++) { |
109 |
0 |
os.write(alphabet[result[j++]]); |
110 |
|
} |
111 |
|
} |
112 |
|
|
|
|
| 86.7% |
Uncovered Elements: 4 (30) |
Complexity: 9 |
Complexity Density: 0.5 |
|
113 |
300116 |
@Override... |
114 |
|
public String encode(byte[] in) { |
115 |
|
|
116 |
300116 |
byte[] input = Arrays.copyOf(in, in.length); |
117 |
|
|
118 |
300116 |
int length = input.length; |
119 |
|
|
120 |
300116 |
if (length == 0) { |
121 |
0 |
return ""; |
122 |
|
} |
123 |
|
|
124 |
300116 |
int zeros = 0; |
125 |
700544 |
while (zeros < length && input[zeros] == 0) { |
126 |
400428 |
zeros++; |
127 |
|
} |
128 |
|
|
129 |
300116 |
final char[] encoded = new char[input.length * 2]; |
130 |
|
|
131 |
300116 |
int output = encoded.length; |
132 |
|
|
133 |
6102114 |
for (int start = zeros; start < length; ) { |
134 |
5801998 |
encoded[--output] = alphabet[mod(input, start, 256, 58)]; |
135 |
5801998 |
if (input[start] == 0) { |
136 |
4403414 |
++start; |
137 |
|
} |
138 |
|
} |
139 |
|
|
140 |
300116 |
while (output < encoded.length && encoded[output] == 0) { |
141 |
0 |
++output; |
142 |
|
} |
143 |
|
|
144 |
700544 |
while (--zeros >= 0) { |
145 |
400428 |
encoded[--output] = zero; |
146 |
|
} |
147 |
|
|
148 |
300116 |
return new String(encoded, output, encoded.length - output); |
149 |
|
} |
150 |
|
|
|
|
| 84.2% |
Uncovered Elements: 6 (38) |
Complexity: 11 |
Complexity Density: 0.5 |
|
151 |
500116 |
@Override... |
152 |
|
public byte[] decode(String input) { |
153 |
500116 |
int length = input.length(); |
154 |
500116 |
if (length == 0) { |
155 |
0 |
return new byte[0]; |
156 |
|
} |
157 |
|
|
158 |
500116 |
byte[] bytes = new byte[length]; |
159 |
|
|
160 |
10899793 |
for (int i = 0; i < length; i++) { |
161 |
10399677 |
char ch = input.charAt(i); |
162 |
10399677 |
int digit = ch < 128 ? indexes[ch] : -1; |
163 |
|
|
164 |
10399677 |
if (digit < 0) { |
165 |
0 |
throw new IllegalArgumentException( |
166 |
|
String.format("Unexpected character '%c' at index %d", ch, i)); |
167 |
|
} |
168 |
|
|
169 |
10399677 |
bytes[i] = (byte) digit; |
170 |
|
} |
171 |
|
|
172 |
500116 |
int zeros = 0; |
173 |
1100948 |
while (zeros < length && bytes[zeros] == 0) { |
174 |
600832 |
++zeros; |
175 |
|
} |
176 |
|
|
177 |
500116 |
byte[] decoded = new byte[length]; |
178 |
|
|
179 |
500116 |
int start = length; |
180 |
|
|
181 |
10298961 |
for (int istart = zeros; istart < length; ) { |
182 |
9798845 |
decoded[--start] = mod(bytes, istart, 58, 256); |
183 |
9798845 |
if (bytes[istart] == 0) { |
184 |
9798845 |
++istart; |
185 |
|
} |
186 |
|
} |
187 |
|
|
188 |
2895929 |
while (start < length && decoded[start] == 0) { |
189 |
2395813 |
++start; |
190 |
|
} |
191 |
|
|
192 |
500116 |
return Arrays.copyOfRange(decoded, start - zeros, length); |
193 |
|
} |
194 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
195 |
100 |
@Override... |
196 |
|
public String encode(String input) { |
197 |
100 |
return encode(input.getBytes()); |
198 |
|
} |
199 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (9) |
Complexity: 2 |
Complexity Density: 0.29 |
|
200 |
15600843 |
static byte mod(byte[] d, int fst, int base, int divisor) {... |
201 |
15600843 |
int rem = 0; |
202 |
163168648 |
for (int i = fst; i < d.length; i++) { |
203 |
147567805 |
int digit = (int) d[i] & 0xFF; |
204 |
147567805 |
int t = rem * base + digit; |
205 |
147567805 |
d[i] = (byte) (t / divisor); |
206 |
147567805 |
rem = t % divisor; |
207 |
|
} |
208 |
15600843 |
return (byte) rem; |
209 |
|
} |
210 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
211 |
11 |
public static Encoding getInstance(Alphabets alphabet) {... |
212 |
11 |
return new Base58(alphabet); |
213 |
|
} |
214 |
|
} |