
com.tmiyapub.parser.KeyValueLogParser Maven / Gradle / Ivy
package com.tmiyapub.parser;
import com.tmiyapub.parser.exception.IllegalCharacterException;
import java.util.HashMap;
import java.util.Map;
/**
* a parser for log contains both key and value.
*/
public class KeyValueLogParser {
private String source;
private boolean doesWantComma = false;
private boolean permitToOmitQuote = false;
public KeyValueLogParser(String source) {
this.source = source;
}
public KeyValueLogParser(String source, boolean doesWantComma) {
this.source = source;
this.doesWantComma = doesWantComma;
}
public KeyValueLogParser(String source, boolean doesWantComma, boolean permitToOmitQuote) {
this.source = source;
this.doesWantComma = doesWantComma;
this.permitToOmitQuote = permitToOmitQuote;
}
public enum ParseMode {
DEFAULT, WANT_EQ, WANT_QUOTE_OR_VALUE, WANT_VALUE, WANT_QUOTE, QUOTED, ESCAPED, WANT_COMMA, WANT_NEXT_NAME
}
/**
* parse the source string and make a map
*
* @param index starting point on the string
* @param map translated from source
* @exception IllegalCharacterException to notify an illegal format
*/
public void parse(int index, Map map) throws IllegalCharacterException {
int i = index;
ParseMode mode = ParseMode.DEFAULT;
StringBuffer buffer = new StringBuffer();
String name = null;
Character quote = null;
while (i < source.length()) {
char c = source.charAt(i);
switch (mode) {
case DEFAULT:
if (c == ' ' || c == '\t') {
name = buffer.toString();
buffer = new StringBuffer();
mode = ParseMode.WANT_EQ;
} else if (c == '=') {
name = buffer.toString();
buffer = new StringBuffer();
if (permitToOmitQuote) {
mode = ParseMode.WANT_QUOTE_OR_VALUE;
} else {
mode = ParseMode.WANT_QUOTE;
}
} else if (c == '\"' || c == '\'') {
throw new IllegalCharacterException(i, c, mode, "unexpected quote character in key name.");
} else {
buffer.append(c);
}
break;
case WANT_EQ:
if (c == '=') {
if (permitToOmitQuote) {
mode = ParseMode.WANT_QUOTE_OR_VALUE;
} else {
mode = ParseMode.WANT_QUOTE;
}
} else if (c == ' ' || c == '\t') {
// do nothing
} else {
throw new IllegalCharacterException(i, c, mode, "unexpected quote character after key name.");
}
break;
case WANT_QUOTE_OR_VALUE:
if (c == '\'' || c == '\"') {
quote = c;
mode = ParseMode.QUOTED;
} else if (c == ' ' || c == '\t') {
// do nothing
} else {
buffer.append(c);
mode = ParseMode.WANT_VALUE;
}
break;
case WANT_VALUE:
if (c == ' ' || c == '\t') {
if (name == null) {
throw new UnknownError("impossible");
}
map.put(name, buffer.toString());
if (doesWantComma) {
mode = ParseMode.WANT_COMMA;
} else {
mode = ParseMode.WANT_NEXT_NAME;
}
buffer = new StringBuffer();
} else {
buffer.append(c);
}
break;
case WANT_QUOTE:
if (c == '\'' || c == '\"') {
quote = c;
mode = ParseMode.QUOTED;
} else if (c == ' ' || c == '\t') {
// do nothing
} else {
throw new IllegalCharacterException(i, c, mode, "unexpected quote character after equal.");
}
break;
case QUOTED:
if (quote == null) {
throw new UnknownError("impossible");
} else if (quote.equals(c)) {
if (name == null) {
throw new UnknownError("impossible");
}
map.put(name, buffer.toString());
if (doesWantComma) {
mode = ParseMode.WANT_COMMA;
} else {
mode = ParseMode.WANT_NEXT_NAME;
}
buffer = new StringBuffer();
} else if (c == '\\') {
mode = ParseMode.ESCAPED;
} else {
buffer.append(c);
}
break;
case ESCAPED:
if (c == 't') {
buffer.append('\t');
} else if (c == 'b') {
buffer.append('\b');
} else if (c == 'n') {
buffer.append('\n');
} else if (c == 'r') {
buffer.append('\r');
} else if (c == 'f') {
buffer.append('\f');
} else if (c == '\'') {
buffer.append('\'');
} else if (c == '\"') {
buffer.append('\"');
} else if (c == '\'') {
buffer.append('\'');
} else if (c == 'x') {
String xx = source.substring(i + 1, i + 3);
buffer.append((char)Integer.parseInt(xx, 16));
i += 2;
} else {
throw new IllegalCharacterException(i, c, mode, "unknown escape sequence.");
}
mode = ParseMode.QUOTED;
break;
case WANT_COMMA:
if (c == ' ' || c == '\t') {
// do nothing
} else if (c == ',') {
mode = ParseMode.WANT_NEXT_NAME;
} else {
throw new IllegalCharacterException(i, c, mode, "only comma wanted.");
}
break;
case WANT_NEXT_NAME:
if (c == ' ' || c == '\t') {
// do nothing
} else {
mode = ParseMode.DEFAULT;
i--; // redo this character in DEFAULT mode.
}
break;
default:
throw new UnknownError("impossible");
}
i++;
}
if (mode != ParseMode.WANT_NEXT_NAME && mode != ParseMode.WANT_COMMA) {
throw new IllegalCharacterException(i, null, mode, "Unexpected end of source.");
}
}
/**
* parse the source string and make a map
*
* @return map translated from source
* @exception IllegalCharacterException to notify an illegal format
*/
public Map parse() throws IllegalCharacterException {
Map map = new HashMap<>();
this.parse(0, map);
return map;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy