private KVObject ReadBinaryValue(string name, KVType datatype, KVFlag flagInfo, BinaryReader reader, KVObject parent) { var currentOffset = reader.BaseStream.Position; switch (datatype) { case KVType.NULL: parent.AddProperty(name, MakeValue(datatype, null, flagInfo)); break; case KVType.BOOLEAN: if (currentBinaryBytesOffset > -1) { reader.BaseStream.Position = currentBinaryBytesOffset; } parent.AddProperty(name, MakeValue(datatype, reader.ReadBoolean(), flagInfo)); if (currentBinaryBytesOffset > -1) { currentBinaryBytesOffset++; reader.BaseStream.Position = currentOffset; } break; case KVType.BOOLEAN_TRUE: parent.AddProperty(name, MakeValue(datatype, true, flagInfo)); break; case KVType.BOOLEAN_FALSE: parent.AddProperty(name, MakeValue(datatype, false, flagInfo)); break; case KVType.INT64_ZERO: parent.AddProperty(name, MakeValue(datatype, 0L, flagInfo)); break; case KVType.INT64_ONE: parent.AddProperty(name, MakeValue(datatype, 1L, flagInfo)); break; case KVType.INT64: if (currentEightBytesOffset > 0) { reader.BaseStream.Position = currentEightBytesOffset; } parent.AddProperty(name, MakeValue(datatype, reader.ReadInt64(), flagInfo)); if (currentEightBytesOffset > 0) { currentEightBytesOffset = reader.BaseStream.Position; reader.BaseStream.Position = currentOffset; } break; case KVType.UINT64: if (currentEightBytesOffset > 0) { reader.BaseStream.Position = currentEightBytesOffset; } parent.AddProperty(name, MakeValue(datatype, reader.ReadUInt64(), flagInfo)); if (currentEightBytesOffset > 0) { currentEightBytesOffset = reader.BaseStream.Position; reader.BaseStream.Position = currentOffset; } break; case KVType.INT32: parent.AddProperty(name, MakeValue(datatype, reader.ReadInt32(), flagInfo)); break; case KVType.UINT32: parent.AddProperty(name, MakeValue(datatype, reader.ReadUInt32(), flagInfo)); break; case KVType.DOUBLE: if (currentEightBytesOffset > 0) { reader.BaseStream.Position = currentEightBytesOffset; } parent.AddProperty(name, MakeValue(datatype, reader.ReadDouble(), flagInfo)); if (currentEightBytesOffset > 0) { currentEightBytesOffset = reader.BaseStream.Position; reader.BaseStream.Position = currentOffset; } break; case KVType.DOUBLE_ZERO: parent.AddProperty(name, MakeValue(datatype, 0.0D, flagInfo)); break; case KVType.DOUBLE_ONE: parent.AddProperty(name, MakeValue(datatype, 1.0D, flagInfo)); break; case KVType.STRING: var id = reader.ReadInt32(); parent.AddProperty(name, MakeValue(datatype, id == -1 ? string.Empty : stringArray[id], flagInfo)); break; case KVType.BINARY_BLOB: var length = reader.ReadInt32(); if (currentBinaryBytesOffset > -1) { reader.BaseStream.Position = currentBinaryBytesOffset; } parent.AddProperty(name, MakeValue(datatype, reader.ReadBytes(length), flagInfo)); if (currentBinaryBytesOffset > -1) { currentBinaryBytesOffset = reader.BaseStream.Position; reader.BaseStream.Position = currentOffset + 4; } break; case KVType.ARRAY: var arrayLength = reader.ReadInt32(); var array = new KVObject(name, true); for (var i = 0; i < arrayLength; i++) { ParseBinaryKV3(reader, array, true); } parent.AddProperty(name, MakeValue(datatype, array, flagInfo)); break; case KVType.ARRAY_TYPED: var typeArrayLength = reader.ReadInt32(); var(subType, subFlagInfo) = ReadType(reader); var typedArray = new KVObject(name, true); for (var i = 0; i < typeArrayLength; i++) { ReadBinaryValue(name, subType, subFlagInfo, reader, typedArray); } parent.AddProperty(name, MakeValue(datatype, typedArray, flagInfo)); break; case KVType.OBJECT: var objectLength = reader.ReadInt32(); var newObject = new KVObject(name, false); for (var i = 0; i < objectLength; i++) { ParseBinaryKV3(reader, newObject, false); } if (parent == null) { parent = newObject; } else { parent.AddProperty(name, MakeValue(datatype, newObject, flagInfo)); } break; default: throw new InvalidDataException($"Unknown KVType {datatype} for field '{name}' on byte {reader.BaseStream.Position - 1}"); } return(parent); }
private KVObject ParseBinaryKV3(BinaryReader reader, KVObject parent, bool inArray = false) { string name = null; if (!inArray) { var stringID = reader.ReadInt32(); name = (stringID == -1) ? string.Empty : stringArray[stringID]; } var datatype = reader.ReadByte(); var flagInfo = KVFlag.None; if ((datatype & 0x80) > 0) { datatype &= 0x7F; //Remove the flag bit. flagInfo = (KVFlag)reader.ReadByte(); } switch (datatype) { case (byte)KVType.NULL: parent.AddProperty(name, MakeValue(datatype, null, flagInfo)); break; case (byte)KVType.BOOLEAN: parent.AddProperty(name, MakeValue(datatype, reader.ReadBoolean(), flagInfo)); break; case (byte)KVType.INTEGER: parent.AddProperty(name, MakeValue(datatype, reader.ReadInt64(), flagInfo)); break; case (byte)KVType.DOUBLE: parent.AddProperty(name, MakeValue(datatype, reader.ReadDouble(), flagInfo)); break; case (byte)KVType.STRING: var id = reader.ReadInt32(); parent.AddProperty(name, MakeValue(datatype, id == -1 ? string.Empty : stringArray[id], flagInfo)); break; case (byte)KVType.ARRAY: var arrayLength = reader.ReadInt32(); //UInt or Int? var array = new KVObject(name, true); for (var i = 0; i < arrayLength; i++) { ParseBinaryKV3(reader, array, true); } parent.AddProperty(name, MakeValue(datatype, array, flagInfo)); break; case (byte)KVType.OBJECT: var objectLength = reader.ReadInt32(); //UInt or Int? var newObject = new KVObject(name, false); for (var i = 0; i < objectLength; i++) { ParseBinaryKV3(reader, newObject, false); } if (parent == null) { parent = newObject; } else { parent.AddProperty(name, MakeValue(datatype, newObject, flagInfo)); } break; default: throw new InvalidDataException(string.Format("Unknown KVType {0}", datatype)); } return(parent); }