mirror of
https://github.com/plexusorg/toml4j.git
synced 2024-10-31 17:29:14 +00:00
Improved handling of bare and quoted keys
This commit is contained in:
parent
f804c99534
commit
b7b546dc83
|
@ -25,6 +25,35 @@ class Keys {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static String getKey(String key) {
|
||||||
|
key = key.trim();
|
||||||
|
|
||||||
|
if (key.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean quoted = false;
|
||||||
|
char[] chars = key.toCharArray();
|
||||||
|
StringBuilder sb = new StringBuilder(key.length());
|
||||||
|
|
||||||
|
for (int i = 0; i < chars.length; i++) {
|
||||||
|
char c = chars[i];
|
||||||
|
|
||||||
|
if (c == '"' && (i == 0 || chars[i - 1] != '\\')) {
|
||||||
|
if (!quoted && i > 0 && chars [i - 1] != '.') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
quoted = !quoted;
|
||||||
|
} else if (!quoted && (ALLOWED_CHARS.indexOf(c) == -1)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
static Keys.Key[] split(String key) {
|
static Keys.Key[] split(String key) {
|
||||||
List<Key> splitKey = new ArrayList<Key>();
|
List<Key> splitKey = new ArrayList<Key>();
|
||||||
StringBuilder current = new StringBuilder();
|
StringBuilder current = new StringBuilder();
|
||||||
|
@ -111,6 +140,9 @@ class Keys {
|
||||||
for (int i = 1; i < chars.length; i++) {
|
for (int i = 1; i < chars.length; i++) {
|
||||||
char c = chars[i];
|
char c = chars[i];
|
||||||
if (c == '"' && chars[i - 1] != '\\') {
|
if (c == '"' && chars[i - 1] != '\\') {
|
||||||
|
if (!quoted && i > 1 && chars [i - 1] != '.') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
quoted = !quoted;
|
quoted = !quoted;
|
||||||
} else if (!quoted && c == ']') {
|
} else if (!quoted && c == ']') {
|
||||||
terminated = true;
|
terminated = true;
|
||||||
|
|
|
@ -36,7 +36,7 @@ class TomlParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isTableArray(line)) {
|
if (isTableArray(line)) {
|
||||||
String tableName = getTableArrayName(line);
|
String tableName = Keys.getTableArrayName(line);
|
||||||
if (tableName != null) {
|
if (tableName != null) {
|
||||||
results.startTableArray(tableName);
|
results.startTableArray(tableName);
|
||||||
String afterTableName = line.substring(tableName.length() + 4);
|
String afterTableName = line.substring(tableName.length() + 4);
|
||||||
|
@ -51,7 +51,7 @@ class TomlParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (multiline.isNotMultiline() && isTable(line)) {
|
if (multiline.isNotMultiline() && isTable(line)) {
|
||||||
String tableName = getTableName(line);
|
String tableName = Keys.getTableName(line);
|
||||||
if (tableName != null) {
|
if (tableName != null) {
|
||||||
results.startTables(tableName);
|
results.startTables(tableName);
|
||||||
} else {
|
} else {
|
||||||
|
@ -140,14 +140,14 @@ class TomlParser {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
key = pair[0].trim();
|
key = Keys.getKey(pair[0]);
|
||||||
|
if (key == null) {
|
||||||
|
results.errors.append("Invalid key name: " + pair[0] + "\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
value = pair[1].trim();
|
value = pair[1].trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isKeyValid(key)) {
|
|
||||||
results.errors.append("Invalid key name: " + key + "\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object convertedValue = VALUE_ANALYSIS.convert(value);
|
Object convertedValue = VALUE_ANALYSIS.convert(value);
|
||||||
|
|
||||||
|
@ -169,26 +169,10 @@ class TomlParser {
|
||||||
return line.startsWith("[[");
|
return line.startsWith("[[");
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getTableArrayName(String line) {
|
|
||||||
return Keys.getTableArrayName(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isTable(String line) {
|
private boolean isTable(String line) {
|
||||||
return line.startsWith("[");
|
return line.startsWith("[");
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getTableName(String line) {
|
|
||||||
return Keys.getTableName(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isKeyValid(String key) {
|
|
||||||
if (key.contains("#") || key.trim().isEmpty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isComment(String line) {
|
private boolean isComment(String line) {
|
||||||
if (line == null || line.isEmpty()) {
|
if (line == null || line.isEmpty()) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -10,7 +10,7 @@ public class BareKeysTest {
|
||||||
public final ExpectedException exception = ExpectedException.none();
|
public final ExpectedException exception = ExpectedException.none();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void should_fail_when_characters_outside_accept_range_are_used() throws Exception {
|
public void should_fail_when_characters_outside_accept_range_are_used_in_table_name() throws Exception {
|
||||||
exception.expect(IllegalStateException.class);
|
exception.expect(IllegalStateException.class);
|
||||||
exception.expectMessage("Invalid table definition: [~]");
|
exception.expectMessage("Invalid table definition: [~]");
|
||||||
|
|
||||||
|
@ -18,16 +18,48 @@ public class BareKeysTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void should_fail_on_sharp_sign_in_table_names() throws Exception {
|
public void should_fail_when_characters_outside_accept_range_are_used_in_key_name() throws Exception {
|
||||||
|
exception.expect(IllegalStateException.class);
|
||||||
|
|
||||||
|
new Toml().parse("~ = 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void should_fail_on_sharp_sign_in_table_name() throws Exception {
|
||||||
exception.expect(IllegalStateException.class);
|
exception.expect(IllegalStateException.class);
|
||||||
|
|
||||||
new Toml().parse("[group#]\nkey=1");
|
new Toml().parse("[group#]\nkey=1");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void should_fail_on_spaces_in_table_names() throws Exception {
|
public void should_fail_on_spaces_in_table_name() throws Exception {
|
||||||
exception.expect(IllegalStateException.class);
|
exception.expect(IllegalStateException.class);
|
||||||
|
|
||||||
new Toml().parse("[valid key]");
|
new Toml().parse("[valid key]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalStateException.class)
|
||||||
|
public void should_fail_on_question_marks_in_key_name() throws Exception {
|
||||||
|
new Toml().parse("key?=true");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalStateException.class)
|
||||||
|
public void should_fail_on_empty_table_name() {
|
||||||
|
new Toml().parse("[]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalStateException.class)
|
||||||
|
public void should_fail_on_nested_table_name_ending_with_empty_table_name() {
|
||||||
|
new Toml().parse("[a.]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalStateException.class)
|
||||||
|
public void should_fail_on_nested_table_name_containing_empty_table_name() {
|
||||||
|
new Toml().parse("[a..b]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalStateException.class)
|
||||||
|
public void should_fail_on_nested_table_name_starting_with_empty_table_name() {
|
||||||
|
new Toml().parse("[.b]");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,16 +109,26 @@ public class BurntSushiValidTest {
|
||||||
run("key-equals-nospace");
|
run("key-equals-nospace");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test @Ignore
|
||||||
public void key_space() throws Exception {
|
public void key_space() throws Exception {
|
||||||
run("key-space");
|
run("key-space");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
public void key_space_modified() throws Exception {
|
||||||
|
run("key-space-modified");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test @Ignore
|
||||||
public void key_special_chars() throws Exception {
|
public void key_special_chars() throws Exception {
|
||||||
run("key-special-chars");
|
run("key-special-chars");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void key_special_chars_modified() throws Exception {
|
||||||
|
run("key-special-chars-modified");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void keys_with_dots() throws Exception {
|
public void keys_with_dots() throws Exception {
|
||||||
run("keys-with-dots");
|
run("keys-with-dots");
|
||||||
|
@ -134,11 +144,16 @@ public class BurntSushiValidTest {
|
||||||
run("long-integer");
|
run("long-integer");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test @Ignore
|
||||||
public void multiline_string() throws Exception {
|
public void multiline_string() throws Exception {
|
||||||
run("multiline-string");
|
run("multiline-string");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void multiline_string_modified() throws Exception {
|
||||||
|
run("multiline-string-modified");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void raw_multiline_string() throws Exception {
|
public void raw_multiline_string() throws Exception {
|
||||||
run("raw-multiline-string");
|
run("raw-multiline-string");
|
||||||
|
@ -154,11 +169,16 @@ public class BurntSushiValidTest {
|
||||||
run("string-empty");
|
run("string-empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test @Ignore
|
||||||
public void string_escapes() throws Exception {
|
public void string_escapes() throws Exception {
|
||||||
run("string-escapes-modified");
|
run("string-escapes-modified");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void string_escapes_modified() throws Exception {
|
||||||
|
run("string-escapes-modified");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void string_simple() throws Exception {
|
public void string_simple() throws Exception {
|
||||||
run("string-simple");
|
run("string-simple");
|
||||||
|
|
|
@ -81,6 +81,28 @@ public class QuotedKeysTest {
|
||||||
assertEquals("type0", toml.getString("dog.\"ty\\\"pe\".\"na\\\"me\""));
|
assertEquals("type0", toml.getString("dog.\"ty\\\"pe\".\"na\\\"me\""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void should_support_fully_quoted_table_name() throws Exception {
|
||||||
|
Toml toml = new Toml().parse("[\"abc.def\"] \n key = 1");
|
||||||
|
|
||||||
|
assertEquals(1, toml.getLong("\"abc.def\".key").intValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalStateException.class)
|
||||||
|
public void should_fail_on_malformed_quoted_key() throws Exception {
|
||||||
|
new Toml().parse("k\"ey\" = 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalStateException.class)
|
||||||
|
public void should_fail_on_malformed_quoted_table() throws Exception {
|
||||||
|
new Toml().parse("[a\"bc\"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalStateException.class)
|
||||||
|
public void should_fail_on_malformed_quoted_nested_table() throws Exception {
|
||||||
|
new Toml().parse("[a.a\"bc\"]");
|
||||||
|
}
|
||||||
|
|
||||||
private static class Quoted {
|
private static class Quoted {
|
||||||
|
|
||||||
String ʎǝʞ;
|
String ʎǝʞ;
|
||||||
|
|
|
@ -116,13 +116,6 @@ public class TomlTest {
|
||||||
|
|
||||||
assertEquals(1, toml.getLong("a_a").intValue());
|
assertEquals(1, toml.getLong("a_a").intValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void should_support_question_marks_in_key_names() throws Exception {
|
|
||||||
Toml toml = new Toml().parse("key?=true");
|
|
||||||
|
|
||||||
assertTrue(toml.getBoolean("key?"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void should_support_dots_in_key_names() throws Exception {
|
public void should_support_dots_in_key_names() throws Exception {
|
||||||
|
@ -207,26 +200,6 @@ public class TomlTest {
|
||||||
public void should_fail_when_illegal_characters_after_table() throws Exception {
|
public void should_fail_when_illegal_characters_after_table() throws Exception {
|
||||||
new Toml().parse("[error] if you didn't catch this, your parser is broken");
|
new Toml().parse("[error] if you didn't catch this, your parser is broken");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalStateException.class)
|
|
||||||
public void should_fail_on_empty_table_name() {
|
|
||||||
new Toml().parse("[]");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = IllegalStateException.class)
|
|
||||||
public void should_fail_on_compound_table_name_ending_with_empty_table_name() {
|
|
||||||
new Toml().parse("[a.]");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = IllegalStateException.class)
|
|
||||||
public void should_fail_on_compound_table_name_containing_empty_table_name() {
|
|
||||||
new Toml().parse("[a..b]");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = IllegalStateException.class)
|
|
||||||
public void should_fail_on_compound_table_name_starting_with_empty_table_name() {
|
|
||||||
new Toml().parse("[.b]");
|
|
||||||
}
|
|
||||||
|
|
||||||
private File file(String file) {
|
private File file(String file) {
|
||||||
return new File(getClass().getResource(file + ".toml").getFile());
|
return new File(getClass().getResource(file + ".toml").getFile());
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"ab": {"type": "integer", "value": "1"}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
ab = 1
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"_-1234567890": {
|
||||||
|
"type": "integer", "value": "1"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
_-1234567890 = 1
|
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
"multiline_empty_one": {
|
||||||
|
"type": "string",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"multiline_empty_two": {
|
||||||
|
"type": "string",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"multiline_empty_three": {
|
||||||
|
"type": "string",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"multiline_empty_four": {
|
||||||
|
"type": "string",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"equivalent_one": {
|
||||||
|
"type": "string",
|
||||||
|
"value": "The quick brown fox jumps over the lazy dog."
|
||||||
|
},
|
||||||
|
"equivalent_two": {
|
||||||
|
"type": "string",
|
||||||
|
"value": "The quick brown fox jumps over the lazy dog."
|
||||||
|
},
|
||||||
|
"equivalent_three": {
|
||||||
|
"type": "string",
|
||||||
|
"value": "The quick brown fox jumps over the lazy dog."
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
multiline_empty_one = """"""
|
||||||
|
multiline_empty_two = """
|
||||||
|
"""
|
||||||
|
multiline_empty_three = """\
|
||||||
|
"""
|
||||||
|
multiline_empty_four = """\
|
||||||
|
\
|
||||||
|
\
|
||||||
|
"""
|
||||||
|
|
||||||
|
equivalent_one = "The quick brown fox jumps over the lazy dog."
|
||||||
|
equivalent_two = """
|
||||||
|
The quick brown \
|
||||||
|
|
||||||
|
|
||||||
|
fox jumps over \
|
||||||
|
the lazy dog."""
|
||||||
|
|
||||||
|
equivalent_three = """\
|
||||||
|
The quick brown \
|
||||||
|
fox jumps over \
|
||||||
|
the lazy dog.\
|
||||||
|
"""
|
Loading…
Reference in a new issue