//Field vs offset vs Size using Map = Selector<string, int, int>; /// <summary> /// clase con los mapas de los archivos de la database /// </summary> internal class MappedFile { static bool hasLoadedMaps = false; const string MapsPath = "C:\\Database\\DBMaps\\"; /// <summary> /// table name vs fileMap /// </summary> static Dictionary<string, Map> DBMaps = new Dictionary<string, Map>(); static void GetMaps() { if (hasLoadedMaps) return; if (!Directory.Exists(MapsPath)) Directory.CreateDirectory(MapsPath); foreach (string file in Directory.GetFiles(MapsPath)) { if (file.EndsWith(".map")) { Map map = new Map(); StreamReader sr = new StreamReader(file); while (sr.Peek() > 0) { string line = sr.ReadLine(); if (line.Contains('=')) { string[] field = line.Split('='); map.TryAdd(field[0], int.Parse(field[1]), int.Parse(field[2])); } } string mapName = file.Substring(MapsPath.Length); mapName = mapName.Remove(mapName.Length - 4); DBMaps.Add(mapName, map); } } hasLoadedMaps = true; } public static Selector<string, int, int> GetMap(string table) { if (!hasLoadedMaps) GetMaps(); if (DBMaps.ContainsKey(table)) return DBMaps[table]; else throw new Exception("El mapa para la tabla " + table + " no ha sido creado!"); } }
/// <summary> /// Contiene el tipo de la variable y su longitudo maxima como string mas el caracter '>' /// </summary> internal class VariableSize { public const int Int8 = 4, Int16 = 6, Int32 = 11, Int64 = 20, SmallString = 30, MediumString = 65, BigString = 100; }
public class DBEngine : IDisposable { /// <summary> /// Obtiene el nombre del objeto que se esta manipulando /// </summary> public string CurrentObject { get; private set; } /// <summary> /// obtiene el nombre de la tabla a la que pertenece el objeto que se esta manipulando /// </summary> public string CurrentTable { get; private set; } const char NullChar = '~'; private Selector<string, int, int> FileMap; private FileStream fs; /// <summary> /// Crea una nueva instancia de DBEngine con la tabla seleccionada /// </summary> /// <param name="Object">tabla en la que se encuentra el objeto a manipular</param> public DBEngine(string Table) { FileMap = MappedFile.GetMap(Table); CurrentTable = Table; } /// <summary> /// Objeto a manipular por el DBEngine /// </summary> /// <param name="Object"></param> public DBEngine SelectObject(string Object) { CurrentObject = Object; fs = new FileStream(Constants.DatabaseFolder + CurrentTable + "\\" + CurrentObject + ".dbe", FileMode.OpenOrCreate); return this; } /// <summary> /// devuelve true si el objeto existe en la base de datos, o false si no exist /// </summary> /// <param name="Object"></param> /// <returns></returns> public bool Exist(string Object) { return File.Exists(Constants.DatabaseFolder + CurrentTable + "\\" + Object + ".dbe"); } /// <summary> /// Escribe el campo 'field' a la variable 'value' /// </summary> /// <param name="value"></param> /// <param name="field"></param> public void Write(object value, string field) { int size; FileMap.TryGetValue(field, out size); lock (fs) { StringBuilder sb = new StringBuilder(value.ToString(), size); sb.Append(NullChar, size - value.ToString().Length); int offset; if (FileMap.TryGetKey2(field, out offset)) { byte[] writeBuffer = Encoding.ASCII.GetBytes(sb.ToString()); fs.Seek(offset, SeekOrigin.Begin); fs.Write(writeBuffer, 0, size); fs.Flush(); } else throw new Exception("El campo " + field + " no existe en la tabla " + CurrentTable); } } private string MainRead(string field, int length) { lock (fs) { int offset; FileMap.TryGetKey2(field, out offset); StringBuilder sb = new StringBuilder(length); fs.Seek(offset, SeekOrigin.Begin); for (int i = 0; i < length; i++) { char e; e = (char)fs.ReadByte(); if (e == NullChar) break; else sb.Append(e); } return sb.ToString(); } } public bool ReadBool(string field) { return ReadByte(field) == 1; } public byte ReadByte(string field) { return byte.Parse(MainRead(field, VariableSize.Int8)); } public sbyte ReadSByte(string field) { return sbyte.Parse(MainRead(field, VariableSize.Int8)); } public short ReadInt16(string field) { return short.Parse(MainRead(field, VariableSize.Int16)); } public ushort ReadUInt16(string field) { return ushort.Parse(MainRead(field, VariableSize.Int16)); } public int ReadInt32(string field) { return int.Parse(MainRead(field, VariableSize.Int32)); } public uint ReadUInt32(string field) { return uint.Parse(MainRead(field, VariableSize.Int32)); } public long ReadInt64(string field) { return long.Parse(MainRead(field, VariableSize.Int64)); } public ulong ReadUInt64(string field) { return ulong.Parse(MainRead(field, VariableSize.Int64)); } /// <summary> /// Lee un String de 30 caracteres /// </summary> /// <param name="field"></param> /// <returns></returns> public string ReadSmallString(string field) { return MainRead(field, VariableSize.SmallString); } /// <summary> /// Lee un string de 65 caracteres /// </summary> /// <param name="field"></param> /// <returns></returns> public string ReadMediumString(string field) { return MainRead(field, VariableSize.MediumString); } /// <summary> /// Lee un string de 100 caracteres /// </summary> /// <param name="field"></param> /// <returns></returns> public string BigString(string field) { return MainRead(field, VariableSize.BigString); } /// <summary> /// Escribe los nombres de los campos y les asigna el valor nullChar('~'). /// </summary> public void Create() { int length; //int offset; System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); StringBuilder sb = new StringBuilder(); foreach (string field in FileMap.Keys1) { FileMap.TryGetValue(field, out length); sb.Append(field + '='); sb.Append(NullChar, length); sb.Append(Environment.NewLine); } byte[] writeBuffer = Encoding.ASCII.GetBytes(sb.ToString()); fs.Write(writeBuffer, 0, writeBuffer.Length); sw.Stop(); Output.Line(sw.ElapsedMilliseconds + "-" + sw.ElapsedTicks); } public void Dispose() { try { fs.Dispose(); fs.Close(); } catch { } } }
public class Selector<TKey1, TKey2, TValue> { ConcurrentDictionary<TKey1, TValue> Key1ToValue; ConcurrentDictionary<TKey2, TKey1> Key2ToKey1; ConcurrentDictionary<TKey1, TKey2> Key1ToKey2; public Selector() { Key1ToValue = new ConcurrentDictionary<TKey1, TValue>(); Key2ToKey1 = new ConcurrentDictionary<TKey2, TKey1>(); Key1ToKey2 = new ConcurrentDictionary<TKey1, TKey2>(); } public bool TryGetValue(TKey1 key, out TValue value) { return Key1ToValue.TryGetValue(key, out value); } public bool TryGetValue(TKey2 key2, out TValue value) { TKey1 key1; if (Key2ToKey1.TryGetValue(key2, out key1)) return Key1ToValue.TryGetValue(key1, out value); value = default(TValue); return false; } public bool TryGetKey1(TKey2 key2, out TKey1 value) { return Key2ToKey1.TryGetValue(key2, out value); } public bool TryGetKey2(TKey1 key1, out TKey2 value) { return Key1ToKey2.TryGetValue(key1, out value); } public bool TryAdd(TKey1 key1, TKey2 key2, TValue value) { return (Key1ToKey2.TryAdd(key1, key2) && Key1ToValue.TryAdd(key1, value) && Key2ToKey1.TryAdd(key2, key1)); } public bool TryRemove(TKey1 key1) { TValue deletedval; TKey1 deleted1; TKey2 key2; if (Key1ToKey2.TryRemove(key1, out key2)) return (Key2ToKey1.TryRemove(key2, out deleted1) && Key1ToValue.TryRemove(key1, out deletedval)); return false; } public bool ContainsKey1(TKey1 value) { return Key1ToValue.ContainsKey(value); } public bool ContainsKey2(TKey2 value) { return Key2ToKey1.ContainsKey(value); } public bool ContainsValue(TValue value) { return Key1ToValue.Values.Contains(value); } public ICollection<TKey1> Keys1 { get { return Key1ToKey2.Keys; } } public ICollection<TKey2> Keys2 { get { return Key2ToKey1.Keys; } } public ICollection<TValue> Values { get { return Key1ToValue.Values; } } }