Added support for nested inline tables

This commit is contained in:
moandji.ezana 2015-02-10 20:06:46 +02:00
parent 5bd87a6b56
commit ddb061b9f9
3 changed files with 67 additions and 34 deletions

View file

@ -17,39 +17,45 @@ class InlineTableConverter implements ValueConverter {
@Override
public Object convert(String s) {
AtomicInteger sharedIndex = new AtomicInteger(1);
Object converted = convert(s, sharedIndex);
char[] chars = s.toCharArray();
for (; sharedIndex.get() < s.length(); sharedIndex.incrementAndGet()) {
char c = chars[sharedIndex.get()];
if (Character.isWhitespace(c)) {
continue;
}
if (c == '#') {
break;
}
return INVALID;
}
return converted;
}
Object convert(String s, AtomicInteger sharedIndex) {
char[] chars = s.toCharArray();
boolean inKey = true;
boolean pairHasKey = false;
boolean inValue = false;
boolean quoted = false;
boolean inArray = false;
boolean inString = false;
boolean terminated = false;
StringBuilder currentKey = new StringBuilder();
StringBuilder current = new StringBuilder();
HashMap<String, Object> results = new HashMap<String, Object>();
for (int i = 1; i < chars.length; i++) {
for (; sharedIndex.get() < chars.length; sharedIndex.incrementAndGet()) {
int i = sharedIndex.get();
char c = chars[i];
if (terminated) {
if (Character.isWhitespace(c)) {
continue;
}
if (c == '#') {
break;
}
return INVALID;
}
if (c == '"') {
quoted = !quoted;
(inValue ? current : currentKey).append(c);
} else if (quoted) {
(inKey ? currentKey : current).append(c);
} else if (c == '[' && inValue) {
AtomicInteger sharedIndex = new AtomicInteger(i);
sharedIndex.incrementAndGet();
Object converted = ArrayConverter.ARRAY_PARSER.convert(s, sharedIndex);
@ -59,15 +65,23 @@ class InlineTableConverter implements ValueConverter {
results.put(currentKey.toString().trim(), converted);
i = sharedIndex.get();
inArray = true;
continue;
} else if (c == ']' && inArray) {
current.append(']');
inArray = false;
} else if (c == '{') {
sharedIndex.incrementAndGet();
Object converted = convert(s, sharedIndex);
if (converted == INVALID) {
return INVALID;
}
results.put(currentKey.toString().trim(), converted);
inKey = true;
inValue = false;
currentKey = new StringBuilder();
current = new StringBuilder();
} else if (c == ',') {
if (inArray) {
inArray = false;
} else {
if (!current.toString().trim().isEmpty()) {
Object converted = CONVERTERS.convert(current.toString().trim());
if (converted == INVALID) {
@ -78,28 +92,28 @@ class InlineTableConverter implements ValueConverter {
}
inKey = true;
pairHasKey = false;
inValue = false;
currentKey = new StringBuilder();
current = new StringBuilder();
} else if (c == '=') {
inKey = false;
pairHasKey = true;
inValue = true;
} else if (c == '}') {
terminated = true;
if (current.toString().trim().length() == 0) {
continue;
String trimmed = current.toString().trim();
if (!trimmed.isEmpty()) {
Object converted = CONVERTERS.convert(trimmed);
if (converted == INVALID) {
return INVALID;
}
results.put(currentKey.toString().trim(), converted);
}
Object converted = CONVERTERS.convert(current.toString().trim());
if (converted == INVALID) {
return INVALID;
}
results.put(currentKey.toString().trim(), converted);
sharedIndex.incrementAndGet();
break;
} else {
(inKey ? currentKey : current).append(c);
}

View file

@ -117,6 +117,7 @@ class Results {
for (Map.Entry<String, Object> entry : valueMap.entrySet()) {
addValue(entry.getKey(), entry.getValue());
}
stack.pop();
} else if (currentTable.accepts(key)) {
currentTable.put(key, value);
} else {

View file

@ -107,4 +107,22 @@ public class InlineTableTest {
assertEquals("abc", toml.getString("string"));
assertThat(toml.<Long>getList("list"), contains(5L, 6L, 7L, 8L));
}
@Test
public void should_read_nested_inline_tables() throws Exception {
Toml tables = new Toml().parse("tables = { t1 = { t1_1 = 1, t1_2 = 2}, t2 = { t2_1 = \"a\"} }").getTable("tables");
assertEquals(1L, tables.getLong("t1.t1_1").longValue());
assertEquals(2L, tables.getLong("t1.t1_2").longValue());
assertEquals("a", tables.getString("t2.t2_1"));
}
@Test
public void should_read_all_string_types() throws Exception {
Toml strings = new Toml().parse("strings = { literal = 'ab]\"c', multiline = \"\"\"de]\"f\"\"\", multiline_literal = '''gh]\"i''' }").getTable("strings");
assertEquals("ab]\"c", strings.getString("literal"));
assertEquals("de]\"f", strings.getString("multiline"));
assertEquals("gh]\"i", strings.getString("multiline_literal"));
}
}