blob: c6cffcb70e21a8c0fbb81f54a5d144d8b55b0e3e [file] [log] [blame] [raw]
package net.querz.nbt.io;
import net.querz.io.MaxDepthIO;
import net.querz.nbt.tag.ByteArrayTag;
import net.querz.nbt.tag.ByteTag;
import net.querz.nbt.tag.CompoundTag;
import net.querz.nbt.tag.DoubleTag;
import net.querz.nbt.tag.EndTag;
import net.querz.nbt.tag.FloatTag;
import net.querz.nbt.tag.IntArrayTag;
import net.querz.nbt.tag.IntTag;
import net.querz.nbt.tag.ListTag;
import net.querz.nbt.tag.LongArrayTag;
import net.querz.nbt.tag.LongTag;
import net.querz.nbt.tag.ShortTag;
import net.querz.nbt.tag.StringTag;
import net.querz.nbt.tag.Tag;
import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Array;
import java.util.Map;
import java.util.regex.Pattern;
/**
* SNBTWriter creates an SNBT String.
*
* */
public final class SNBTWriter implements MaxDepthIO {
private static final Pattern NON_QUOTE_PATTERN = Pattern.compile("[a-zA-Z_.+\\-]+");
private Writer writer;
private SNBTWriter(Writer writer) {
this.writer = writer;
}
public static void write(Tag<?> tag, Writer writer, int maxDepth) throws IOException {
new SNBTWriter(writer).writeAnything(tag, maxDepth);
}
public static void write(Tag<?> tag, Writer writer) throws IOException {
write(tag, writer, Tag.DEFAULT_MAX_DEPTH);
}
private void writeAnything(Tag<?> tag, int maxDepth) throws IOException {
switch (tag.getID()) {
case EndTag.ID:
//do nothing
break;
case ByteTag.ID:
writer.append(Byte.toString(((ByteTag) tag).asByte())).write('b');
break;
case ShortTag.ID:
writer.append(Short.toString(((ShortTag) tag).asShort())).write('s');
break;
case IntTag.ID:
writer.write(Integer.toString(((IntTag) tag).asInt()));
break;
case LongTag.ID:
writer.append(Long.toString(((LongTag) tag).asLong())).write('l');
break;
case FloatTag.ID:
writer.append(Float.toString(((FloatTag) tag).asFloat())).write('f');
break;
case DoubleTag.ID:
writer.append(Double.toString(((DoubleTag) tag).asDouble())).write('d');
break;
case ByteArrayTag.ID:
writeArray(((ByteArrayTag) tag).getValue(), ((ByteArrayTag) tag).length(), "B");
break;
case StringTag.ID:
writer.write(escapeString(((StringTag) tag).getValue()));
break;
case ListTag.ID:
writer.write('[');
for (int i = 0; i < ((ListTag<?>) tag).size(); i++) {
writer.write(i == 0 ? "" : ",");
writeAnything(((ListTag<?>) tag).get(i), decrementMaxDepth(maxDepth));
}
writer.write(']');
break;
case CompoundTag.ID:
writer.write('{');
boolean first = true;
for (Map.Entry<String, Tag<?>> entry : (CompoundTag) tag) {
writer.write(first ? "" : ",");
writer.append(escapeString(entry.getKey())).write(':');
writeAnything(entry.getValue(), decrementMaxDepth(maxDepth));
first = false;
}
writer.write('}');
break;
case IntArrayTag.ID:
writeArray(((IntArrayTag) tag).getValue(), ((IntArrayTag) tag).length(), "I");
break;
case LongArrayTag.ID:
writeArray(((LongArrayTag) tag).getValue(), ((LongArrayTag) tag).length(), "L");
break;
default:
throw new IOException("unknown tag with id \"" + tag.getID() + "\"");
}
}
private void writeArray(Object array, int length, String prefix) throws IOException {
writer.append('[').append(prefix).write(';');
for (int i = 0; i < length; i++) {
writer.append(i == 0 ? "" : ",").write(Array.get(array, i).toString());
}
writer.write(']');
}
public static String escapeString(String s) {
if (!NON_QUOTE_PATTERN.matcher(s).matches()) {
StringBuilder sb = new StringBuilder();
sb.append('"');
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '\\' || c == '"') {
sb.append('\\');
}
sb.append(c);
}
sb.append('"');
return sb.toString();
}
return s;
}
}