예제 #1
0
        private const uint WDB3FmtSig = 0x33424457; // WDB3

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

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

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

            RecordsCount = serializer.Records.Count - CopyData.Count;
            if (Flags.HasFlagExt(DB2Flags.Sparse))
            {
                StringTableSize = 0;
            }

            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(WDB3FmtSig);
                writer.Write(RecordsCount);
                writer.Write(FieldsCount);
                writer.Write(RecordSize);
                writer.Write(StringTableSize);
                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);

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

                // sparse data
                if (Flags.HasFlagExt(DB2Flags.Sparse))
                {
                    int  sparseCount   = maxIndex - minIndex + 1;
                    uint recordsOffset = (uint)(writer.BaseStream.Position + (sparseCount * 6));
                    WriteOffsetRecords(writer, serializer, recordsOffset, sparseCount);
                }

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

                // record data
                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);
                    }
                }

                // 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);
                    }
                }
            }
        }
예제 #2
0
        public Storage(Stream stream)
        {
            DB2Reader reader;

            using (stream)
                using (var bin = new BinaryReader(stream))
                {
                    var identifier = new string(bin.ReadChars(4));
                    stream.Position = 0;
                    switch (identifier)
                    {
                    case "WDC3":
                        reader = new WDC3Reader(stream);
                        break;

                    case "WDC2":
                    case "1SLC":
                        reader = new WDC2Reader(stream);
                        break;

                    case "WDC1":
                        reader = new WDC1Reader(stream);
                        break;

                    case "WDB6":
                        reader = new WDB6Reader(stream);
                        break;

                    case "WDB5":
                        reader = new WDB5Reader(stream);
                        break;

                    case "WDB4":
                        reader = new WDB4Reader(stream);
                        break;

                    case "WDB3":
                        reader = new WDB3Reader(stream);
                        break;

                    case "WDB2":
                        reader = new WDB2Reader(stream);
                        break;

                    case "WDBC":
                        reader = new WDBCReader(stream);
                        break;

                    default:
                        throw new Exception("DB type " + identifier + " is not supported!");
                    }
                }

            FieldInfo[] fields = typeof(T).GetFields();

            FieldCache <T>[] fieldCache = new FieldCache <T> [fields.Length];
            for (int i = 0; i < fields.Length; ++i)
            {
                bool indexMapAttribute = reader.Flags.HasFlagExt(DB2Flags.Index) ? Attribute.IsDefined(fields[i], typeof(IndexAttribute)) : false;
                fieldCache[i] = new FieldCache <T>(fields[i], indexMapAttribute);
            }

            Parallel.ForEach(reader.AsEnumerable(), new ParallelOptions()
            {
                MaxDegreeOfParallelism = 1
            }, row =>
            {
                T entry = new T();
                row.Value.GetFields(fieldCache, entry);
                lock (this)
                    Add(row.Value.Id, entry);
            });
        }
예제 #3
0
 public DB3Row(WDB3Reader reader, byte[] data)
 {
     m_reader = reader;
     m_data   = data;
 }