예제 #1
0
        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++;
        }
예제 #2
0
        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++;
        }
예제 #3
0
        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);
            }
        }