Consolidated all number parsing into NumberConverter

This commit is contained in:
moandji.ezana 2015-02-08 22:54:28 +02:00
parent 0dc5f6d206
commit 5d17559728
6 changed files with 116 additions and 155 deletions

View file

@ -1,70 +0,0 @@
package com.moandjiezana.toml;
class ExponentConverter implements ValueConverter {
public static final ExponentConverter EXPONENT_PARSER = new ExponentConverter();
@Override
public boolean canConvert(String s) {
char[] chars = s.toCharArray();
boolean whitespace = false;
boolean exponent = false;
boolean signable = true;
boolean decimal = false;
for (int i = 0; i < chars.length; i++) {
char c = chars[i];
if (Character.isDigit(c)) {
signable = false;
continue;
}
if (signable && (c == '+' || c == '-') && chars.length > i + 1 && Character.isDigit(chars[i + 1])) {
signable = false;
continue;
}
if (i > 0 && (c == 'E' || c == 'e')) {
signable = true;
exponent = true;
continue;
}
if (i > 0 && c == '.' && !decimal && !exponent) {
decimal = true;
continue;
}
if (Character.isWhitespace(c)) {
whitespace = true;
continue;
}
if (whitespace && c == '#') {
break;
}
return false;
}
return exponent && !signable;
}
@Override
public Object convert(String s) {
if (s.startsWith("+")) {
s = s.substring(1);
}
int startOfComment = s.indexOf('#');
if (startOfComment > -1) {
s = s.substring(0, startOfComment).trim();
}
String[] exponentString = s.split("[eE]");
return Double.parseDouble(exponentString[0]) * Math.pow(10, Double.parseDouble(exponentString[1]));
}
}

View file

@ -1,28 +0,0 @@
package com.moandjiezana.toml;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class FloatConverter implements ValueConverter {
public static final FloatConverter FLOAT_PARSER = new FloatConverter();
private static final Pattern FLOAT_REGEX = Pattern.compile("([+-]?\\d+\\.\\d+)(.*)");
@Override
public boolean canConvert(String s) {
Matcher matcher = FLOAT_REGEX.matcher(s);
return matcher.matches() && ValueConverterUtils.isComment(matcher.group(2));
}
@Override
public Object convert(String s) {
Matcher matcher = FLOAT_REGEX.matcher(s);
matcher.matches();
return Double.valueOf(matcher.group(1));
}
private FloatConverter() {}
}

View file

@ -1,53 +0,0 @@
package com.moandjiezana.toml;
class IntegerConverter implements ValueConverter {
static final IntegerConverter INTEGER_PARSER = new IntegerConverter();
@Override
public boolean canConvert(String s) {
char[] chars = s.toCharArray();
boolean whitespace = false;
for (int i = 0; i < chars.length; i++) {
char c = chars[i];
if (Character.isDigit(c)) {
continue;
}
if (i == 0 && (c == '+' || c == '-')) {
continue;
}
if (Character.isWhitespace(c)) {
whitespace = true;
continue;
}
if (whitespace && c == '#') {
return true;
}
return false;
}
return true;
}
@Override
public Object convert(String s) {
if (s.startsWith("+")) {
s = s.substring(1);
}
int startOfComment = s.indexOf('#');
if (startOfComment > -1) {
s = s.substring(0, startOfComment).trim();
}
return Long.valueOf(s);
}
private IntegerConverter() {}
}

View file

@ -0,0 +1,78 @@
package com.moandjiezana.toml;
import static com.moandjiezana.toml.ValueConverterUtils.INVALID;
class NumberConverter implements ValueConverter {
static final NumberConverter NUMBER_PARSER = new NumberConverter();
@Override
public boolean canConvert(String s) {
char firstChar = s.charAt(0);
return firstChar == '+' || firstChar == '-' || Character.isDigit(firstChar);
}
public static void main(String[] args) {
new NumberConverter().convert("5e+22");
}
@Override
public Object convert(String s) {
char[] chars = s.toCharArray();
boolean whitespace = false;
boolean signable = true;
boolean dottable = false;
boolean exponentable = false;
String type = "";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < chars.length; i++) {
char c = chars[i];
if (Character.isDigit(c)) {
sb.append(c);
signable = false;
if (type.isEmpty()) {
type = "integer";
dottable = true;
}
exponentable = !type.equals("exponent");
} else if ((c == '+' || c == '-') && signable && chars.length > i + 1) {
signable = false;
if (c == '-') {
sb.append('-');
}
} else if (c == '.' && dottable && chars.length > i + 1) {
sb.append('.');
type = "float";
dottable = false;
exponentable = false;
} else if ((c == 'E' || c == 'e') && exponentable && chars.length > i + 1) {
sb.append('E');
type = "exponent";
signable = true;
dottable = false;
exponentable = false;
} else if (Character.isWhitespace(c)) {
whitespace = true;
} else if (whitespace && c == '#') {
break;
} else {
type = "";
break;
}
}
if (type.equals("integer")) {
return Long.valueOf(sb.toString());
} else if (type.equals("float")) {
return Double.valueOf(sb.toString());
} else if (type.equals("exponent")) {
String[] exponentString = sb.toString().split("E");
return Double.parseDouble(exponentString[0]) * Math.pow(10, Double.parseDouble(exponentString[1]));
} else {
return INVALID;
}
}
}

View file

@ -3,19 +3,17 @@ package com.moandjiezana.toml;
import static com.moandjiezana.toml.ArrayConverter.ARRAY_PARSER;
import static com.moandjiezana.toml.BooleanConverter.BOOLEAN_PARSER;
import static com.moandjiezana.toml.DateConverter.DATE_PARSER;
import static com.moandjiezana.toml.ExponentConverter.EXPONENT_PARSER;
import static com.moandjiezana.toml.FloatConverter.FLOAT_PARSER;
import static com.moandjiezana.toml.IntegerConverter.INTEGER_PARSER;
import static com.moandjiezana.toml.LiteralStringConverter.LITERAL_STRING_PARSER;
import static com.moandjiezana.toml.MultilineLiteralStringConverter.MULTILINE_LITERAL_STRING_CONVERTER;
import static com.moandjiezana.toml.MultilineStringConverter.MULTILINE_STRING_PARSER;
import static com.moandjiezana.toml.NumberConverter.NUMBER_PARSER;
import static com.moandjiezana.toml.StringConverter.STRING_PARSER;
import static com.moandjiezana.toml.ValueConverterUtils.INVALID;
class ValueConverters {
private static final ValueConverter[] PARSERS = {
MULTILINE_STRING_PARSER, MULTILINE_LITERAL_STRING_CONVERTER, LITERAL_STRING_PARSER, STRING_PARSER, DATE_PARSER, EXPONENT_PARSER, INTEGER_PARSER, FLOAT_PARSER, BOOLEAN_PARSER, ARRAY_PARSER
MULTILINE_STRING_PARSER, MULTILINE_LITERAL_STRING_CONVERTER, LITERAL_STRING_PARSER, STRING_PARSER, DATE_PARSER, NUMBER_PARSER, BOOLEAN_PARSER, ARRAY_PARSER
};
public Object convert(String value) {

View file

@ -84,6 +84,12 @@ public class NumberTest {
new Toml().parse("answer = -.12345");
}
@Test(expected = IllegalStateException.class)
public void should_fail_on_float_with_sign_after_dot() {
new Toml().parse("answer = 1.-1");
new Toml().parse("answer = 1.+1");
}
@Test(expected = IllegalStateException.class)
public void should_fail_on_float_without_digits_after_dot() {
new Toml().parse("answer = 1.");
@ -93,4 +99,34 @@ public class NumberTest {
public void should_fail_on_negative_float_without_digits_after_dot() {
new Toml().parse("answer = -1.");
}
@Test(expected = IllegalStateException.class)
public void should_fail_on_exponent_without_digits_after_dot() {
new Toml().parse("answer = 1.E1");
}
@Test(expected = IllegalStateException.class)
public void should_fail_on_negative_exponent_without_digits_after_dot() {
new Toml().parse("answer = -1.E1");
}
@Test(expected = IllegalStateException.class)
public void should_fail_on_exponent_with_dot_in_exponent_part() {
new Toml().parse("answer = -1E1.0");
}
@Test(expected = IllegalStateException.class)
public void should_fail_on_exponent_without_numbers_after_E() {
new Toml().parse("answer = -1E");
}
@Test(expected = IllegalStateException.class)
public void should_fail_on_exponent_with_two_E() {
new Toml().parse("answer = -1E1E1");
}
@Test(expected = IllegalStateException.class)
public void should_fail_on_float_with_two_dots() {
new Toml().parse("answer = 1.1.1");
}
}