mirror of
https://github.com/plexusorg/toml4j.git
synced 2024-06-29 01:10:48 +00:00
158 lines
4.2 KiB
Java
158 lines
4.2 KiB
Java
package com.moandjiezana.toml;
|
|
|
|
import static com.moandjiezana.toml.ValueConverterUtils.INVALID;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
class ArrayConverter implements ValueConverter {
|
|
|
|
static final ArrayConverter ARRAY_PARSER = new ArrayConverter();
|
|
|
|
private static final ValueConverters VALUE_CONVERTERS = new ValueConverters();
|
|
|
|
@Override
|
|
public boolean canConvert(String s) {
|
|
return s.startsWith("[");
|
|
}
|
|
|
|
@Override
|
|
public Object convert(String s) {
|
|
AtomicInteger sharedIndex = new AtomicInteger(1);
|
|
Object converted = convert(s, sharedIndex);
|
|
|
|
char[] chars = s.toCharArray();
|
|
|
|
for (int i = sharedIndex.incrementAndGet(); i < chars.length; i++) {
|
|
char c = chars[i];
|
|
|
|
if (c == '#') {
|
|
break;
|
|
}
|
|
|
|
if (!Character.isWhitespace(c)) {
|
|
return INVALID;
|
|
}
|
|
}
|
|
|
|
return converted;
|
|
}
|
|
|
|
Object convert(String s, AtomicInteger sharedIndex) {
|
|
char[] chars = s.toCharArray();
|
|
List<Object> arrayItems = new ArrayList<Object>();
|
|
boolean terminated = false;
|
|
StringType stringType = StringType.NONE;
|
|
StringBuilder current = new StringBuilder();
|
|
|
|
for (; sharedIndex.get() < chars.length; sharedIndex.incrementAndGet()) {
|
|
int i = sharedIndex.get();
|
|
char c = chars[sharedIndex.get()];
|
|
|
|
if (stringType == StringType.NONE) {
|
|
if (c == ',') {
|
|
if (current.toString().trim().length() > 0) {
|
|
arrayItems.add(current.toString());
|
|
}
|
|
current = new StringBuilder();
|
|
continue;
|
|
}
|
|
|
|
if (c == '[') {
|
|
sharedIndex.incrementAndGet();
|
|
arrayItems.add(convert(s, sharedIndex));
|
|
continue;
|
|
}
|
|
|
|
if (c == ']') {
|
|
terminated = true;
|
|
if (current.toString().trim().length() > 0) {
|
|
arrayItems.add(current.toString());
|
|
}
|
|
current = new StringBuilder();
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (c == '"' && chars[i - 1] != '\\' && !stringType.accepts(c)) {
|
|
if (chars.length > i + 2 && chars[i + 1] == c && chars[i + 2] == c) {
|
|
stringType = stringType.flip(StringType.MULTILINE);
|
|
} else {
|
|
stringType = stringType.flip(StringType.BASIC);
|
|
}
|
|
}
|
|
|
|
if (c == '\'' && !stringType.accepts(c)) {
|
|
if (chars.length > i + 2 && chars[i + 1] == c && chars[i + 2] == c) {
|
|
stringType = stringType.flip(StringType.MULTILINE_LITERAL);
|
|
} else {
|
|
stringType = stringType.flip(StringType.LITERAL);
|
|
}
|
|
}
|
|
|
|
current.append(c);
|
|
}
|
|
|
|
if (!terminated) {
|
|
return INVALID;
|
|
}
|
|
|
|
return convertList(arrayItems);
|
|
}
|
|
|
|
private Object convertList(List<Object> tokens) {
|
|
ArrayList<Object> nestedList = new ArrayList<Object>();
|
|
|
|
for (Object token : tokens) {
|
|
if (token instanceof String) {
|
|
Object converted = VALUE_CONVERTERS.convert(((String) token).trim());
|
|
if (converted == INVALID) {
|
|
return INVALID;
|
|
}
|
|
if (isHomogenousArray(converted, nestedList)) {
|
|
nestedList.add(converted);
|
|
} else {
|
|
return INVALID;
|
|
}
|
|
} else if (token instanceof List) {
|
|
@SuppressWarnings("unchecked")
|
|
List<Object> convertedList = (List<Object>) token;
|
|
if (isHomogenousArray(convertedList, nestedList)) {
|
|
nestedList.add(convertedList);
|
|
} else {
|
|
return INVALID;
|
|
}
|
|
}
|
|
}
|
|
|
|
return nestedList;
|
|
}
|
|
|
|
private boolean isHomogenousArray(Object o, List<?> values) {
|
|
return values.isEmpty() || values.get(0).getClass().isAssignableFrom(o.getClass()) || o.getClass().isAssignableFrom(values.get(0).getClass());
|
|
}
|
|
|
|
private static enum StringType {
|
|
NONE, BASIC, LITERAL, MULTILINE, MULTILINE_LITERAL;
|
|
|
|
StringType flip(StringType to) {
|
|
return this == NONE ? to : NONE;
|
|
}
|
|
|
|
boolean accepts(char c) {
|
|
if (this == BASIC || this == MULTILINE) {
|
|
return c != '"';
|
|
}
|
|
|
|
if (this == LITERAL || this == MULTILINE_LITERAL) {
|
|
return c != '\'';
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private ArrayConverter() {}
|
|
}
|