"The [[Integer]] value of the given
[[string representation|string]] of an integer value in the
base given by [[radix]], or `null` if the string does not
represent an integer in that base, or if the mathematical
integer it represents is too large in magnitude to be
represented by an instance of the class `Integer`.
The syntax accepted by this function depends upon the
given [[base|radix]]:
- For base 10, the accepted syntax 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 `-`) and may not contain grouping underscore
characters. That is, an optional sign character, followed
be a string of decimal digits, followed by an optional SI
magnitude: `k`, `M`, `G`, `T`, or `P`.
- For other bases, the accepted syntax is an optional sign
character, followed by a string of digits of the given
base.
The given `radix` specifies the base of the string
representation. 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 is used. This function is not case sensitive;
`a` and `A` both correspond to the digit `a` whose decimal
value is `10`.
Integer: Base10 | BaseN
Base10: Sign? Base10Digits Magnitude
BaseN: Sign? BaseNDigits
Sign: '+' | '-'
Magnitude: 'k' | 'M' | 'G' | 'T' | 'P'
Base10Digits: ('0'..'9')+
BaseNDigits: ('0'..'9'|'a'..'z'|'A'..'Z')+"
throws (`class AssertionError`,
"if [[radix]] is not between [[minRadix]] and
[[maxRadix]]")
see (`function Integer.parse`)
tagged("Numbers", "Basic types")
deprecated("Use [[Integer.parse]]")
shared Integer? parseInteger(
"The string representation to parse."
String string,
"The base, between [[minRadix]] and [[maxRadix]]
inclusive."
Integer radix = 10)
=> if (is Integer result
= parseIntegerInternal(string, radix))
then result
else null;
Integer minRadix = 2;
Integer maxRadix = 36;
Integer|ParseException parseIntegerInternal(
String string, Integer radix = 10) {
"illegal radix"
assert (minRadix <= radix <= maxRadix);
Integer start;
Integer max = runtime.minIntegerValue / radix;
// Parse the sign
Boolean negative;
if (exists char = string.first) {
if (char == '-') {
negative = true;
start = 1;
}
else if (char == '+') {
negative = false;
start = 1;
}
else {
negative = false;
start = 0;
}
}
else {
return ParseException("illegal format for Integer: no digits");
}
value limit = negative
then runtime.minIntegerValue
else -runtime.maxIntegerValue;
value length = string.size;
variable value result = 0;
variable value digitIndex = 0;
variable value index = start;
while (index < length) {
assert (exists ch = string.getFromFirst(index));
if (index + 1 == length &&
radix == 10 &&
ch in "kMGTP") {
// The SI-style magnitude
"unrecognized SI magnitude"
assert (exists exp = parseIntegerExponent(ch));
Integer magnitude = 10^exp;
if ((limit / magnitude) < result) {
result *= magnitude;
break;
}
else {
// overflow
return ParseException("numeric value is too large for Integer");
}
}
else if (exists digit = parseDigit(ch, radix)) {
// A regular digit
if (result < max) {
// overflow
return ParseException("numeric value too large for Integer");
}
result *= radix;
if (result < limit + digit) {
// overflow
return ParseException("numeric value too large for Integer");
}
// += would be much more obvious, but it doesn't work for minIntegerValue
result -= digit;
}
else {
// Invalid character
return ParseException("illegal format for Integer: unexpected character '``ch``'");
}
index++;
digitIndex++;
}
if (digitIndex == 0) {
return ParseException("illegal format for Integer: no digits");
}
else {
return negative then result else -result;
}
}
Integer? parseIntegerExponent(Character char) {
switch (char)
case ('P') {
return 15;
}
case ('T') {
return 12;
}
case ('G') {
return 9;
}
case ('M') {
return 6;
}
case ('k') {
return 3;
}
else {
return null;
}
}
Integer aIntLower = 'a'.integer;
Integer aIntUpper = '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-aIntLower<26) {
figure=digitInt-aIntLower+10;
}
else if (0<=digitInt-aIntUpper<26) {
figure=digitInt-aIntUpper+10;
}
else {
return null;
}
return figure<radix then figure;
}