diff --git a/config/src/main/java/com/typesafe/config/impl/SimpleConfigObject.java b/config/src/main/java/com/typesafe/config/impl/SimpleConfigObject.java index cf5f5ea07..08f5e6011 100644 --- a/config/src/main/java/com/typesafe/config/impl/SimpleConfigObject.java +++ b/config/src/main/java/com/typesafe/config/impl/SimpleConfigObject.java @@ -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, 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; @@ -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); diff --git a/config/src/test/resources/test12.conf b/config/src/test/resources/test12.conf new file mode 100644 index 000000000..b7aff622b --- /dev/null +++ b/config/src/test/resources/test12.conf @@ -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" \ No newline at end of file diff --git a/config/src/test/scala/Rendering.scala b/config/src/test/scala/Rendering.scala index 0d8be469e..e1ca3cf6d 100644 --- a/config/src/test/scala/Rendering.scala +++ b/config/src/test/scala/Rendering.scala @@ -33,6 +33,7 @@ object RenderExample extends App { render("test01") render("test06") render("test05") + render("test12") } object RenderOptions extends App {