Fix #6, testsuite implemented.
This commit is contained in:
parent
270302bb4b
commit
b359400c83
16 changed files with 268 additions and 3 deletions
|
@ -155,16 +155,20 @@ class ByteLayer {
|
|||
|
||||
void writeFloat(double value) {
|
||||
_ensureCapacity(4);
|
||||
// Round the float to 8 decimal places before writing
|
||||
value = double.parse(value.toStringAsFixed(8));
|
||||
_byteBuffer.buffer.asByteData().setFloat32(_position, value, Endian.big);
|
||||
_position += 2;
|
||||
_position += 4;
|
||||
}
|
||||
|
||||
double readFloat() {
|
||||
final value =
|
||||
_byteBuffer.buffer.asByteData().getFloat32(_position, Endian.big);
|
||||
|
||||
_position += 2;
|
||||
return value;
|
||||
_position += 4;
|
||||
|
||||
// Round the float to 8 decimal places after reading
|
||||
return double.parse(value.toStringAsFixed(8));
|
||||
}
|
||||
|
||||
void writeTagName(String name) {
|
||||
|
@ -234,4 +238,49 @@ class ByteLayer {
|
|||
_position += 8;
|
||||
return value;
|
||||
}
|
||||
|
||||
void writeVarLongNoZigZag(int value) {
|
||||
while (true) {
|
||||
if ((value & ~0x7F) == 0) {
|
||||
writeByte(value);
|
||||
return;
|
||||
}
|
||||
writeByte((value & 0x7F) | 0x80);
|
||||
value = value >> 7;
|
||||
}
|
||||
}
|
||||
|
||||
void writeVarLongZigZag(int value) {
|
||||
value = (value << 1) ^ (value >> 63);
|
||||
writeVarLongNoZigZag(value);
|
||||
}
|
||||
|
||||
void writeLongZigZag(int value) {
|
||||
value = (value << 1) & (value >> 63);
|
||||
_byteBuffer.buffer.asByteData().setInt64(_position, value, Endian.big);
|
||||
}
|
||||
|
||||
int readVarLongNoZigZag() {
|
||||
int result = 0;
|
||||
int shift = 0;
|
||||
int b;
|
||||
|
||||
do {
|
||||
b = readByte();
|
||||
result |= (b & 0x7F) << shift;
|
||||
shift += 7;
|
||||
} while ((b & 0x80) != 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int readVarLongZigZag() {
|
||||
int result = readVarLongNoZigZag();
|
||||
return (result >> 1) ^ -(result & 1);
|
||||
}
|
||||
|
||||
int readLongZigZag() {
|
||||
int value = readLong();
|
||||
return (value >> 1) ^ (-(value & 1));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,10 @@ abstract class Tag {
|
|||
return (_key == null ? "" : _key!);
|
||||
}
|
||||
|
||||
void setKey(String key) {
|
||||
_key = key;
|
||||
}
|
||||
|
||||
static Tag readNamedTag(ByteLayer data) {
|
||||
var type = data.readByte();
|
||||
if (type == 0) {
|
||||
|
@ -227,4 +231,61 @@ abstract class Tag {
|
|||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void prettyPrint(int indent, bool recurse);
|
||||
|
||||
static String getCanonicalName(TagType type) {
|
||||
switch (type) {
|
||||
case TagType.String:
|
||||
return "TAG_String";
|
||||
case TagType.List:
|
||||
return "TAG_List";
|
||||
case TagType.LongArray:
|
||||
return "TAG_LongArray";
|
||||
case TagType.Long:
|
||||
return "TAG_Long";
|
||||
case TagType.IntArray:
|
||||
return "TAG_IntArray";
|
||||
case TagType.Int:
|
||||
return "TAG_Int";
|
||||
case TagType.Compound:
|
||||
return "TAG_Compound";
|
||||
case TagType.ByteArray:
|
||||
return "TAG_ByteArray";
|
||||
case TagType.Byte:
|
||||
return "TAG_Byte";
|
||||
case TagType.Double:
|
||||
return "TAG_Double";
|
||||
case TagType.Float:
|
||||
return "TAG_Float";
|
||||
case TagType.Short:
|
||||
return "TAG_Short";
|
||||
case TagType.End:
|
||||
return "TAG_End";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class NBTAccountant {
|
||||
static int _prettyIndex = 0;
|
||||
static void printRead(Tag tag) {
|
||||
tag.prettyPrint(_prettyIndex, false);
|
||||
}
|
||||
|
||||
static void visitTag() {
|
||||
_prettyIndex++;
|
||||
}
|
||||
|
||||
static void leaveTag(Tag tag) {
|
||||
if (tag is CompoundTag || tag is ListTag) {
|
||||
if (tag is CompoundTag) {
|
||||
CompoundTag ct = tag as CompoundTag;
|
||||
ct.endPrettyPrint(_prettyIndex);
|
||||
} else if (tag is ListTag) {
|
||||
ListTag lt = tag as ListTag;
|
||||
lt.endPrettyPrint(_prettyIndex);
|
||||
}
|
||||
}
|
||||
_prettyIndex--;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,4 +34,16 @@ class ByteArrayTag extends Tag {
|
|||
TagType getTagType() {
|
||||
return TagType.ByteArray;
|
||||
}
|
||||
|
||||
@override
|
||||
void prettyPrint(int indent, bool recurse) {
|
||||
String array = "";
|
||||
for (int b in value) {
|
||||
array += "${b}, ";
|
||||
}
|
||||
array = array.substring(0, array.length - 2);
|
||||
|
||||
print(
|
||||
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: [${array}]");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,4 +28,10 @@ class ByteTag extends Tag {
|
|||
TagType getTagType() {
|
||||
return TagType.Byte;
|
||||
}
|
||||
|
||||
@override
|
||||
void prettyPrint(int indent, bool recurse) {
|
||||
print(
|
||||
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: ${value}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,24 @@ class CompoundTag extends Tag {
|
|||
void readValue(ByteLayer data) {
|
||||
value.clear();
|
||||
|
||||
NBTAccountant.visitTag();
|
||||
NBTAccountant.printRead(this);
|
||||
|
||||
while (true) {
|
||||
Tag tag = Tag.readNamedTag(data);
|
||||
if (tag.getType() == 0) {
|
||||
NBTAccountant.leaveTag(this);
|
||||
return;
|
||||
}
|
||||
|
||||
put(tag.getKey(), tag);
|
||||
|
||||
if (tag.getTagType() != TagType.Compound &&
|
||||
tag.getTagType() != TagType.List) {
|
||||
NBTAccountant.visitTag();
|
||||
NBTAccountant.printRead(tag);
|
||||
NBTAccountant.leaveTag(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,6 +45,7 @@ class CompoundTag extends Tag {
|
|||
|
||||
void put(String name, Tag tag) {
|
||||
value[name] = tag;
|
||||
tag.setKey(name);
|
||||
}
|
||||
|
||||
bool contains(String name) {
|
||||
|
@ -57,4 +69,20 @@ class CompoundTag extends Tag {
|
|||
TagType getTagType() {
|
||||
return TagType.Compound;
|
||||
}
|
||||
|
||||
@override
|
||||
void prettyPrint(int indent, bool recurse) {
|
||||
print(
|
||||
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: [${value.length} entries]");
|
||||
print("${"".padLeft(indent, '\t')}{");
|
||||
if (recurse) {
|
||||
for (Tag tag in value.values) {
|
||||
tag.prettyPrint(indent + 1, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void endPrettyPrint(int indent) {
|
||||
print("${"".padLeft(indent, '\t')}}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,4 +28,10 @@ class DoubleTag extends Tag {
|
|||
TagType getTagType() {
|
||||
return TagType.Double;
|
||||
}
|
||||
|
||||
@override
|
||||
void prettyPrint(int indent, bool recurse) {
|
||||
print(
|
||||
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: ${value}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,4 +14,9 @@ class EndTag extends Tag {
|
|||
TagType getTagType() {
|
||||
return TagType.End;
|
||||
}
|
||||
|
||||
@override
|
||||
void prettyPrint(int indent, bool recurse) {
|
||||
print("${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,4 +27,10 @@ class FloatTag extends Tag {
|
|||
TagType getTagType() {
|
||||
return TagType.Float;
|
||||
}
|
||||
|
||||
@override
|
||||
void prettyPrint(int indent, bool recurse) {
|
||||
print(
|
||||
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: ${value}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,4 +29,16 @@ class IntArrayTag extends Tag {
|
|||
TagType getTagType() {
|
||||
return TagType.IntArray;
|
||||
}
|
||||
|
||||
@override
|
||||
void prettyPrint(int indent, bool recurse) {
|
||||
String array = "";
|
||||
for (int b in value) {
|
||||
array += "${b}, ";
|
||||
}
|
||||
array = array.substring(0, array.length - 2);
|
||||
|
||||
print(
|
||||
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: [${array}]");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,4 +27,10 @@ class IntTag extends Tag {
|
|||
TagType getTagType() {
|
||||
return TagType.Int;
|
||||
}
|
||||
|
||||
@override
|
||||
void prettyPrint(int indent, bool recurse) {
|
||||
print(
|
||||
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: ${value}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,4 +62,18 @@ class ListTag extends Tag {
|
|||
int size() {
|
||||
return value.length;
|
||||
}
|
||||
|
||||
@override
|
||||
void prettyPrint(int indent, bool recurse) {
|
||||
print(
|
||||
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: [${value.length} entries]");
|
||||
print("${"".padLeft(indent, '\t')}[");
|
||||
for (Tag tag in value) {
|
||||
tag.prettyPrint(indent + 1, true);
|
||||
}
|
||||
}
|
||||
|
||||
void endPrettyPrint(int indent) {
|
||||
print("${"".padLeft(indent, '\t')}]");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,4 +37,16 @@ class LongArrayTag extends Tag {
|
|||
TagType getTagType() {
|
||||
return TagType.LongArray;
|
||||
}
|
||||
|
||||
@override
|
||||
void prettyPrint(int indent, bool recurse) {
|
||||
String array = "";
|
||||
for (int b in value) {
|
||||
array += "${b}, ";
|
||||
}
|
||||
array = array.substring(0, array.length - 2);
|
||||
|
||||
print(
|
||||
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: [${array}]");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,4 +27,10 @@ class LongTag extends Tag {
|
|||
TagType getTagType() {
|
||||
return TagType.Long;
|
||||
}
|
||||
|
||||
@override
|
||||
void prettyPrint(int indent, bool recurse) {
|
||||
print(
|
||||
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: ${value}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,4 +27,10 @@ class ShortTag extends Tag {
|
|||
TagType getTagType() {
|
||||
return TagType.Short;
|
||||
}
|
||||
|
||||
@override
|
||||
void prettyPrint(int indent, bool recurse) {
|
||||
print(
|
||||
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: ${value}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,4 +27,10 @@ class StringTag extends Tag {
|
|||
TagType getTagType() {
|
||||
return TagType.String;
|
||||
}
|
||||
|
||||
@override
|
||||
void prettyPrint(int indent, bool recurse) {
|
||||
print(
|
||||
"${"".padLeft(indent, '\t')}${Tag.getCanonicalName(getTagType())}: ${value}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'dart:io';
|
|||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:libac_flutter/nbt/NbtIo.dart';
|
||||
import 'package:libac_flutter/nbt/impl/CompoundTag.dart';
|
||||
import 'package:libac_flutter/nbt/impl/StringTag.dart';
|
||||
|
||||
void main() {
|
||||
test('read non-compressed helloworld NBT', () async {
|
||||
|
@ -14,4 +15,33 @@ void main() {
|
|||
|
||||
expect(tag.get("name")!.asString(), "Bananrama");
|
||||
});
|
||||
|
||||
test("write a hello-world NBT", () async {
|
||||
CompoundTag tag = CompoundTag();
|
||||
tag.setKey("hello world");
|
||||
tag.put("name", StringTag.valueOf("Bananrama"));
|
||||
|
||||
var path = "${Directory.current.path}/build/hello_world.nbt";
|
||||
await NbtIo.write(path, tag);
|
||||
expect(File(path).existsSync(), true);
|
||||
});
|
||||
|
||||
test('read non-compressed self-made helloworld NBT', () async {
|
||||
print("READING : ${Directory.current.path}/build/hello_world.nbt");
|
||||
CompoundTag tag =
|
||||
await NbtIo.read("${Directory.current.path}/build/hello_world.nbt");
|
||||
expect(tag.getKey(), "hello world");
|
||||
expect(tag.contains("name"), true);
|
||||
|
||||
expect(tag.get("name")!.asString(), "Bananrama");
|
||||
});
|
||||
|
||||
test('read compressed bigtest.nbt', () async {
|
||||
var path = "${Directory.current.path}/test/bigtest.nbt";
|
||||
CompoundTag tag = await NbtIo.read(path);
|
||||
expect(tag.getKey(), "Level");
|
||||
expect(tag.get("shortTest")!.asShort(), 32767);
|
||||
expect(tag.get("doubleTest")!.asDouble(), 0.4931287132182315);
|
||||
expect(tag.get("floatTest")!.asFloat(), 0.49823147);
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue