private static long parseUnsignedLong(String s, int radix)
    {
        if (s.length() == 0)
        {
            throw new NumberFormatException("empty string");
        }
        if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
        {
            throw new NumberFormatException("illegal radix: " + radix);
        }

        int max_safe_pos = maxSafeDigits[radix] - 1;
        long value = 0;
        for (int pos = 0; pos < s.length(); pos++)
        {
            int digit = Character.digit(s.charAt(pos), radix);
            if (digit == -1)
            {
                throw new NumberFormatException(s);
            }
            if (pos > max_safe_pos && overflowInParse(value, digit, radix))
            {
                throw new NumberFormatException("Too large for unsigned long: " + s);
            }
            value = (value * radix) + digit;
        }

        return value;
    }
Returns the unsigned {@code long} value represented by a string with the given radix.

@param s
           the string containing the unsigned {@code long} representation to be parsed.
@param radix
           the radix to use while parsing {@code s}
@throws NumberFormatException
            if the string does not contain a valid unsigned {@code long} with the given radix, or if
            {@code radix} is not between {@link Character#MIN_RADIX} and {@link Character#MAX_RADIX}.
@throws NullPointerException
            if {@code s} is null (in contrast to {@link Long#parseLong(String)})
protostuff-api/src/main/java/io/protostuff/UnsignedNumberUtil.java