Example #1
0
        private const uint WDB4FmtSig = 0x34424457; // WDB4

        public WDB4Writer(WDB4Reader reader, IDictionary <int, T> storage, Stream stream) : base(reader)
        {
            // always 2 empties
            StringTableSize++;

            WDB4RowSerializer <T> serializer = new WDB4RowSerializer <T>(this);

            serializer.Serialize(storage);
            serializer.GetCopyRows();

            RecordsCount = serializer.Records.Count - CopyData.Count;

            using (var writer = new BinaryWriter(stream))
            {
                int minIndex      = storage.Keys.Min();
                int maxIndex      = storage.Keys.Max();
                int copyTableSize = Flags.HasFlagExt(DB2Flags.Sparse) ? 0 : CopyData.Count * 8;

                writer.Write(WDB4FmtSig);
                writer.Write(RecordsCount);
                writer.Write(FieldsCount);
                writer.Write(RecordSize);
                writer.Write(StringTableSize); // if flags & 0x01 != 0, offset to the offset_map
                writer.Write(reader.TableHash);
                writer.Write(reader.Build);
                writer.Write((uint)DateTimeOffset.UtcNow.ToUnixTimeSeconds());
                writer.Write(minIndex);
                writer.Write(maxIndex);
                writer.Write(reader.Locale);
                writer.Write(copyTableSize);
                writer.Write((uint)Flags);

                if (storage.Count == 0)
                {
                    return;
                }

                // record data
                uint recordsOffset = (uint)writer.BaseStream.Position;
                foreach (var record in serializer.Records)
                {
                    if (!CopyData.ContainsKey(record.Key))
                    {
                        record.Value.CopyTo(writer.BaseStream);
                    }
                }

                // string table
                if (!Flags.HasFlagExt(DB2Flags.Sparse))
                {
                    writer.WriteCString("");
                    foreach (var str in StringTableStingAsKeyPosAsValue)
                    {
                        writer.WriteCString(str.Key);
                    }
                }

                // sparse data
                if (Flags.HasFlagExt(DB2Flags.Sparse))
                {
                    // change the StringTableSize to the offset_map position
                    long oldPos = writer.BaseStream.Position;
                    writer.BaseStream.Position = 16;
                    writer.Write((uint)oldPos);
                    writer.BaseStream.Position = oldPos;

                    WriteOffsetRecords(writer, serializer, recordsOffset, maxIndex - minIndex + 1);
                }

                // secondary key
                if (Flags.HasFlagExt(DB2Flags.SecondaryKey))
                {
                    WriteSecondaryKeyData(writer, storage, maxIndex - minIndex + 1);
                }

                // index table
                if (Flags.HasFlagExt(DB2Flags.Index))
                {
                    writer.WriteArray(serializer.Records.Keys.Except(CopyData.Keys).ToArray());
                }

                // copy table
                if (!Flags.HasFlagExt(DB2Flags.Sparse))
                {
                    foreach (var copyRecord in CopyData)
                    {
                        writer.Write(copyRecord.Key);
                        writer.Write(copyRecord.Value);
                    }
                }
            }
        }