private static CpkColumnInfo ReadColumn(BinaryReaderX tableBr, BinaryReaderX stringBr, BinaryReaderX dataBr) { // Read column info var flags = tableBr.ReadByte(); var nameOffset = tableBr.ReadInt32(); // Resolve final information var name = CpkSupport.ReadString(stringBr, nameOffset); var storage = (CpkColumnStorage)(flags >> 4); var type = (CpkDataType)(flags & 0xF); switch (storage) { case CpkColumnStorage.Const: return(CpkColumnInfo.CreateConst(name, CpkValue.Read(type, tableBr, stringBr, dataBr))); case CpkColumnStorage.Default: return(CpkColumnInfo.CreateZero(name, type)); case CpkColumnStorage.Row: return(CpkColumnInfo.CreateRow(name, type)); default: throw new InvalidOperationException($"Unknown storage type '{storage}'."); } }
public void Write(BinaryWriterX bw, StringWriter writer, ref long tablePosition, ref long dataPosition, long dataOffset) { bw.BaseStream.Position = tablePosition; switch (Type) { case CpkDataType.UInt8: bw.Write((byte)_value); break; case CpkDataType.SInt8: bw.Write((sbyte)_value); break; case CpkDataType.UInt16: bw.Write((ushort)_value); break; case CpkDataType.SInt16: bw.Write((short)_value); break; case CpkDataType.UInt32: bw.Write((uint)_value); break; case CpkDataType.SInt32: bw.Write((int)_value); break; case CpkDataType.UInt64: bw.Write((ulong)_value); break; case CpkDataType.SInt64: bw.Write((long)_value); break; case CpkDataType.Float: bw.Write((float)_value); break; case CpkDataType.String: bw.Write((int)writer.WriteString((string)_value)); break; case CpkDataType.Data: bw.Write((int)(dataPosition - dataOffset)); bw.Write(((byte[])_value).Length); CpkSupport.WriteData(bw, dataPosition, (byte[])_value); dataPosition = bw.BaseStream.Position; break; default: throw new InvalidOperationException($"'{Type}' not supported."); } tablePosition += GetSize(); }
public long WriteString(string value) { if (_cachedStrings.ContainsKey(value)) { return(_cachedStrings[value]); } _cachedStrings[value] = _stringPosition; var bkPos = _bw.BaseStream.Position; CpkSupport.WriteString(_bw, _stringOffset + _stringPosition, value); _stringPosition = _bw.BaseStream.Position - _stringOffset; _bw.BaseStream.Position = bkPos; return(_cachedStrings[value]); }
public static CpkTable Create(Stream utfStream, string tableMagic) { // Read table info using var utfBr = new BinaryReaderX(utfStream, ByteOrder.BigEndian); var tableInfo = utfBr.ReadType <CpkTableInfo>(); // Create readers var tableStream = new SubStream(utfStream, 0x8, tableInfo.tableSize); var stringStream = new SubStream(tableStream, tableInfo.stringsOffset, tableInfo.binaryOffset - tableInfo.stringsOffset); var dataStream = new SubStream(tableStream, tableInfo.binaryOffset, tableInfo.tableSize - tableInfo.binaryOffset); using var tableBr = new BinaryReaderX(tableStream, ByteOrder.BigEndian); using var stringBr = new BinaryReaderX(stringStream, ByteOrder.BigEndian); using var dataBr = new BinaryReaderX(dataStream, ByteOrder.BigEndian); // Read table name var name = CpkSupport.ReadString(stringBr, tableInfo.nameOffset); // Read columns tableStream.Position = 0x18; var columns = new CpkColumnInfo[tableInfo.columnCount]; for (var i = 0; i < tableInfo.columnCount; i++) { columns[i] = ReadColumn(tableBr, stringBr, dataBr); } // Read rows tableStream.Position = tableInfo.valuesOffset; var rows = new CpkRow[tableInfo.rowCount]; for (var i = 0; i < tableInfo.rowCount; i++) { rows[i] = ReadRow(tableBr, stringBr, dataBr, columns); } return(new CpkTable(tableMagic, name, rows)); }
public static CpkValue Read(CpkDataType type, BinaryReaderX br, BinaryReaderX stringBr, BinaryReaderX dataBr) { switch (type) { case CpkDataType.UInt8: return(new CpkValue(type) { _value = br.ReadByte() }); case CpkDataType.SInt8: return(new CpkValue(type) { _value = br.ReadSByte() }); case CpkDataType.UInt16: return(new CpkValue(type) { _value = br.ReadUInt16() }); case CpkDataType.SInt16: return(new CpkValue(type) { _value = br.ReadInt16() }); case CpkDataType.UInt32: return(new CpkValue(type) { _value = br.ReadUInt32() }); case CpkDataType.SInt32: return(new CpkValue(type) { _value = br.ReadInt32() }); case CpkDataType.UInt64: return(new CpkValue(type) { _value = br.ReadUInt64() }); case CpkDataType.SInt64: return(new CpkValue(type) { _value = br.ReadInt64() }); case CpkDataType.Float: return(new CpkValue(type) { _value = br.ReadSingle() }); case CpkDataType.String: return(new CpkValue(type) { _value = CpkSupport.ReadString(stringBr, br.ReadInt32()) }); case CpkDataType.Data: return(new CpkValue(type) { _value = CpkSupport.ReadBytes(dataBr, br.ReadInt32(), br.ReadInt32()) }); default: throw new InvalidOperationException($"'{type}' not supported."); } }