package openmods.calc; import org.apache.commons.lang3.tuple.Pair; public abstract class PositionalNotationPrinter<E> { private final int maxDigits; public PositionalNotationPrinter(int maxDigits) { this.maxDigits = maxDigits; } public interface IDigitProvider { public int getNextDigit(); public boolean hasNextDigit(); } protected abstract IDigitProvider createIntegerDigitProvider(E value, int radix); protected abstract IDigitProvider createFractionalDigitProvider(E value, int radix); protected abstract boolean isNegative(E value); protected abstract boolean isZero(E value); protected abstract E negate(E value); protected abstract Pair<E, E> splitNumber(E value); private static final char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; private static String digitToString(int digit) { if (digit >= digits.length) { return "'" + digit + "'"; } else { return String.valueOf(digits[digit]); } } public String toString(E value, int radix) { final StringBuilder result = new StringBuilder(); final boolean isNegative = isNegative(value); if (isNegative) value = negate(value); final Pair<E, E> split = splitNumber(value); final E integer = split.getLeft(); if (integer != null) { if (isZero(integer)) { result.append('0'); } else { final IDigitProvider provider = createIntegerDigitProvider(integer, radix); while (provider.hasNextDigit()) { final int digit = provider.getNextDigit(); result.insert(0, digitToString(digit)); } } } if (isNegative) result.insert(0, "-"); int digitCount = 0; final E fractional = split.getRight(); if (fractional != null && !isZero(fractional)) { result.append('.'); final IDigitProvider provider = createFractionalDigitProvider(fractional, radix); while (provider.hasNextDigit() && digitCount++ < maxDigits) { final int digit = provider.getNextDigit(); result.append(digitToString(digit)); } } return result.toString().replace("''", "\""); } }