/// <summary> /// Loads the storage from a <see cref="System.IO.Stream"/>. /// </summary> /// <param name="stream"> /// The <see cref="System.IO.Stream"/> from which the storage should be loaded. /// </param> /// <param name="flags"> /// The <see cref="DBFilesClient.NET.LoadFlags"/> to be used when loading. /// </param> public unsafe virtual void Load(Stream stream, LoadFlags flags) { GenerateLoadMethod(); byte[] headerBytes; byte[] data; byte[] pool; fixed(byte *headerPtr = headerBytes = new byte[DBCHeader.Size]) { if (stream.Read(headerBytes, 0, DBCHeader.Size) != DBCHeader.Size) { throw new IOException("Failed to read the DBC header."); } var header = (DBCHeader *)headerPtr; if (!flags.HasFlag(LoadFlags.IgnoreWrongFourCC) && header->FourCC != 0x43424457) { throw new ArgumentException("This is not a valid DBC file."); } if (header->RecordSize != m_entrySize) { throw new ArgumentException("This DBC file has wrong record size (" + header->RecordSize + ", expected is " + m_entrySize + ")."); } m_records = header->Records; int index, size; index = 0; size = header->Records * header->RecordSize; data = new byte[size]; while (index < size) { index += stream.Read(data, index, size - index); } index = 0; size = header->StringPoolSize; pool = new byte[size]; while (index < size) { index += stream.Read(pool, index, size - index); } } fixed(byte *pdata_ = data) { byte *pdata = pdata_; if (m_records > 0) { uint minId = uint.MaxValue; uint maxId = uint.MinValue; byte *pdata2 = pdata; for (int i = 0; i < m_records; i++) { uint id = *(uint *)pdata2; if (minId > id) { minId = id; } if (maxId < id) { maxId = id; } pdata2 += m_entrySize; } this.Resize(minId, maxId); } fixed(byte *ppool = m_haveString?pool : null) { sbyte * spool = (sbyte *)ppool; int poolLen = pool.Length; StringGetter strGetter = offset => LazyCString.LoadString(spool, poolLen, offset); bool ignoreLazyCStrings = !flags.HasFlag(LoadFlags.LazyCStrings); for (int i = 0; i < m_records; i++) { var entry = (T)m_ctor.Invoke(null); m_loadMethod(pdata, pool, strGetter, entry, ignoreLazyCStrings); uint id = *(uint *)pdata; m_entries[id - m_minId] = entry; pdata += m_entrySize; } } } }
public override unsafe void Load(Stream stream, LoadFlags flags) { GenerateLoadMethod(); byte[] headerBytes; byte[] data; byte[] pool; fixed(byte *headerPtr = headerBytes = new byte[DB2Header.Size]) { if (stream.Read(headerBytes, 0, DB2Header.Size) != DB2Header.Size) { throw new IOException("Failed to read the DB2 header."); } var header = (DB2Header *)headerPtr; if (!flags.HasFlag(LoadFlags.IgnoreWrongFourCC) && header->FourCC != 0x32424457) { throw new ArgumentException("This is not a valid DB2 file."); } if (header->RecordSize != m_entrySize) { throw new ArgumentException("This DB2 file has wrong record size (" + m_entrySize + ", expected is " + header->RecordSize + ")."); } m_records = header->Records; this.Hash = header->Hash; this.Build = header->Build; if (header->Build > 12880) { fixed(byte *extHeaderPtr = headerBytes = new byte[DB2ExtendedHeader.Size]) { if (stream.Read(headerBytes, 0, DB2ExtendedHeader.Size) != DB2ExtendedHeader.Size) { throw new IOException("Failed to read the extended DB2 header."); } var extHeader = (DB2ExtendedHeader *)extHeaderPtr; this.Locale = extHeader->Locale; if (extHeader->MaxId != 0) { int diff; checked { diff = (int)(extHeader->MaxId - extHeader->MinId + 1) * 6; } if (stream.CanSeek) { stream.Seek(diff, SeekOrigin.Current); } else { var dummy = new byte[4096]; while (diff > 0) { diff -= stream.Read(dummy, 0, Math.Min(diff, 4096)); } } } } } int index, size; index = 0; size = header->Records * header->RecordSize; data = new byte[size]; while (index < size) { index += stream.Read(data, index, size - index); } index = 0; size = header->StringPoolSize; pool = new byte[size]; while (index < size) { index += stream.Read(pool, index, size - index); } } fixed(byte *pdata_ = data) { byte *pdata = pdata_; if (m_records > 0) this.Resize(*(uint *)pdata, *(uint *)(pdata + m_entrySize * (m_records - 1))); fixed(byte *ppool = m_haveString?pool : null) { sbyte * spool = (sbyte *)ppool; int poolLen = pool.Length; StringGetter strGetter = offset => LazyCString.LoadString(spool, poolLen, offset); bool ignoreLazyCStrings = !flags.HasFlag(LoadFlags.LazyCStrings); for (int i = 0; i < m_records; i++) { var entry = (T)m_ctor.Invoke(null); m_loadMethod(pdata, pool, strGetter, entry, ignoreLazyCStrings); uint id = *(uint *)pdata; m_entries[id - m_minId] = entry; pdata += m_entrySize; } } } }