public void WriteField(string fieldName, Type fieldType) { if (status != Status.FieldCollection) { WriteStartFieldCollection(); } CriFieldFlag fieldFlag = (CriFieldFlag)Array.IndexOf(CriField.FieldTypes, fieldType) | CriFieldFlag.RowStorage; if (!string.IsNullOrEmpty(fieldName)) { fieldFlag |= CriFieldFlag.Name; } CriTableField field = new CriTableField { Flag = fieldFlag, Name = fieldName }; DataStream.WriteByte(destination, (byte)field.Flag); if (!string.IsNullOrEmpty(fieldName)) { WriteString(field.Name); } field.Offset = header.RowLength; switch (field.Flag & CriFieldFlag.TypeMask) { case CriFieldFlag.Byte: case CriFieldFlag.SByte: header.RowLength += 1; break; case CriFieldFlag.Int16: case CriFieldFlag.UInt16: header.RowLength += 2; break; case CriFieldFlag.Int32: case CriFieldFlag.UInt32: case CriFieldFlag.Single: case CriFieldFlag.String: header.RowLength += 4; break; case CriFieldFlag.Int64: case CriFieldFlag.UInt64: case CriFieldFlag.Double: case CriFieldFlag.Data: header.RowLength += 8; break; } fields.Add(field); header.FieldCount++; }
public void WriteField(string fieldName, Type fieldType, object defaultValue) { if (status != Status.FieldCollection) { WriteStartFieldCollection(); } CriFieldFlag fieldFlag = (CriFieldFlag)Array.IndexOf(CriField.FieldTypes, fieldType); if (!string.IsNullOrEmpty(fieldName)) { fieldFlag |= CriFieldFlag.Name; } if (defaultValue != null) { fieldFlag |= CriFieldFlag.DefaultValue; } CriTableField field = new CriTableField { Flag = fieldFlag, Name = fieldName, Value = defaultValue }; DataStream.WriteByte(destination, (byte)field.Flag); if (!string.IsNullOrEmpty(fieldName)) { WriteString(field.Name); } if (defaultValue != null) { WriteValue(defaultValue); } fields.Add(field); header.FieldCount++; }
private void ReadTable() { headerPosition = source.Position; if (!(header.Signature = DataStream.ReadBytes(source, 4)).SequenceEqual(CriTableHeader.SignatureBytes)) { MemoryStream unmaskedSource = new MemoryStream(); CriTableMasker.FindKeys(header.Signature, out uint x, out uint m); source.Seek(headerPosition, SeekOrigin.Begin); CriTableMasker.Mask(source, unmaskedSource, source.Length, x, m); // Close the old stream if (!leaveOpen) { source.Close(); } source = unmaskedSource; source.Seek(4, SeekOrigin.Begin); } header.Length = DataStream.ReadUInt32BE(source) + 0x8; header.UnknownByte = DataStream.ReadByte(source); header.EncodingType = DataStream.ReadByte(source); if (header.UnknownByte != 0) { throw new InvalidDataException($"Invalid byte ({header.UnknownByte}. Please report this error with the file(s)."); } switch (header.EncodingType) { case CriTableHeader.EncodingTypeShiftJis: encoding = Encoding.GetEncoding("shift-jis"); break; case CriTableHeader.EncodingTypeUtf8: encoding = Encoding.UTF8; break; default: throw new InvalidDataException($"Unknown encoding type ({header.EncodingType}). Please report this error with the file(s)."); } header.RowsPosition = (ushort)(DataStream.ReadUInt16BE(source) + 0x8); header.StringPoolPosition = DataStream.ReadUInt32BE(source) + 0x8; header.DataPoolPosition = DataStream.ReadUInt32BE(source) + 0x8; header.TableName = ReadString(); header.FieldCount = DataStream.ReadUInt16BE(source); header.RowLength = DataStream.ReadUInt16BE(source); header.RowCount = DataStream.ReadUInt32BE(source); uint offset = 0; for (ushort i = 0; i < header.FieldCount; i++) { CriTableField field = new CriTableField(); field.Flag = (CriFieldFlag)DataStream.ReadByte(source); if (field.Flag.HasFlag(CriFieldFlag.Name)) { field.Name = ReadString(); } if (field.Flag.HasFlag(CriFieldFlag.DefaultValue)) { if (field.Flag.HasFlag(CriFieldFlag.Data)) { field.Position = DataStream.ReadUInt32BE(source); field.Length = DataStream.ReadUInt32BE(source); } else { field.Value = ReadValue(field.Flag); } } // Not even per row, and not even constant value? Then there's no storage. else if (!field.Flag.HasFlag(CriFieldFlag.RowStorage) && !field.Flag.HasFlag(CriFieldFlag.DefaultValue)) { field.Value = CriField.NullValues[(byte)field.Flag & 0x0F]; } // Row storage, calculate the offset if (field.Flag.HasFlag(CriFieldFlag.RowStorage)) { field.Offset = offset; switch (field.Flag & CriFieldFlag.TypeMask) { case CriFieldFlag.Byte: case CriFieldFlag.SByte: offset += 1; break; case CriFieldFlag.Int16: case CriFieldFlag.UInt16: offset += 2; break; case CriFieldFlag.Int32: case CriFieldFlag.UInt32: case CriFieldFlag.Single: case CriFieldFlag.String: offset += 4; break; case CriFieldFlag.Int64: case CriFieldFlag.UInt64: case CriFieldFlag.Double: case CriFieldFlag.Data: offset += 8; break; } } fields.Add(field); } }