Integer minRadix = 2; Integer maxRadix = 36; "The `Integer` value of the given string representation of an integer, or `null` if the string does not represent an integer or if the mathematical integer it represents is too large in magnitude to be represented by an `Integer`. The syntax accepted by this function is the same as the syntax for an `Integer` literal in the Ceylon language except that it may optionally begin with a sign character (`+` or `-`). A radix can be given in input to specify what is the base to take in consideration for the parsing. radix has to be between `minRadix` and `maxRadix` included. The list of available digits starts from `0` to `9` followed by `a` to `z`. When parsing in a specific base, the first `radix` digits from the available digits list can be used. This function is not case sensitive; `a` and `A` both correspond to the `a` digit which decimal value is `10`. `_` character can be used to separate groups of digits for bases 2, 10 and 16 as for `Integer` literal in the Ceylon language. For any other bases, no grouping is supported." throws (`class AssertionException`, "if `radix` is not between `minRadix` and `maxRadix`") shared Integer? parseInteger(String string, Integer radix = 10) { assert (radix >= minRadix, radix <= maxRadix); variable Integer ii = 0; Integer max = runtime.minIntegerValue / radix; Boolean negative; if (exists char = string[ii]) { if (char == '-') { negative = true; ii++; } else if (char == '+') { negative = false; ii++; } else { negative = false; } } else { return null; } Integer limit = negative then runtime.minIntegerValue else -runtime.maxIntegerValue; Integer length = string.size; variable Integer result = 0; variable Integer sep = -1; variable Integer digitIndex = 0; variable Integer groupingSize = -1; while (ii < length) { Character ch; if (exists char = string[ii]) { ch = char; } else { return null; } if (ch == '_') { if (sep == -1) { if (exists digitGroupSize = computeDigitGroupingSize(radix, digitIndex, string, ii), digitIndex <= digitGroupSize) { groupingSize = digitGroupSize; sep = digitIndex; } else { return null; } } else if ((digitIndex - sep) == groupingSize) { return null; } else { sep = digitIndex; } } else { if (sep != -1 && (digitIndex - sep) == (groupingSize + 1)) { return null; } if (ii + 1 == length && radix == 10 && ch in ['k','M','G','T','P']) { // The magnitude if (exists magnitude = computeMagnitude(radix, string[ii++])) { if ((limit / magnitude) < result) { result *= magnitude; break; } else { // overflow return null; } } else { return null; } } else if (exists digit = parseDigit(ch, radix)) { if (result < max) { // overflow return null; } result *= radix; if (result < limit + digit) { // overflow return null; } // += would be much more obvious, but it doesn't work for minIntegerValue result -= digit; } else { // Invalid digit return null; } } ii++; digitIndex++; } // check for insufficient digits after the last _ if (sep != -1 && (digitIndex - sep) != (groupingSize + 1)) { return null; } if (digitIndex == 0) { return null; } return negative then result else -result; } Integer? computeDigitGroupingSize(Integer radix, Integer digitIndex, String string, Integer ii) { Integer? groupingSize; if (radix == 2) { groupingSize = 4; } else if (radix == 10) { groupingSize = 3; } else if (radix == 16) { if (digitIndex <= 2, exists char = string[ii + 3], char == '_') { groupingSize = 2; } else { groupingSize = 4; } } else { groupingSize = null; } return groupingSize; } Integer? computeMagnitude(Integer radix, Character? char) { Integer? power; if (exists char) { if (char == 'P') { power = 15; } else if (char == 'T') { power = 12; } else if (char == 'G') { power = 9; } else if (char == 'M') { power = 6; } else if (char == 'k') { power = 3; } else { power = null; } } else { power = null; } if (exists power) { return radix^power; } return null; } Integer aInt = 'a'.integer; Integer zeroInt = '0'.integer; Integer? parseDigit(Character digit, Integer radix) { Integer figure; Integer digitInt = digit.integer; if (0<=digitInt-zeroInt<10) { figure=digitInt-zeroInt; } else if (0<=digitInt-aInt<26) { figure=digitInt-aInt+10; } else { return null; } return figure<radix then figure; } "The string representation of `integer` in the `radix` base. `radix` must be between `minRadix` and `maxRadix` included. If `integer` is negative, returned string will start by character `-`" throws (`class AssertionException`, "if `radix` is not between `minRadix` and `maxRadix`") shared String formatInteger(Integer integer, Integer radix = 10) { assert (radix >= minRadix, radix <= maxRadix); if (integer == 0) { return "0"; } StringBuilder digits = StringBuilder(); Integer insertIndex; variable Integer i; if (integer < 0) { digits.append("-"); insertIndex = 1; i = integer; } else { insertIndex = 0; i = -integer; } while (i != 0) { Integer d = -(i % radix); Character c; if (0<=d<10) { c = (d+zeroInt).character; } else if (10<=d<36) { c = (d-10+aInt).character; } else { assert (false); } digits.insertCharacter(insertIndex, c); i = (i + d) / radix; } return digits.string; }