SimpleJavaEngine/src/main/java/speiger/src/coreengine/utils/io/dataTag/parsing/DataTagParser.java

331 lines
9.2 KiB
Java

package speiger.src.coreengine.utils.io.dataTag.parsing;
import java.io.IOException;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import speiger.src.collections.bytes.lists.ByteArrayList;
import speiger.src.collections.bytes.lists.ByteList;
import speiger.src.collections.doubles.lists.DoubleArrayList;
import speiger.src.collections.doubles.lists.DoubleList;
import speiger.src.collections.floats.lists.FloatArrayList;
import speiger.src.collections.floats.lists.FloatList;
import speiger.src.collections.ints.lists.IntArrayList;
import speiger.src.collections.ints.lists.IntList;
import speiger.src.collections.longs.lists.LongArrayList;
import speiger.src.collections.longs.lists.LongList;
import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.collections.objects.lists.ObjectList;
import speiger.src.collections.shorts.lists.ShortArrayList;
import speiger.src.collections.shorts.lists.ShortList;
import speiger.src.coreengine.utils.io.dataTag.DataTag;
import speiger.src.coreengine.utils.io.dataTag.array.ByteArrayTag;
import speiger.src.coreengine.utils.io.dataTag.array.DoubleArrayTag;
import speiger.src.coreengine.utils.io.dataTag.array.FloatArrayTag;
import speiger.src.coreengine.utils.io.dataTag.array.IntArrayTag;
import speiger.src.coreengine.utils.io.dataTag.array.LongArrayTag;
import speiger.src.coreengine.utils.io.dataTag.array.MediumArrayTag;
import speiger.src.coreengine.utils.io.dataTag.array.ShortArrayTag;
import speiger.src.coreengine.utils.io.dataTag.array.StringArrayTag;
import speiger.src.coreengine.utils.io.dataTag.simple.ByteTag;
import speiger.src.coreengine.utils.io.dataTag.simple.DoubleTag;
import speiger.src.coreengine.utils.io.dataTag.simple.FloatTag;
import speiger.src.coreengine.utils.io.dataTag.simple.IntTag;
import speiger.src.coreengine.utils.io.dataTag.simple.LongTag;
import speiger.src.coreengine.utils.io.dataTag.simple.MediumTag;
import speiger.src.coreengine.utils.io.dataTag.simple.PrimitiveTag;
import speiger.src.coreengine.utils.io.dataTag.simple.ShortTag;
import speiger.src.coreengine.utils.io.dataTag.simple.StringTag;
import speiger.src.coreengine.utils.io.dataTag.special.ListTag;
import speiger.src.coreengine.utils.io.dataTag.special.MapTag;
import speiger.src.coreengine.utils.io.streams.StringReader;
public class DataTagParser
{
private static final Pattern BYTE_TYPE = Pattern.compile("[-+]?(?:[0-9]+)b", 2);
private static final Pattern SHORT_TYPE = Pattern.compile("[-+]?(?:[0-9]+)s", 2);
private static final Pattern MEDIUM_TYPE = Pattern.compile("[-+]?(?:[0-9]+)m", 2);
private static final Pattern INT_TYPE = Pattern.compile("[-+]?(?:[0-9]+)i", 2);
private static final Pattern INT_TYPE_DEFAULT = Pattern.compile("[-+]?(?:[0-9]+)");
private static final Pattern LONG_TYPE = Pattern.compile("[-+]?(?:[0-9]+)l", 2);
private static final Pattern FLOAT_TYPE = Pattern.compile("[-+]?(?:[0-9]+[.]?|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?f", 2);
private static final Pattern DOUBLE_TYPE = Pattern.compile("[-+]?(?:[0-9]+[.]?|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?d", 2);
private static final Pattern DOUBLE_TYPE_DEFAULT = Pattern.compile("[-+]?(?:[0-9]+[.]|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?", 2);
StringReader reader;
public DataTagParser(String s)
{
reader = new StringReader(s.replaceAll("\\§\\<(.*?)\\>", ""));
}
public DataTag readTagSave()
{
try
{
return readTag();
}
catch(Exception e)
{
return null;
}
}
public DataTag readTag() throws IOException
{
reader.skipEmpty();
if(!reader.canRead())
{
throw new IOException("Nothing to parse found");
}
else
{
char c0 = reader.peek();
if(c0 == '{')
{
return readMap();
}
else
{
return c0 == '[' ? readList() : readTagType();
}
}
}
public MapTag readMap() throws IOException
{
requirePresent('{');
reader.skipEmpty();
MapTag map = new MapTag();
while(reader.canRead() && reader.peek() != '}')
{
reader.skipEmpty();
int last = reader.getIndex();
String s = reader.readString();
if(s.isEmpty())
{
throw new IOException("Expected Key at " + last);
}
requirePresent(':');
map.putTag(s, readTag());
reader.skipEmpty();
if(!reader.isPresent(','))
{
break;
}
reader.skipEmpty();
}
requirePresent('}');
return map;
}
protected DataTag readList() throws IOException
{
return reader.canRead(3) && !StringReader.isQuoteCharacter(reader.peek(1)) && reader.peek(2) == ';' ? readArrayTag() : readListTag();
}
protected DataTag readTagType() throws IOException
{
reader.skipEmpty();
int last = reader.getIndex();
if(StringReader.isQuoteCharacter(reader.peek()))
{
return new StringTag(reader.readQuotedText());
}
else
{
String s = reader.readString();
if(s.isEmpty())
{
throw new IOException("Expected Value at " + last);
}
else
{
return tag(s);
}
}
}
public ListTag readListTag() throws IOException
{
requirePresent('[');
reader.skipEmpty();
if(!reader.canRead())
{
throw new IOException("Expected List Data");
}
else
{
ListTag list = new ListTag();
while(reader.peek() != ']')
{
list.add(readTag());
if(!reader.isPresent(','))
{
break;
}
reader.skipEmpty();
if(!reader.canRead())
{
throw new IOException("Expected Another Element");
}
}
requirePresent(']');
return list;
}
}
protected DataTag readArrayTag() throws IOException
{
requirePresent('[');
char type = reader.pull();
reader.skip();
reader.skipEmpty();
if(!reader.canRead())
{
throw new IOException("Out of Data!");
}
else if(type == 'B')
{
ByteList list = new ByteArrayList();
readArray(T -> list.add(T.asByte()), 1, PrimitiveTag.class);
return new ByteArrayTag(list.toByteArray());
}
else if(type == 'S')
{
ShortList list = new ShortArrayList();
readArray(T -> list.add(T.asShort()), 2, PrimitiveTag.class);
return new ShortArrayTag(list.toShortArray());
}
else if(type == 'M')
{
IntList list = new IntArrayList();
readArray(T -> list.add(T.asInt()), 3, PrimitiveTag.class);
return new MediumArrayTag(list.toIntArray());
}
else if(type == 'I')
{
IntList list = new IntArrayList();
readArray(T -> list.add(T.asInt()), 4, PrimitiveTag.class);
return new IntArrayTag(list.toIntArray());
}
else if(type == 'L')
{
LongList list = new LongArrayList();
readArray(T -> list.add(T.asLong()), 5, PrimitiveTag.class);
return new LongArrayTag(list.toLongArray());
}
else if(type == 'F')
{
FloatList list = new FloatArrayList();
readArray(T -> list.add(T.asFloat()), 6, PrimitiveTag.class);
return new FloatArrayTag(list.toFloatArray());
}
else if(type == 'D')
{
DoubleList list = new DoubleArrayList();
readArray(T -> list.add(T.asDouble()), 7, PrimitiveTag.class);
return new DoubleArrayTag(list.toDoubleArray());
}
else if(type == 'A')
{
ObjectList<String> list = new ObjectArrayList<String>();
readArray(T -> list.add(T.get()), 8, StringTag.class);
return new StringArrayTag(list.toArray(new String[list.size()]));
}
else
{
throw new IOException("Invalid Data Type: [Received=" + type + ", Valid=[B, S, M, I, L, F, D, A]");
}
}
protected <T extends DataTag> void readArray(Consumer<T> result, int type, Class<T> clz) throws IOException
{
while(true)
{
if(reader.peek() != ']')
{
DataTag tag = readTag();
if(tag.getId() != type)
{
throw new IOException("Mixing of ArrayTypes [Expected=" + DataTag.create((byte)type).getTypeName() + ", Present=" + tag.getTypeName() + "]");
}
result.accept(tag.cast());
reader.skipEmpty();
if(reader.isPresent(','))
{
reader.skipEmpty();
if(!reader.canRead())
{
throw new IOException("Expected Another Element");
}
continue;
}
}
requirePresent(']');
return;
}
}
protected DataTag tag(String s)
{
try
{
if(FLOAT_TYPE.matcher(s).matches())
{
return new FloatTag(Float.parseFloat(s.substring(0, s.length() - 1)));
}
if(BYTE_TYPE.matcher(s).matches())
{
return new ByteTag(Byte.parseByte(s.substring(0, s.length() - 1)));
}
if(LONG_TYPE.matcher(s).matches())
{
return new LongTag(Long.parseLong(s.substring(0, s.length() - 1)));
}
if(SHORT_TYPE.matcher(s).matches())
{
return new ShortTag(Short.parseShort(s.substring(0, s.length() - 1)));
}
if(MEDIUM_TYPE.matcher(s).matches())
{
return new MediumTag(Integer.parseInt(s.substring(0, s.length() - 1)));
}
if(INT_TYPE.matcher(s).matches())
{
return new IntTag(Integer.parseInt(s.substring(0, s.length() - 1)));
}
if(DOUBLE_TYPE.matcher(s).matches())
{
return new DoubleTag(Double.parseDouble(s.substring(0, s.length() - 1)));
}
if(DOUBLE_TYPE_DEFAULT.matcher(s).matches())
{
return new DoubleTag(Double.parseDouble(s));
}
if(INT_TYPE_DEFAULT.matcher(s).matches())
{
return new IntTag(Integer.parseInt(s));
}
if("true".equalsIgnoreCase(s))
{
return new ByteTag((byte)1);
}
if("false".equalsIgnoreCase(s))
{
return new ByteTag((byte)0);
}
}
catch(NumberFormatException e)
{
}
return new StringTag(s);
}
protected void requirePresent(char value)
{
reader.skipEmpty();
reader.requirePresent(value);
}
}