package net.deardeuff.ids.ordered; public final class OrderedLongEncoder { private static final Ordered64EncodeMap encoding = new Ordered64EncodeMap("_~"); private enum SignedEncoder { POSITIVE { protected long adjustSign(final long result) { return result; } protected int sizeOfHeader() { return 1; } }, NEGATIVE { protected long adjustSign(final long result) { return -result; } protected int sizeOfHeader() { return 2; } protected char encodeByte(final int b) { return super.encodeByte(63 - b); } protected int decodeByte(final char c) { return 63 - super.decodeByte(c); } }; protected abstract long adjustSign(long result); protected abstract int sizeOfHeader(); protected char encodeByte(final int b) { return encoding.encodeByte(b); } protected int decodeByte(final char c) { return encoding.decodeByte(c); } String encode(final long num) { final long abs = adjustSign(num); final int len = encodedLength(abs); final int sizeOfHeader = sizeOfHeader(); final char[] out = new char[len + sizeOfHeader]; out[0] = '-'; // will be replaced if positive printTo(out, len, sizeOfHeader); printTo(out, abs, out.length); return new String(out); } private void printTo(final char[] buffer, final long num, final int bufferLength) { int index = bufferLength - 1; for (long n = num; n != 0; n >>>= 6, index--) { final int remainder = (int)n & 63; buffer[index] = encodeByte(remainder); } } long decode(final CharSequence string) { int index = sizeOfHeader() - 1; final int length = decodeByte(string.charAt(index++)); long result = 0; for (final int end = index + length; index < end; index++) { result = (result << 6) | decodeByte(string.charAt(index)); } return adjustSign(result); } static SignedEncoder encoderFromSign(final boolean isPositive) { return isPositive ? SignedEncoder.POSITIVE : SignedEncoder.NEGATIVE; } } public static String encode(final long num) { if (num == 0) return "0"; return SignedEncoder.encoderFromSign(num >= 0).encode(num); } public static long decode(final CharSequence string) { return SignedEncoder.encoderFromSign(string.charAt(0) != '-').decode(string); } private static int encodedLength(final long num) { int r = 0; for (long n = num; n != 0; n >>>= 6) r++; return r; } }