1 | package com.jsql.util.bruter; | |
2 | ||
3 | import java.nio.charset.StandardCharsets; | |
4 | import java.util.Arrays; | |
5 | ||
6 | public class Base58 { | |
7 | ||
8 | private static final char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray(); | |
9 | private static final int BASE_58 = ALPHABET.length; | |
10 | private static final int BASE_256 = 256; | |
11 | ||
12 | private static final int[] INDEXES = new int[128]; | |
13 | | |
14 | static { | |
15 | Arrays.fill(INDEXES, -1); | |
16 | | |
17 | for (int i = 0; i < ALPHABET.length; i++) { | |
18 | INDEXES[ALPHABET[i]] = i; | |
19 | } | |
20 | } | |
21 | ||
22 | private Base58() { | |
23 | // Utility class | |
24 | } | |
25 | ||
26 | public static String encode(byte[] input) { | |
27 | | |
28 |
1
1. encode : negated conditional → KILLED |
if (input.length == 0) { |
29 | // paying with the same coin | |
30 | return ""; | |
31 | } | |
32 | ||
33 | // Make a copy of the input since we are going to modify it. | |
34 | byte[] copyInput = copyOfRange(input, 0, input.length); | |
35 | ||
36 | // Count leading zeroes | |
37 | var zeroCount = 0; | |
38 |
3
1. encode : negated conditional → SURVIVED 2. encode : changed conditional boundary → SURVIVED 3. encode : negated conditional → KILLED |
while (zeroCount < copyInput.length && copyInput[zeroCount] == 0) { |
39 | ++zeroCount; | |
40 | } | |
41 | ||
42 | // The actual encoding | |
43 |
1
1. encode : Replaced integer multiplication with division → KILLED |
var temp = new byte[copyInput.length * 2]; |
44 | int j = temp.length; | |
45 | ||
46 | int startAt = zeroCount; | |
47 |
2
1. encode : negated conditional → KILLED 2. encode : changed conditional boundary → KILLED |
while (startAt < copyInput.length) { |
48 | | |
49 | byte mod = divmod58(copyInput, startAt); | |
50 |
1
1. encode : negated conditional → KILLED |
if (copyInput[startAt] == 0) { |
51 |
1
1. encode : Changed increment from 1 to -1 → KILLED |
++startAt; |
52 | } | |
53 | ||
54 |
1
1. encode : Changed increment from -1 to 1 → KILLED |
temp[--j] = (byte) ALPHABET[mod]; |
55 | } | |
56 | ||
57 | // Strip extra '1' if any | |
58 |
3
1. encode : changed conditional boundary → SURVIVED 2. encode : negated conditional → SURVIVED 3. encode : negated conditional → KILLED |
while (j < temp.length && temp[j] == ALPHABET[0]) { |
59 | ++j; | |
60 | } | |
61 | ||
62 | // Add as many leading '1' as there were leading zeros. | |
63 |
3
1. encode : changed conditional boundary → SURVIVED 2. encode : Changed increment from -1 to 1 → KILLED 3. encode : negated conditional → KILLED |
while (--zeroCount >= 0) { |
64 |
1
1. encode : Changed increment from -1 to 1 → NO_COVERAGE |
temp[--j] = (byte) ALPHABET[0]; |
65 | } | |
66 | ||
67 | byte[] output = copyOfRange(temp, j, temp.length); | |
68 | | |
69 |
1
1. encode : replaced return value with "" for com/jsql/util/bruter/Base58::encode → KILLED |
return new String(output, StandardCharsets.UTF_8); |
70 | } | |
71 | ||
72 | public static byte[] decode(String input) { | |
73 | | |
74 |
1
1. decode : negated conditional → KILLED |
if (input.isEmpty()) { |
75 | // paying with the same coin | |
76 |
1
1. decode : replaced return value with null for com/jsql/util/bruter/Base58::decode → NO_COVERAGE |
return new byte[0]; |
77 | } | |
78 | ||
79 | var input58 = new byte[input.length()]; | |
80 | | |
81 | // Transform the String to a base58 byte sequence | |
82 |
2
1. decode : changed conditional boundary → KILLED 2. decode : negated conditional → KILLED |
for (var i = 0; i < input.length(); ++i) { |
83 | | |
84 | var c = input.charAt(i); | |
85 | ||
86 | int digit58 = -1; | |
87 |
4
1. decode : changed conditional boundary → SURVIVED 2. decode : changed conditional boundary → SURVIVED 3. decode : negated conditional → KILLED 4. decode : negated conditional → KILLED |
if (c >= 0 && c < 128) { |
88 | digit58 = INDEXES[c]; | |
89 | } | |
90 | | |
91 |
2
1. decode : negated conditional → KILLED 2. decode : changed conditional boundary → KILLED |
if (digit58 < 0) { |
92 | throw new IllegalArgumentException("Not a Base58 input: " + input); | |
93 | } | |
94 | ||
95 | input58[i] = (byte) digit58; | |
96 | } | |
97 | ||
98 | // Count leading zeroes | |
99 | var zeroCount = 0; | |
100 |
3
1. decode : negated conditional → SURVIVED 2. decode : changed conditional boundary → SURVIVED 3. decode : negated conditional → KILLED |
while (zeroCount < input58.length && input58[zeroCount] == 0) { |
101 | ++zeroCount; | |
102 | } | |
103 | ||
104 | // The encoding | |
105 | var temp = new byte[input.length()]; | |
106 | int j = temp.length; | |
107 | ||
108 | int startAt = zeroCount; | |
109 |
2
1. decode : changed conditional boundary → KILLED 2. decode : negated conditional → KILLED |
while (startAt < input58.length) { |
110 | | |
111 | byte mod = divmod256(input58, startAt); | |
112 |
1
1. decode : negated conditional → KILLED |
if (input58[startAt] == 0) { |
113 |
1
1. decode : Changed increment from 1 to -1 → KILLED |
++startAt; |
114 | } | |
115 | ||
116 |
1
1. decode : Changed increment from -1 to 1 → KILLED |
temp[--j] = mod; |
117 | } | |
118 | ||
119 | // Do no add extra leading zeroes, move j to first non null byte. | |
120 |
3
1. decode : changed conditional boundary → SURVIVED 2. decode : negated conditional → KILLED 3. decode : negated conditional → KILLED |
while (j < temp.length && temp[j] == 0) { |
121 | ++j; | |
122 | } | |
123 | ||
124 |
2
1. decode : Replaced integer subtraction with addition → SURVIVED 2. decode : replaced return value with null for com/jsql/util/bruter/Base58::decode → KILLED |
return copyOfRange(temp, j - zeroCount, temp.length); |
125 | } | |
126 | ||
127 | private static byte divmod58(byte[] number, int startAt) { | |
128 | | |
129 | var remainder = 0; | |
130 |
2
1. divmod58 : changed conditional boundary → KILLED 2. divmod58 : negated conditional → KILLED |
for (int i = startAt; i < number.length; i++) { |
131 | | |
132 |
1
1. divmod58 : Replaced bitwise AND with OR → KILLED |
int digit256 = number[i] & 0xFF; |
133 |
2
1. divmod58 : Replaced integer multiplication with division → KILLED 2. divmod58 : Replaced integer addition with subtraction → KILLED |
int temp = remainder * BASE_256 + digit256; |
134 | ||
135 |
1
1. divmod58 : Replaced integer division with multiplication → KILLED |
number[i] = (byte) (temp / BASE_58); |
136 | ||
137 |
1
1. divmod58 : Replaced integer modulus with multiplication → KILLED |
remainder = temp % BASE_58; |
138 | } | |
139 | ||
140 |
1
1. divmod58 : replaced byte return with 0 for com/jsql/util/bruter/Base58::divmod58 → KILLED |
return (byte) remainder; |
141 | } | |
142 | ||
143 | private static byte divmod256(byte[] number58, int startAt) { | |
144 | | |
145 | var remainder = 0; | |
146 |
2
1. divmod256 : negated conditional → KILLED 2. divmod256 : changed conditional boundary → KILLED |
for (int i = startAt; i < number58.length; i++) { |
147 | | |
148 |
1
1. divmod256 : Replaced bitwise AND with OR → KILLED |
int digit58 = number58[i] & 0xFF; |
149 |
2
1. divmod256 : Replaced integer multiplication with division → KILLED 2. divmod256 : Replaced integer addition with subtraction → KILLED |
int temp = remainder * BASE_58 + digit58; |
150 | ||
151 |
1
1. divmod256 : Replaced integer division with multiplication → KILLED |
number58[i] = (byte) (temp / BASE_256); |
152 | ||
153 |
1
1. divmod256 : Replaced integer modulus with multiplication → KILLED |
remainder = temp % BASE_256; |
154 | } | |
155 | ||
156 |
1
1. divmod256 : replaced byte return with 0 for com/jsql/util/bruter/Base58::divmod256 → KILLED |
return (byte) remainder; |
157 | } | |
158 | ||
159 | private static byte[] copyOfRange(byte[] source, int from, int to) { | |
160 | | |
161 |
1
1. copyOfRange : Replaced integer subtraction with addition → KILLED |
var range = new byte[to - from]; |
162 |
1
1. copyOfRange : removed call to java/lang/System::arraycopy → KILLED |
System.arraycopy(source, from, range, 0, range.length); |
163 | ||
164 |
1
1. copyOfRange : replaced return value with null for com/jsql/util/bruter/Base58::copyOfRange → KILLED |
return range; |
165 | } | |
166 | } | |
Mutations | ||
28 |
1.1 |
|
38 |
1.1 2.2 3.3 |
|
43 |
1.1 |
|
47 |
1.1 2.2 |
|
50 |
1.1 |
|
51 |
1.1 |
|
54 |
1.1 |
|
58 |
1.1 2.2 3.3 |
|
63 |
1.1 2.2 3.3 |
|
64 |
1.1 |
|
69 |
1.1 |
|
74 |
1.1 |
|
76 |
1.1 |
|
82 |
1.1 2.2 |
|
87 |
1.1 2.2 3.3 4.4 |
|
91 |
1.1 2.2 |
|
100 |
1.1 2.2 3.3 |
|
109 |
1.1 2.2 |
|
112 |
1.1 |
|
113 |
1.1 |
|
116 |
1.1 |
|
120 |
1.1 2.2 3.3 |
|
124 |
1.1 2.2 |
|
130 |
1.1 2.2 |
|
132 |
1.1 |
|
133 |
1.1 2.2 |
|
135 |
1.1 |
|
137 |
1.1 |
|
140 |
1.1 |
|
146 |
1.1 2.2 |
|
148 |
1.1 |
|
149 |
1.1 2.2 |
|
151 |
1.1 |
|
153 |
1.1 |
|
156 |
1.1 |
|
161 |
1.1 |
|
162 |
1.1 |
|
164 |
1.1 |