/******************************************************************************
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* The Original Code is: Jsoda
* The Initial Developer of the Original Code is: William Wong (williamw520@gmail.com)
* Portions created by William Wong are Copyright (C) 2012 William Wong, All Rights Reserved.
*
******************************************************************************/
package wwutil.sys;
import java.io.*;
import java.nio.*;
import java.util.*;
import java.math.BigInteger;
/**
* Encoder for BaseX
*/
public class BaseXUtil
{
// Base62
public static final String DIGITS_62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
// Base58 Base62 minus the 0 O 1 l
public static final String DIGITS_58 = "23456789ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
/**
* Encodes a number using BaseX encoding.
*
* @param number a positive integer
* @param alphabets is the set of alphabet for encoding.
* @return a BaseX string
* @throws IllegalArgumentException if <code>number</code> is negative
*/
public static String encode(BigInteger number, String alphabets) {
if (number.compareTo(BigInteger.ZERO) == -1)
throw new IllegalArgumentException("Number cannot be negative");
StringBuilder sb = new StringBuilder();
BigInteger base = BigInteger.valueOf(alphabets.length());
BigInteger[] divrem = new BigInteger[] {number, BigInteger.ZERO};
while (divrem[0].compareTo(BigInteger.ZERO) == 1) {
divrem = divrem[0].divideAndRemainder(base);
sb.append(alphabets.charAt(divrem[1].intValue()));
}
return (sb.length() == 0) ? alphabets.substring(0, 1) : sb.reverse().toString();
}
/**
* Decodes a string using BaseX encoding.
*
* @param str a BaseX String
* @param alphabets is the set of alphabet for encoding.
* @return a positive number
* @throws IllegalArgumentException if <code>str</code> is empty
*/
public static BigInteger decode(final String str, String alphabets) {
if (str.length() == 0)
throw new IllegalArgumentException("Str cannot be empty");
BigInteger result = BigInteger.ZERO;
BigInteger base = BigInteger.valueOf(alphabets.length());
int digits = str.length();
for (int i = 0; i < digits; i++) {
int digit = alphabets.indexOf(str.charAt(digits - i - 1));
result = result.add(BigInteger.valueOf(digit).multiply(base.pow(i)));
}
return result;
}
public static String encode58(BigInteger number) {
return encode(number, DIGITS_58);
}
public static BigInteger decode58(final String str) {
return decode(str, DIGITS_58);
}
public static String encode62(BigInteger number) {
return encode(number, DIGITS_62);
}
public static BigInteger decode62(final String str) {
return decode(str, DIGITS_62);
}
public static String uuidToBase58(UUID uuid) {
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(uuid.getMostSignificantBits());
bb.putLong(uuid.getLeastSignificantBits());
BigInteger number = new BigInteger(bb.array()).abs();
return encode58(number);
}
public static String uuid16() {
UUID uuid = UUID.randomUUID();
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(uuid.getMostSignificantBits());
bb.putLong(uuid.getLeastSignificantBits());
BigInteger number = new BigInteger(bb.array()).abs();
return encode58(number);
}
public static String uuid8() {
UUID uuid = UUID.randomUUID();
long val = uuid.getMostSignificantBits() ^ uuid.getLeastSignificantBits();
BigInteger number = BigInteger.valueOf(val).abs();
return encode58(number);
}
}