diff --git a/src/main/java/com/moandjiezana/toml/Keys.java b/src/main/java/com/moandjiezana/toml/Keys.java index 0b94672..5a56b03 100644 --- a/src/main/java/com/moandjiezana/toml/Keys.java +++ b/src/main/java/com/moandjiezana/toml/Keys.java @@ -100,18 +100,36 @@ class Keys { char[] chars = line.toCharArray(); boolean quoted = false; boolean terminated = false; + int endIndex = -1; + boolean preKey = true; for (int i = 2; i < chars.length; i++) { char c = chars[i]; if (c == '"' && chars[i - 1] != '\\') { + if (!quoted && i > 1 && chars [i - 1] != '.' && !Character.isWhitespace(chars[i - 1])) { + break; + } quoted = !quoted; } else if (!quoted && c == ']') { if (chars.length > i + 1 && chars[i + 1] == ']') { terminated = true; + endIndex = i + 1; break; } + } else if (!quoted && c == '.') { + preKey = true; + } else if (!quoted && Character.isWhitespace(c)) { + if (preKey && i > 2 && chars[i - 1] != '.' && !Character.isWhitespace(chars[i - 1])) { + break; + } + if (!preKey && chars.length > i + 1 && chars[i + 1] != '.' && chars[i + 1] != ']' && !Character.isWhitespace(chars[i + 1])) { + break; + } + continue; } else if (!quoted && (ALLOWED_CHARS.indexOf(c) == -1)) { break; + } else { + preKey = false; } sb.append(c); @@ -119,12 +137,11 @@ class Keys { String tableName = sb.toString(); - if (!terminated || tableName.isEmpty() || !isComment(line.substring(tableName.length() + 4))) { + if (!terminated || tableName.isEmpty() || !isComment(line.substring(endIndex + 1))) { return null; } - tableName = StringConverter.STRING_PARSER.replaceUnicodeCharacters(tableName); - return tableName; + return StringConverter.STRING_PARSER.replaceUnicodeCharacters(tableName); } /** @@ -136,19 +153,34 @@ class Keys { char[] chars = line.toCharArray(); boolean quoted = false; boolean terminated = false; + int endIndex = -1; + boolean preKey = true; for (int i = 1; i < chars.length; i++) { char c = chars[i]; if (c == '"' && chars[i - 1] != '\\') { - if (!quoted && i > 1 && chars [i - 1] != '.') { + if (!quoted && i > 1 && chars [i - 1] != '.' && !Character.isWhitespace(chars[i - 1])) { break; } quoted = !quoted; } else if (!quoted && c == ']') { terminated = true; + endIndex = i; break; + } else if (!quoted && c == '.') { + preKey = true; + } else if (!quoted && Character.isWhitespace(c)) { + if (preKey && i > 1 && chars[i - 1] != '.' && !Character.isWhitespace(chars[i - 1])) { + break; + } + if (!preKey && chars.length > i + 1 && chars[i + 1] != '.' && chars[i + 1] != ']' && !Character.isWhitespace(chars[i + 1])) { + break; + } + continue; } else if (!quoted && (ALLOWED_CHARS.indexOf(c) == -1)) { break; + } else if (!quoted) { + preKey = false; } sb.append(c); @@ -156,12 +188,11 @@ class Keys { String tableName = sb.toString(); - if (!terminated || !isComment(line.substring(tableName.length() + 2))) { + if (!terminated || !isComment(line.substring(endIndex + 1))) { return null; } - tableName = StringConverter.STRING_PARSER.replaceUnicodeCharacters(tableName); - return tableName; + return StringConverter.STRING_PARSER.replaceUnicodeCharacters(tableName); } private Keys() {} diff --git a/src/main/java/com/moandjiezana/toml/Results.java b/src/main/java/com/moandjiezana/toml/Results.java index 1a3ae9b..8eb5361 100644 --- a/src/main/java/com/moandjiezana/toml/Results.java +++ b/src/main/java/com/moandjiezana/toml/Results.java @@ -29,9 +29,9 @@ class Results { stack.pop(); } - String[] tableParts = tableName.split("\\."); + Keys.Key[] tableParts = Keys.split(tableName); for (int i = 0; i < tableParts.length; i++) { - String tablePart = tableParts[i]; + String tablePart = tableParts[i].name; Container currentContainer = stack.peek(); if (currentContainer.get(tablePart) instanceof Container.TableArray) { diff --git a/src/test/java/com/moandjiezana/toml/BareKeysTest.java b/src/test/java/com/moandjiezana/toml/BareKeysTest.java index 57f18ad..b2b066f 100644 --- a/src/test/java/com/moandjiezana/toml/BareKeysTest.java +++ b/src/test/java/com/moandjiezana/toml/BareKeysTest.java @@ -1,5 +1,7 @@ package com.moandjiezana.toml; +import static org.junit.Assert.assertEquals; + import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -8,6 +10,13 @@ public class BareKeysTest { @Rule public final ExpectedException exception = ExpectedException.none(); + + @Test + public void should_ignore_spaces_around_key_segments() throws Exception { + Toml toml = new Toml().parse("[ a . b . c ] \n key = \"a\""); + + assertEquals("a", toml.getString("a.b.c.key")); + } @Test public void should_fail_when_characters_outside_accept_range_are_used_in_table_name() throws Exception { diff --git a/src/test/java/com/moandjiezana/toml/QuotedKeysTest.java b/src/test/java/com/moandjiezana/toml/QuotedKeysTest.java index 7b5f34c..f030f62 100644 --- a/src/test/java/com/moandjiezana/toml/QuotedKeysTest.java +++ b/src/test/java/com/moandjiezana/toml/QuotedKeysTest.java @@ -60,12 +60,19 @@ public class QuotedKeysTest { @Test public void should_support_table_array_index_with_quoted_key() throws Exception { - Toml toml = new Toml().parse("[[dog.\" type\"]] \n name = \"type0\" \n [[dog.\" type\"]] \n name = \"type1\""); + Toml toml = new Toml().parse("[[ dog. \" type\" ]] \n name = \"type0\" \n [[dog.\" type\"]] \n name = \"type1\""); assertEquals("type0", toml.getString("dog.\" type\"[0].name")); assertEquals("type1", toml.getString("dog.\" type\"[1].name")); } + @Test + public void should_support_table_array_index_with_dot_in_quoted_key() throws Exception { + Toml toml = new Toml().parse("[[ dog. \"a.type\" ]] \n name = \"type0\""); + + assertEquals("type0", toml.getString("dog.\"a.type\"[0].name")); + } + @Test public void should_support_quoted_key_containing_square_brackets() throws Exception { Toml toml = new Toml().parse("[dog.\" type[abc]\"] \n name = \"type0\" \n [dog.\" type[1]\"] \n \"name[]\" = \"type1\""); @@ -88,6 +95,13 @@ public class QuotedKeysTest { assertEquals(1, toml.getLong("\"abc.def\".key").intValue()); } + @Test + public void should_support_whitespace_around_key_segments() throws Exception { + Toml toml = new Toml().parse("[ dog. \"type\". breed ] \n name = \"type0\""); + + assertEquals("type0", toml.getString("dog.\"type\".breed.name")); + } + @Test(expected = IllegalStateException.class) public void should_fail_on_malformed_quoted_key() throws Exception { new Toml().parse("k\"ey\" = 1"); diff --git a/src/test/java/com/moandjiezana/toml/TableArrayTest.java b/src/test/java/com/moandjiezana/toml/TableArrayTest.java index b41a6ca..d1a78d4 100644 --- a/src/test/java/com/moandjiezana/toml/TableArrayTest.java +++ b/src/test/java/com/moandjiezana/toml/TableArrayTest.java @@ -87,6 +87,11 @@ public class TableArrayTest { assertEquals("granny smith", appleVariety.getString("name")); assertEquals("plantain", bananaVariety); } + + @Test(expected = IllegalStateException.class) + public void should_fail_on_empty_table_array_name() { + new Toml().parse("[[]]"); + } private File file(String fileName) { return new File(getClass().getResource(fileName + ".toml").getFile());