magellan/Lucidiot.Raima/DatabaseSchema.cs

132 lines
4.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Text;
namespace Lucidiot.Raima {
public enum DatabaseVersion {
/// <summary>
/// Version 3.00, with a <c>V3.00 + 0x1A</c> file magic.
/// </summary>
V300
}
public class DatabaseSchema {
private short _pageSize = 512;
public short PageSize { get { return _pageSize; } }
public const DatabaseVersion Version = DatabaseVersion.V300;
public const string Magic = "V3.00\x1a";
public string DatabaseFileName;
public readonly IDatabaseStorage StorageMethod;
private List<FileEntry> _fileEntries = new List<FileEntry>();
public ReadOnlyCollection<FileEntry> FileEntries {
get { return _fileEntries.AsReadOnly(); }
}
private List<RecordEntry> _recordEntries = new List<RecordEntry>();
public ReadOnlyCollection<RecordEntry> RecordEntries {
get { return _recordEntries.AsReadOnly(); }
}
private List<FieldEntry> _fieldEntries = new List<FieldEntry>();
public ReadOnlyCollection<FieldEntry> FieldEntries {
get { return _fieldEntries.AsReadOnly(); }
}
private List<SetEntry> _setEntries = new List<SetEntry>();
public ReadOnlyCollection<SetEntry> SetEntries {
get { return _setEntries.AsReadOnly(); }
}
private List<MemberEntry> _memberEntries = new List<MemberEntry>();
public ReadOnlyCollection<MemberEntry> MemberEntries {
get { return _memberEntries.AsReadOnly(); }
}
private List<SortEntry> _sortEntries = new List<SortEntry>();
public ReadOnlyCollection<SortEntry> SortEntries {
get { return _sortEntries.AsReadOnly(); }
}
private List<KeyEntry> _keyEntries = new List<KeyEntry>();
public ReadOnlyCollection<KeyEntry> KeyEntries {
get { return _keyEntries.AsReadOnly(); }
}
public DatabaseSchema(string fileName, IDatabaseStorage storage) {
this.DatabaseFileName = fileName;
this.StorageMethod = storage;
}
public static DatabaseSchema Load(string fileName, IDatabaseStorage storage) {
if (!storage.CanRead)
throw new NotSupportedException("A readable storage method is required to load an existing database.");
DatabaseSchema ds = new DatabaseSchema(fileName, storage);
using (BinaryReader br = storage.GetReader(fileName)) {
ds.Parse(br);
}
return ds;
}
private void Parse(BinaryReader br) {
string foundMagic = new String(Encoding.ASCII.GetChars(br.ReadBytes(Magic.Length)));
if (foundMagic != Magic)
throw new InvalidDataException("Unexpected file magic: " + foundMagic);
short pageSize = br.ReadInt16();
if (pageSize % 512 != 0)
throw new ArgumentOutOfRangeException("Page size must be a multiple of 512 bytes.");
this._pageSize = pageSize;
short fileCount, recordCount, fieldCount, setCount, memberCount, sortCount, keyCount;
fileCount = br.ReadInt16();
recordCount = br.ReadInt16();
fieldCount = br.ReadInt16();
setCount = br.ReadInt16();
memberCount = br.ReadInt16();
sortCount = br.ReadInt16();
keyCount = br.ReadInt16();
_fileEntries.Capacity = Math.Max(_fileEntries.Capacity, fileCount);
for (ushort i = 0; i < fileCount; i++)
_fileEntries.Add(Helpers.ReadStruct<FileEntry>(br));
_recordEntries.Capacity = Math.Max(_recordEntries.Capacity, recordCount);
for (ushort i = 0; i < recordCount; i++)
_recordEntries.Add(Helpers.ReadStruct<RecordEntry>(br));
_fieldEntries.Capacity = Math.Max(_fieldEntries.Capacity, fieldCount);
for (ushort i = 0; i < fieldCount; i++)
_fieldEntries.Add(Helpers.ReadStruct<FieldEntry>(br));
_setEntries.Capacity = Math.Max(_setEntries.Capacity, setCount);
for (ushort i = 0; i < setCount; i++)
_setEntries.Add(Helpers.ReadStruct<SetEntry>(br));
_memberEntries.Capacity = Math.Max(_memberEntries.Capacity, memberCount);
for (ushort i = 0; i < memberCount; i++)
_memberEntries.Add(Helpers.ReadStruct<MemberEntry>(br));
_sortEntries.Capacity = Math.Max(_sortEntries.Capacity, sortCount);
for (ushort i = 0; i < sortCount; i++)
_sortEntries.Add(Helpers.ReadStruct<SortEntry>(br));
_keyEntries.Capacity = Math.Max(_keyEntries.Capacity, keyCount);
for (ushort i = 0; i < keyCount; i++)
_keyEntries.Add(Helpers.ReadStruct<KeyEntry>(br));
}
}
}