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