You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

310 lines
9.7 KiB

using Apewer;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace Apewer.Internals
{
internal class BytesDictionary
{
private Dictionary<string, byte[]> _dict = new Dictionary<string, byte[]>();
private volatile Func<byte[], byte[]> _valueinbound = null;
private volatile Func<byte[], byte[]> _valueoutbound = null;
/// <summary>设置或获取值入站的函数,设置时字典必须为空。设置为 Null 将忽略入站函数。</summary>
public Func<byte[], byte[]> Inbound
{
get { lock (_dict) return _valueinbound; }
set { lock (_dict) _valueinbound = value; }
}
/// <summary>设置或获取值出站的函数。设置为 Null 将忽略出站函数。</summary>
public Func<byte[], byte[]> 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<string> Keys
{
get
{
var list = new List<string>();
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<byte[], byte[]> argValueInbound, Func<byte[], byte[]> 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;
}
/// <summary>Int32 -> Byte[]</summary>
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;
}
/// <summary>Byte[] -> Int32</summary>
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;
}
}
}