Skip to content

Commit

Permalink
Fixed support for keys that look like numbers longer than an int.
Browse files Browse the repository at this point in the history
Previously such config keys would still be parsed with
`Integer#parseInt`, resulting in a `NumberFormatException`.
Now the number-like keys are parsed to a Long (no measures made but
performance expected hit expected to be negligible) if their numbers of
digits is shorter than the number of digits in `Long.MAX_VALUE`.

One could have also tried to parse numbers exactly up to `Long.MAX_VALUE`,
but added usability doesn't seem to match the required complexity - in
fact, one could also argue that the current loop-based checking if a key
looks like a number is a bit of an overkill, but I didn't want to dig into
the original reason for why a regexp was not used, instead focusing on
fixing an apparent bug in the most straightforward way.
  • Loading branch information
michalmela committed Jul 10, 2018
1 parent 1c83360 commit f76deb6
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -421,20 +421,20 @@ public AbstractConfigValue modifyChild(String key, AbstractConfigValue v) {
// this is only Serializable to chill out a findbugs warning
static final private class RenderComparator implements java.util.Comparator<String>, Serializable {
private static final long serialVersionUID = 1L;
private static final int MAX_DIGITS_IN_LONG = Long.toString(Long.MAX_VALUE).length();

private static boolean isAllDigits(String s) {
private static boolean safeToParseAsLong(String s) {
int length = s.length();

// empty string doesn't count as a number
if (length == 0)
// string longer than "max number of digits in a long" cannot be parsed as a long
if (length == 0 || length >= MAX_DIGITS_IN_LONG)
return false;

for (int i = 0; i < length; ++i) {
char c = s.charAt(i);

if (Character.isDigit(c))
continue;
else
if (!Character.isDigit(c))
return false;
}
return true;
Expand All @@ -446,13 +446,13 @@ private static boolean isAllDigits(String s) {
// (numeric indices) appear in order.
@Override
public int compare(String a, String b) {
boolean aDigits = isAllDigits(a);
boolean bDigits = isAllDigits(b);
if (aDigits && bDigits) {
return Integer.compare(Integer.parseInt(a), Integer.parseInt(b));
} else if (aDigits) {
boolean aParsable = safeToParseAsLong(a);
boolean bParsable = safeToParseAsLong(b);
if (aParsable && bParsable) {
return Long.compare(Long.parseLong(a), Long.parseLong(b));
} else if (aParsable) {
return -1;
} else if (bDigits) {
} else if (bParsable) {
return 1;
} else {
return a.compareTo(b);
Expand Down
43 changes: 43 additions & 0 deletions config/src/test/resources/test12.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// this checks sorting map keys, where keys that look like numbers are treated differently
// specifically tests very long numbers which fit neither in an Integer nor in a Long

"10" = "42"
sth = 42
"1" = "42"
"12" = "42"
"123" = "42"
"1234" = "42"
"12345" = "42"
"123456" = "42"
"1234567" = "42"
"12345678" = "42"
"123456789" = "42"
"1234567890" = "42"
"12345678901" = "42"
"123456789012" = "42"
"1234567890123" = "42"
"12345678901234" = "42"
"123456789012345" = "42"
"1234567890123456" = "42"
"12345678901234567" = "42"
"123456789012345678" = "42"
"1234567890123456789" = "42"
"12345678901234567891" = "42"
"123456789012345678912" = "42"
"1234567890123456789123" = "42"
"12345678901234567891234" = "42"
"123456789012345678912345" = "42"
"1234567890123456789123456" = "42"
"12345678901234567891234567" = "42"
"123456789012345678912345678" = "42"
"1234567890123456789123456789" = "42"
"12345678901234567891234567890" = "42"
"123456789012345678912345678901" = "42"
"1234567890123456789123456789012" = "42"
"12345678901234567891234567890123" = "42"
"123456789012345678912345678901234" = "42"
"1234567890123456789123456789012345" = "42"
"12345678901234567891234567890123456" = "42"
"123456789012345678912345678901234567" = "42"
"1234567890123456789123456789012345678" = "42"
"12345678901234567891234567890123456789" = "42"
1 change: 1 addition & 0 deletions config/src/test/scala/Rendering.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ object RenderExample extends App {
render("test01")
render("test06")
render("test05")
render("test12")
}

object RenderOptions extends App {
Expand Down

0 comments on commit f76deb6

Please sign in to comment.