package org.jetbrains.debugger.sourcemap; final class Base64VLQ { private Base64VLQ() { } interface CharIterator { boolean hasNext(); char next(); } // A Base64 VLQ digit can represent 5 bits, so it is base-32. private static final int VLQ_BASE_SHIFT = 5; private static final int VLQ_BASE = 1 << VLQ_BASE_SHIFT; // A mask of bits for a VLQ digit (11111), 31 decimal. private static final int VLQ_BASE_MASK = VLQ_BASE - 1; // The continuation bit is the 6th bit. private static final int VLQ_CONTINUATION_BIT = VLQ_BASE; /** * Decodes the next VLQValue from the provided CharIterator. */ public static int decode(CharIterator in) { int result = 0; int shift = 0; int digit; do { digit = Base64.BASE64_DECODE_MAP[in.next()]; assert (digit != -1) : "invalid char"; result += (digit & VLQ_BASE_MASK) << shift; shift += VLQ_BASE_SHIFT; } while ((digit & VLQ_CONTINUATION_BIT) != 0); boolean negate = (result & 1) == 1; result >>= 1; return negate ? -result : result; } private static final class Base64 { /** * A map used to convert integer values in the range 0-63 to their base64 * values. */ private static final String BASE64_MAP = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; /** * A map used to convert base64 character into integer values. */ private static final int[] BASE64_DECODE_MAP = new int[256]; static { for (int i = 0; i < BASE64_MAP.length(); i++) { BASE64_DECODE_MAP[BASE64_MAP.charAt(i)] = i; } } } }