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.
328 lines
9.9 KiB
328 lines
9.9 KiB
using Apewer.Internals;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
|
|
namespace Apewer
|
|
{
|
|
|
|
/// <summary></summary>
|
|
public class BytesSet
|
|
{
|
|
|
|
private Dictionary<string, byte[]> _dict = new Dictionary<string, byte[]>();
|
|
|
|
private volatile Func<byte[], byte[]> _inbound = null;
|
|
private volatile Func<byte[], byte[]> _outbound = null;
|
|
|
|
/// <summary></summary>
|
|
public byte[] this[string key]
|
|
{
|
|
get { return GetValue(key); }
|
|
set { SetValue(key, value); }
|
|
}
|
|
|
|
/// <summary>设置或获取值入站的函数,设置时字典必须为空。设置为 Null 将忽略入站函数。</summary>
|
|
public Func<byte[], byte[]> Inbound
|
|
{
|
|
get { lock (_dict) return _inbound; }
|
|
set { lock (_dict) _inbound = value; }
|
|
}
|
|
|
|
/// <summary>设置或获取值出站的函数。设置为 Null 将忽略出站函数。</summary>
|
|
public Func<byte[], byte[]> Outbound
|
|
{
|
|
get { lock (_dict) return _outbound; }
|
|
set { lock (_dict) _outbound = value; }
|
|
}
|
|
|
|
/// <summary></summary>
|
|
public int Count
|
|
{
|
|
get
|
|
{
|
|
var count = 0;
|
|
lock (_dict) { count = _dict.Count; }
|
|
return count;
|
|
}
|
|
}
|
|
|
|
/// <summary></summary>
|
|
public List<string> Keys
|
|
{
|
|
get
|
|
{
|
|
var list = new List<string>();
|
|
lock (_dict)
|
|
{
|
|
list.AddRange(_dict.Keys);
|
|
}
|
|
return list;
|
|
}
|
|
}
|
|
|
|
/// <summary></summary>
|
|
public BytesSet() { }
|
|
|
|
/// <summary></summary>
|
|
public BytesSet(Func<byte[], byte[]> inbound, Func<byte[], byte[]> outbound)
|
|
{
|
|
_inbound = inbound;
|
|
_outbound = outbound;
|
|
}
|
|
|
|
/// <summary></summary>
|
|
public void Clear()
|
|
{
|
|
lock (_dict)
|
|
{
|
|
foreach (var key in _dict.Keys)
|
|
{
|
|
_dict[key] = null;
|
|
}
|
|
_dict.Clear();
|
|
}
|
|
}
|
|
|
|
/// <summary></summary>
|
|
public bool Import(byte[] data)
|
|
{
|
|
var memory = new MemoryStream();
|
|
lock (data)
|
|
{
|
|
if (data != null) memory.Write(data, 0, data.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 = BytesUtility.ToText(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;
|
|
}
|
|
|
|
/// <summary></summary>
|
|
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 = BytesUtility.FromText(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;
|
|
}
|
|
|
|
/// <summary></summary>
|
|
public bool Contains(string key)
|
|
{
|
|
if (key == null) return false;
|
|
var contains = false;
|
|
lock (_dict)
|
|
{
|
|
contains = _dict.ContainsKey(key);
|
|
}
|
|
return contains;
|
|
}
|
|
|
|
/// <summary></summary>
|
|
public byte[] GetValue(string key)
|
|
{
|
|
var k = key;
|
|
var v = Constant.EmptyBytes;
|
|
if (k == null) return v;
|
|
lock (_dict)
|
|
{
|
|
if (_dict.ContainsKey(k)) v = _dict[k];
|
|
}
|
|
if (_outbound != null)
|
|
{
|
|
v = _outbound(v);
|
|
if (v == null) v = Constant.EmptyBytes;
|
|
}
|
|
return v;
|
|
}
|
|
|
|
/// <summary></summary>
|
|
public bool SetValue(string key, byte[] value)
|
|
{
|
|
var k = key;
|
|
var v = Constant.EmptyBytes;
|
|
if (k == null) return false;
|
|
lock (value)
|
|
{
|
|
if (value != null) v = BytesUtility.Clone(value);
|
|
}
|
|
if (_inbound != null)
|
|
{
|
|
v = _inbound(v);
|
|
if (v == null) v = Constant.EmptyBytes;
|
|
}
|
|
lock (_dict)
|
|
{
|
|
if (_dict.ContainsKey(k)) _dict.Remove(k);
|
|
_dict.Add(k, v);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private static bool CanRead(Stream stream, int length)
|
|
{
|
|
if (length < 0) return false;
|
|
if (stream == null) return false;
|
|
if (stream.CanRead == false) return false;
|
|
if (stream.Position + length > stream.Length) return false;
|
|
return true;
|
|
}
|
|
|
|
/// <summary>Int32 -> Byte[]</summary>
|
|
private static byte[] GetBytes(int value)
|
|
{
|
|
const int t3 = 256 * 256 * 256;
|
|
const int t2 = 256 * 256;
|
|
const int t1 = 256;
|
|
|
|
byte[] bs = { 0, 0, 0, 0 };
|
|
|
|
if (value >= 0)
|
|
{
|
|
int vint = value;
|
|
|
|
bs[0] = (byte)(vint / t3);
|
|
vint = vint % t3;
|
|
|
|
bs[1] = (byte)(vint / t2);
|
|
vint = vint % t2;
|
|
|
|
bs[2] = (byte)(vint / t1);
|
|
vint = vint % t1;
|
|
|
|
bs[3] = (byte)(vint);
|
|
}
|
|
else
|
|
{
|
|
int minusInt = Math.Abs(value + 1);
|
|
var minusBytes = GetBytes(minusInt);
|
|
bs[0] = (byte)(255 - minusBytes[0]);
|
|
bs[1] = (byte)(255 - minusBytes[1]);
|
|
bs[2] = (byte)(255 - minusBytes[2]);
|
|
bs[3] = (byte)(255 - minusBytes[3]);
|
|
}
|
|
|
|
return bs;
|
|
}
|
|
|
|
/// <summary>Byte[] -> Int32</summary>
|
|
private static Int32 GetInt32(byte[] value)
|
|
{
|
|
if (value.Length == 4)
|
|
{
|
|
const int t3 = 256 * 256 * 256;
|
|
const int t2 = 256 * 256;
|
|
const int t1 = 256;
|
|
|
|
if (value[0] <= 127)
|
|
{
|
|
int[] vis = { 0, 0, 0, 0 };
|
|
vis[0] = value[0] * t3;
|
|
vis[1] = value[1] * t2;
|
|
vis[2] = value[2] * t1;
|
|
vis[3] = value[3];
|
|
int vr = vis[0] + vis[1] + vis[2] + vis[3];
|
|
return vr;
|
|
}
|
|
else
|
|
{
|
|
if ((value[0] == 128) && (value[1] == 0) && (value[2] == 0) && (value[3] == 0))
|
|
{
|
|
return int.MinValue;
|
|
}
|
|
else
|
|
{
|
|
var bytes = new byte[4];
|
|
bytes[0] = (byte)(255 - value[0]);
|
|
bytes[1] = (byte)(255 - value[1]);
|
|
bytes[2] = (byte)(255 - value[2]);
|
|
bytes[3] = (byte)(255 - value[3]);
|
|
int vminusint = 0 - 1 - GetInt32(bytes);
|
|
return vminusint;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|