using Apewer; using System; using System.Collections.Generic; using System.IO; using System.Text; namespace Apewer.Internals { internal class BytesDictionary { private Dictionary _dict = new Dictionary(); private volatile Func _valueinbound = null; private volatile Func _valueoutbound = null; /// 设置或获取值入站的函数,设置时字典必须为空。设置为 Null 将忽略入站函数。 public Func Inbound { get { lock (_dict) return _valueinbound; } set { lock (_dict) _valueinbound = value; } } /// 设置或获取值出站的函数。设置为 Null 将忽略出站函数。 public Func Outbound { get { lock (_dict) return _valueoutbound; } set { lock (_dict) _valueoutbound = value; } } public int Count { get { var count = 0; lock (_dict) { count = _dict.Count; } return count; } } public List Keys { get { var list = new List(); lock (_dict) { list.AddRange(_dict.Keys); } return list; } } public void Clear() { lock (_dict) { foreach (var key in _dict.Keys) { _dict[key] = null; } _dict.Clear(); } } public bool Import(byte[] argData) { var memory = new MemoryStream(); lock (argData) { if (argData != null) memory.Write(argData, 0, argData.Length); BytesUtility.ResetPosition(memory); } if (memory.Length < 4) return false; var count = 0; var first = true; while (true) { if (!CanRead(memory, 4)) break; if (first) { var buffer = new byte[4]; memory.Read(buffer, 0, 4); count = GetInt32(buffer); first = false; } else { // Read Key Length var keylength = 0; { if (!CanRead(memory, 4)) break; var buffer = new byte[4]; memory.Read(buffer, 0, 4); keylength = GetInt32(buffer); } // Read Key Data var key = Constant.EmptyString; if (keylength > 1) { if (!CanRead(memory, keylength)) break; var buffer = new byte[keylength]; memory.Read(buffer, 0, keylength); key = TextUtility.FromBytes(buffer); } // Read Value Length var valuelength = 0; { if (!CanRead(memory, 4)) break; var buffer = new byte[4]; memory.Read(buffer, 0, 4); valuelength = GetInt32(buffer); } // Read Key Data var value = Constant.EmptyBytes; if (valuelength > 1) { if (!CanRead(memory, valuelength)) break; var buffer = new byte[valuelength]; memory.Read(buffer, 0, valuelength); value = BytesUtility.Clone(buffer); } if (_dict.ContainsKey(key)) continue; _dict.Add(key, value); if (_dict.Count >= count) break; } } return count == _dict.Count; } public byte[] Export() { var memory = new MemoryStream(); lock (_dict) { var count = _dict.Count; var countbytes = GetBytes(count); memory.Write(countbytes, 0, countbytes.Length); foreach (var pair in _dict) { var keydata = TextUtility.Bytes(pair.Key); var keycount = GetBytes(keydata.Length); memory.Write(keycount, 0, keycount.Length); if (keydata.Length > 0) memory.Write(keydata, 0, keydata.Length); var valuedata = pair.Value ?? Constant.EmptyBytes; var valuecount = GetBytes(valuedata.Length); memory.Write(valuecount, 0, valuecount.Length); if (valuedata.Length > 0) memory.Write(valuedata, 0, valuedata.Length); } } var data = memory.ToArray(); memory.Dispose(); return data; } public bool Contains(string argKey) { if (argKey == null) return false; var contains = false; lock (_dict) { contains = _dict.ContainsKey(argKey); } return contains; } public byte[] GetValue(string argKey) { var key = argKey; var value = Constant.EmptyBytes; if (key == null) return value; lock (_dict) { if (_dict.ContainsKey(key)) value = _dict[key]; } if (_valueoutbound != null) { value = _valueoutbound(value); if (value == null) value = Constant.EmptyBytes; } return value; } public bool SetValue(string argKey, byte[] argValue) { var key = argKey; var value = Constant.EmptyBytes; if (key == null) return false; lock (argValue) { if (argValue != null) value = BytesUtility.Clone(argValue); } if (_valueinbound != null) { value = _valueinbound(value); if (value == null) value = Constant.EmptyBytes; } lock (_dict) { if (_dict.ContainsKey(key)) _dict.Remove(key); _dict.Add(key, value); } return true; } public BytesDictionary() { } public BytesDictionary(Func argValueInbound, Func argValueOutbound) { _valueinbound = argValueInbound; _valueoutbound = argValueOutbound; } private static bool CanRead(Stream argStream, int argLength) { if (argLength < 0) return false; if (argStream == null) return false; if (argStream.CanRead == false) return false; if (argStream.Position + argLength > argStream.Length) return false; return true; } /// Int32 -> Byte[] private static byte[] GetBytes(int argValue) { const int t3 = 256 * 256 * 256; const int t2 = 256 * 256; const int t1 = 256; byte[] vbs = { 0, 0, 0, 0 }; if (argValue >= 0) { int vint = argValue; vbs[0] = (byte)(vint / t3); vint = vint % t3; vbs[1] = (byte)(vint / t2); vint = vint % t2; vbs[2] = (byte)(vint / t1); vint = vint % t1; vbs[3] = (byte)(vint); } else { int vminusint = Math.Abs(argValue + 1); var vminusbs = GetBytes(vminusint); vbs[0] = (byte)(255 - vminusbs[0]); vbs[1] = (byte)(255 - vminusbs[1]); vbs[2] = (byte)(255 - vminusbs[2]); vbs[3] = (byte)(255 - vminusbs[3]); } return vbs; } /// Byte[] -> Int32 private static Int32 GetInt32(byte[] argValue) { if (argValue.Length == 4) { const int t3 = 256 * 256 * 256; const int t2 = 256 * 256; const int t1 = 256; if (argValue[0] <= 127) { int[] vis = { 0, 0, 0, 0 }; vis[0] = argValue[0] * t3; vis[1] = argValue[1] * t2; vis[2] = argValue[2] * t1; vis[3] = argValue[3]; int vr = vis[0] + vis[1] + vis[2] + vis[3]; return vr; } else { if ((argValue[0] == 128) && (argValue[1] == 0) && (argValue[2] == 0) && (argValue[3] == 0)) { return int.MinValue; } else { var vbs = new byte[4]; vbs[0] = (byte)(255 - argValue[0]); vbs[1] = (byte)(255 - argValue[1]); vbs[2] = (byte)(255 - argValue[2]); vbs[3] = (byte)(255 - argValue[3]); int vminusint = 0 - 1 - GetInt32(vbs); return vminusint; } } } return 0; } } }