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
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;
|
|
}
|
|
|
|
}
|
|
|
|
}
|