using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Reflection;
using System.Xml;
using CommonLang.Xml;
using System.IO.Compression;
namespace CommonLang.IO
{
public static class IOUtil
{
public static byte TryReadByte(Stream data)
{
int b = data.ReadByte();
if (b < 0) { throw new IOException("EOF of stream"); }
return (byte)b;
}
///
/// 从输入流复制到输出流
///
/// 输入流
/// 输出流
/// 总共复制多少字节
/// 进度回调,返回False表示终止进程
/// 缓冲区大小
///
public static bool ReadTo(Stream input, Stream output, long total_bytes, Predicate progress, int buffer_size = 16384)
{
byte[] io_buffer = new byte[buffer_size];
long total_readed = 0;
while (total_readed < total_bytes)
{
if (!progress(0)) return false;
int expect = (int)Math.Min(io_buffer.Length, total_bytes - total_readed);
int readed = input.Read(io_buffer, 0, expect);
total_readed += readed;
if (!progress(readed)) return false;
output.Write(io_buffer, 0, readed);
}
output.Flush();
return true;
}
public static byte[] ReadExpect(Stream input, int count)
{
if (count == 0) return new byte[0];
byte[] data = new byte[count];
ReadToEnd(input, data, 0, count);
return data;
}
public static void ReadToEnd(Stream input, byte[] data, int offset, int count)
{
if (count == 0) return;
int readed = input.Read(data, offset, count);
if (readed <= 0)
throw new IOException("EOF of stream");
while (readed < count)
{
int bytes = input.Read(data, offset + readed, count - readed);
if (bytes <= 0)
{
throw new IOException("EOF of stream");
}
readed += bytes;
}
}
public static void ReadToEnd(Stream src, Stream dst)
{
byte[] buffer = new byte[1024];
while (true)
{
int readed = src.Read(buffer, 0, buffer.Length);
if (readed > 0)
{
dst.Write(buffer, 0, readed);
}
else
{
break;
}
}
}
public static byte[] ReadToEnd(Stream src)
{
using (MemoryStream dst = new MemoryStream())
{
ReadToEnd(src, dst);
return dst.ToArray();
}
}
public static void WriteToEnd(Stream output, byte[] data, int offset, int count)
{
output.Write(data, offset, count);
}
public static T CloneIExternalizable(IExternalizableFactory decode, T src) where T : IExternalizable, new()
{
if (src != null)
{
T ret = new T();
{
using (MemoryStream ms = new MemoryStream())
{
src.WriteExternal(new OutputStream(ms, decode));
ms.Position = 0;
ret.ReadExternal(new InputStream(ms, decode));
}
}
return ret;
}
return default(T);
}
public static IExternalizable Clone(IExternalizableFactory decode, IExternalizable src)
{
IExternalizable ret = null;
if (src != null)
{
using (MemoryStream ms = new MemoryStream())
{
new OutputStream(ms, decode).PutExt(src);
ms.Position = 0;
ret = new InputStream(ms, decode).GetExtAny();
}
}
return ret;
}
public static byte[] LoadFromAssembly(Assembly assembly, string resource)
{
Stream stream = assembly.GetManifestResourceStream(resource);
byte[] ret = new byte[stream.Length];
/*stream.Read(ret, 0, ret.Length);*/
IOUtil.ReadToEnd(stream, ret, 0, ret.Length);
return ret;
}
public static byte[] ObjectToBin(IExternalizableFactory decode, IExternalizable ext)
{
using (MemoryStream ms = new MemoryStream())
{
OutputStream output = new OutputStream(ms, decode);
output.PutExt(ext);
int len = (int)ms.Position;
byte[] buffer = ms.GetBuffer();
Array.Resize(ref buffer, len);
return buffer;
}
}
public static T BinToObject(IExternalizableFactory decode, byte[] data) where T : IExternalizable, new()
{
if (data == null || data.Length == 0) return default(T);
using (MemoryStream ms = new MemoryStream(data))
{
var input = new InputStream(ms, decode);
return input.GetExt();
}
}
public static IExternalizable BinToObjectAny(IExternalizableFactory decode, byte[] data)
{
if (data == null || data.Length == 0) return null;
using (MemoryStream ms = new MemoryStream(data))
{
InputStream input = new InputStream(ms, decode);
return input.GetExtAny();
}
}
public static void Zip(Stream src, Stream dst)
{
GZipStream zipStream = null;
try
{
zipStream = new GZipStream(dst, CompressionMode.Compress, true);
byte[] buffer = new byte[Math.Min(1024, src.Length)];
while (true)
{
int bytesRead = src.Read(buffer, 0, buffer.Length);
if (bytesRead == 0)
break;
zipStream.Write(buffer, 0, bytesRead);
}
zipStream.Flush();
dst.Flush();
}
finally
{
if (zipStream != null) zipStream.Close();
}
}
public static void Unzip(Stream src, Stream dst)
{
GZipStream zipStream = null;
try
{
// Create a compression stream pointing to the destiantion stream
zipStream = new GZipStream(src, CompressionMode.Decompress, true);
// Read the footer to determine the length of the destiantion file
byte[] buffer = new byte[1024];
// Read the compressed data into the buffer
while (true)
{
int bytesRead = zipStream.Read(buffer, 0, buffer.Length);
if (bytesRead == 0)
break;
dst.Write(buffer, 0, bytesRead);
}
dst.Flush();
}
finally
{
if (zipStream != null) zipStream.Close();
}
}
public static byte[] Zip(byte[] data)
{
// Read in the compressed source stream
MemoryStream src = new MemoryStream(data);
MemoryStream dst = new MemoryStream(data.Length * 2);
try
{
Zip(src, dst);
byte[] ret = new byte[dst.Position];
Array.Copy(dst.GetBuffer(), 0, ret, 0, ret.Length);
return ret;
}
catch (Exception err)
{
Console.WriteLine(err.Message + "\r" + err.StackTrace);
return null;
}
finally
{
if (src != null) src.Close();
if (dst != null) dst.Close();
}
}
public static byte[] Unzip(byte[] data)
{
// Read in the compressed source stream
MemoryStream src = new MemoryStream(data);
MemoryStream dst = new MemoryStream(data.Length);
try
{
Unzip(src, dst);
byte[] ret = new byte[dst.Position];
Array.Copy(dst.GetBuffer(), 0, ret, 0, ret.Length);
return ret;
}
catch (Exception err)
{
Console.WriteLine(err.Message + "\r" + err.StackTrace);
return null;
}
finally
{
if (src != null) src.Close();
if (dst != null) dst.Close();
}
}
}
public interface IExternalizable
{
void WriteExternal(IOutputStream output);
void ReadExternal(IInputStream input);
}
public interface IExternalizableFactory
{
int GetTypeID(Type type);
Type GetType(int id);
}
public enum DataType : byte
{
NA = 0,
U8 = 1,
S8 = 2,
U16 = 3,
S16 = 4,
U32 = 5,
S32 = 6,
U64 = 7,
S64 = 8,
F32 = 9,
F64 = 10,
UTF = 11,
EXT = 12,
UC = 13,
}
public delegate T GetData();
public delegate void PutData(T v);
public abstract class IOStream
{
public static int DEFAULT_ARRAY_LIMIT = UInt16.MaxValue;
public static int DEFAULT_BYTES_LIMIT = 100 * 1024 * 1024;
public int ARRAY_LIMIT = DEFAULT_ARRAY_LIMIT;
public int BYTES_LIMIT = DEFAULT_BYTES_LIMIT;
}
public abstract class IOutputStream : IOStream
{
protected static System.Text.UTF8Encoding utfenc = new System.Text.UTF8Encoding(false);
public IOutputStream(IExternalizableFactory factory)
{
this.Factory = factory;
}
public IExternalizableFactory Factory { get; private set; }
#region _Abstract_
public abstract void PutBytes(byte[] bytes);
public abstract void PutRawData(byte[] bytes, int offset, int count);
public abstract void PutBool(bool value);
public abstract void PutU8(byte value);
public abstract void PutS8(sbyte value);
public abstract void PutU16(ushort value);
public abstract void PutS16(short value);
public abstract void PutU32(uint value);
public abstract void PutS32(int value);
public abstract void PutU64(ulong value);
public abstract void PutS64(long value);
public abstract void PutF32(float value);
public abstract void PutF64(double value);
public abstract void PutUnicode(char value);
public abstract void PutUTF(string str);
public abstract long GetBuffPos();
#endregion
#region _基础类型_
///
/// 写入可变长度32位
///
public void PutVU32(uint value)
{
PutVU64(value);
}
///
/// 写入可变长度32位
///
public void PutVS32(int value)
{
PutVS64(value);
}
///
/// 写入可变长度64位
///
public void PutVS64(long value)
{
ulong m;
if (value < 0)
{
m = (ulong)(((-value) << 1) | 1);
}
else
{
m = (ulong)(((value) << 1));
}
PutVU64(m);
}
///
/// 写入可变长度64位
///
public void PutVU64(ulong value)
{
do
{
byte b = (byte)(value & 0x7F);
value = (value >> 7);
if (value != 0)
{
b = (byte)(b | 0x80);
}
this.PutU8(b);
}
while (value != 0);
}
public void PutEnum8(ValueType enum8)
{
byte u8 = (byte)enum8;
PutU8(u8);
}
public void PutEnum32(ValueType enum32)
{
int s32 = (int)enum32;
PutS32(s32);
}
public void PutEnum8(T enum8)
{
byte u8 = Convert.ToByte(enum8);
PutU8(u8);
}
public void PutEnum32(T enum32)
{
int s32 = Convert.ToInt32(enum32);
PutS32(s32);
}
#endregion
#region _对象类型_
public void PutExt(IExternalizable value)
{
if (value != null)
{
int typeID = Factory.GetTypeID(value.GetType());
if (typeID != 0)
{
PutS32(typeID);
value.WriteExternal(this);
//if(typeID != 0x8601 && typeID != 0x8006 && typeID != 0x8100 && typeID != 0x4003 && typeID != 0x4004 && typeID != 0x000B0010 &
// typeID != 0x4009 && typeID != 0x4104 && typeID != 0x4109 && typeID != 0x8407 && typeID != 0x9001012 && typeID != 0xF000024 &&
// typeID != 0xF00001D && typeID != 0x400B && typeID != 0x4107 && typeID != 0x400C && typeID != 0xF000038 && typeID != 0x400C &&
// typeID != 0x000B0005 && typeID != 0x900100A && typeID != 0x9001004 && typeID != 0x9001005 && typeID != 0x9001002 &&
// typeID != 0x9001013 && typeID != 0x000B0001 && typeID != 0x8401 && typeID != 0x8116 && typeID != 0x9001010 &&
// typeID != 0x9001016 && typeID != 0xF000008 && typeID != 0x9001003 && typeID != 0x9001006 && typeID != 0x4016 && typeID != 0x9005 &&
// typeID != 0x9002 && typeID != 0xF00001E && typeID != 0xF000015 && typeID != 0x9006 && typeID != 0x9010)
//{
// Console.WriteLine(" -- putExt -- {0:x}", typeID);
//}
}
else
{
PutS32(0);
//log.Error("Can Not Resolve IExternalizable Message : " + value.GetType());
throw new IOException("Can Not Resolve IExternalizable Message : " + value.GetType());
}
}
else
{
PutS32(0);
}
}
public int GetTypeID(IExternalizable value)
{
return Factory.GetTypeID(value.GetType());
}
public void PutObj2Xml(object obj)
{
if (obj != null)
{
XmlDocument x = XmlUtil.ObjectToXml(obj);
string utf = XmlUtil.ToString(x);
byte[] data = CUtils.UTF8.GetBytes(utf);
PutBytes(data);
}
else
{
PutBytes(null);
}
}
///
/// 自动检测类型
///
///
public void PutData(object value)
{
if (value is byte)
{
PutU8((byte)DataType.U8);
PutU8((byte)value);
}
else if (value is sbyte)
{
PutU8((byte)DataType.S8);
PutS8((sbyte)value);
}
else if (value is ushort)
{
PutU8((byte)DataType.U16);
PutU16((ushort)value);
}
else if (value is short)
{
PutU8((byte)DataType.S16);
PutS16((short)value);
}
else if (value is uint)
{
PutU8((byte)DataType.U32);
PutU32((uint)value);
}
else if (value is int)
{
PutU8((byte)DataType.S32);
PutS32((int)value);
}
else if (value is ulong)
{
PutU8((byte)DataType.U64);
PutU64((ulong)value);
}
else if (value is long)
{
PutU8((byte)DataType.S64);
PutS64((long)value);
}
else if (value is float)
{
PutU8((byte)DataType.F32);
PutF32((float)value);
}
else if (value is double)
{
PutU8((byte)DataType.F64);
PutF64((double)value);
}
else if (value is char)
{
PutU8((byte)DataType.UC);
PutUnicode((char)value);
}
else if (value is string)
{
PutU8((byte)DataType.UTF);
PutUTF((string)value);
}
else if (value is IExternalizable)
{
PutU8((byte)DataType.EXT);
PutExt((IExternalizable)value);
}
else
{
PutU8((byte)DataType.NA);
}
}
#endregion
#region _集合类型_
public void PutUTFArray(string[] array)
{
if (array == null)
{
PutS32(-1);
}
else
{
int len = array.Length;
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
PutS32(len);
for (int i = 0; i < len; i++)
{
this.PutUTF(array[i]);
}
}
}
public void PutUTFList(IList list)
{
if (list == null)
{
PutS32(-1);
}
else
{
int len = list.Count;
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
PutS32(len);
for (int i = 0; i < len; i++)
{
this.PutUTF(list[i]);
}
}
}
public void PutArray(T[] array, PutData action)
{
if (array == null)
{
PutS32(-1);
}
else
{
int len = array.Length;
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
PutS32(len);
for (int i = 0; i < len; i++)
{
action.Invoke(array[i]);
}
}
}
public void PutList(IList list, PutData action)
{
if (list == null)
{
PutS32(-1);
}
else
{
int len = list.Count;
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
PutS32(len);
for (int i = 0; i < len; i++)
{
action.Invoke(list[i]);
}
}
}
public void PutMap(IDictionary map, PutData k_action, PutData v_action)
{
if (map == null)
{
PutS32(-1);
}
else
{
int len = map.Count;
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
this.PutS32(len);
foreach (var kv in map)
{
k_action.Invoke(kv.Key);
v_action.Invoke(kv.Value);
}
}
}
///
/// 不包括消息头,列表中元素必须保证类型一致
///
public void PutStructArray(T[] array) where T : IExternalizable
{
if (array == null)
{
PutS32(-1);
}
else
{
int len = array.Length;
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
this.PutS32(array.Length);
for (int i = 0; i < array.Length; i++)
{
array[i].WriteExternal(this);
}
}
}
///
/// 不包括消息头,列表中元素必须保证类型一致
///
public void PutStructList(IList array) where T : IExternalizable
{
if (array == null)
{
PutS32(-1);
}
else
{
int len = array.Count;
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
this.PutS32(array.Count);
for (int i = 0; i < array.Count; i++)
{
array[i].WriteExternal(this);
}
}
}
///
/// 不包括消息头,列表中元素必须保证类型一致
///
public void PutExtArray(T[] array) where T : IExternalizable
{
if (array == null)
{
PutS32(-1);
}
else
{
int len = array.Length;
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
this.PutS32(array.Length);
for (int i = 0; i < array.Length; i++)
{
array[i].WriteExternal(this);
}
}
}
///
/// 不包括消息头,列表中元素必须保证类型一致
///
public void PutExtList(IList array) where T : IExternalizable
{
if (array == null)
{
PutS32(-1);
}
else
{
int len = array.Count;
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
this.PutS32(array.Count);
for (int i = 0; i < array.Count; i++)
{
array[i].WriteExternal(this);
}
}
}
#endregion
}
public abstract class IInputStream : IOStream
{
protected static System.Text.UTF8Encoding utfenc = new System.Text.UTF8Encoding(false);
public IInputStream(IExternalizableFactory factory)
{
this.Factory = factory;
}
public IExternalizableFactory Factory { get; private set; }
#region _Abstract_
public abstract byte[] GetBytes();
public abstract void GetRawData(byte[] buff, int offset, int count);
public abstract bool GetBool();
public abstract byte GetU8();
public abstract sbyte GetS8();
public abstract ushort GetU16();
public abstract short GetS16();
public abstract uint GetU32();
public abstract int GetS32();
public abstract ulong GetU64();
public abstract long GetS64();
public abstract float GetF32();
public abstract double GetF64();
public abstract char GetUnicode();
public abstract string GetUTF();
#endregion
#region _基础类型_
///
/// 写入可变长度32位
///
public UInt32 GetVU32()
{
return (UInt32)GetVU64();
}
///
/// 写入可变长度32位
///
public Int32 GetVS32()
{
return (Int32)GetVS64();
}
///
/// 写入可变长度64位
///
public Int64 GetVS64()
{
ulong m = GetVU64();
long v = (long)(m >> 1);
if (m % 2 == 1)
{
return -v;
}
else
{
return v;
}
}
///
/// 写入可变长度64位
///
public UInt64 GetVU64()
{
UInt64 value = 0;
UInt64 b = 0;
for (int i = 0; i <= 70; i += 7)
{
b = GetU8();
value |= ((b & 0x7F) << i);
if ((b & 0x80) == 0)
break;
}
return value;
}
public T GetEnum8()
{
byte u8 = GetU8();
if (Enum.IsDefined(typeof(T), u8))
{
return (T)Enum.ToObject(typeof(T), u8);
}
return default(T);
}
public T GetEnum32()
{
int s32 = GetS32();
if (Enum.IsDefined(typeof(T), s32))
{
return (T)Enum.ToObject(typeof(T), s32);
}
return default(T);
}
#endregion
#region _对象类型_
public T GetExt() where T : IExternalizable, new()
{
int typeID = GetS32();
if (typeID != 0)
{
Type type = Factory.GetType(typeID);
if (type != null)
{
T any = (T)Activator.CreateInstance(type);
any.ReadExternal(this);
return any;
}
else
{
throw new IOException("Can Not Resolve IExternalizable Message : 0x" + typeID.ToString("X"));
}
}
return default(T);
}
public T GetExt(T ret) where T : IExternalizable
{
int typeID = GetS32();
if (typeID != 0)
{
Type type = Factory.GetType(typeID);
if (type == null)
{
throw new IOException("Can Not Resolve IExternalizable Message : 0x" + typeID.ToString("X"));
}
if (!type.IsInstanceOfType(ret))
{
throw new IOException("type can't match:" + type + "->" + ret.GetType());
}
else
{
ret.ReadExternal(this);
return ret;
}
}
return default(T);
}
public IExternalizable GetExtAny()
{
int typeID = GetS32();
if (typeID != 0)
{
Type type = Factory.GetType(typeID);
if (type != null)
{
IExternalizable any = (IExternalizable)Activator.CreateInstance(type);
any.ReadExternal(this);
return any;
}
else
{
throw new IOException("Can Not Resolve IExternalizable Message : 0x" + typeID.ToString("X"));
}
}
return null;
}
public T GetXml2Obj(Action error = null)
{
byte[] data = GetBytes();
if (data != null && data.Length > 0)
{
string xml = CUtils.UTF8.GetString(data);
XmlDocument x = XmlUtil.FromString(xml);
T ret = (T)XmlUtil.XmlToObject(x, error);
return ret;
}
return default(T);
}
///
/// 自动检测类型
///
///
public object GetData(out DataType type)
{
byte dt = GetU8();
if (Enum.IsDefined(typeof(DataType), dt))
{
type = (DataType)dt;
switch (type)
{
case DataType.U8: return GetU8();
case DataType.S8: return GetS8();
case DataType.U16: return GetU16();
case DataType.S16: return GetS16();
case DataType.U32: return GetU32();
case DataType.S32: return GetS32();
case DataType.U64: return GetU64();
case DataType.S64: return GetS64();
case DataType.F32: return GetF32();
case DataType.F64: return GetF64();
case DataType.UC: return GetUnicode();
case DataType.UTF: return GetUTF();
case DataType.EXT: return GetExtAny();
}
}
type = DataType.NA;
return null;
}
public object GetData()
{
byte dt = GetU8();
if (Enum.IsDefined(typeof(DataType), dt))
{
DataType type = (DataType)dt;
switch (type)
{
case DataType.U8: return GetU8();
case DataType.S8: return GetS8();
case DataType.U16: return GetU16();
case DataType.S16: return GetS16();
case DataType.U32: return GetU32();
case DataType.S32: return GetS32();
case DataType.U64: return GetU64();
case DataType.S64: return GetS64();
case DataType.F32: return GetF32();
case DataType.F64: return GetF64();
case DataType.UC: return GetUnicode();
case DataType.UTF: return GetUTF();
case DataType.EXT: return GetExtAny();
}
}
return null;
}
#endregion
#region _集合类型_
public string[] GetUTFArray()
{
int len = GetS32();
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
if (len < 0) return null;
string[] ret = new string[len];
for (int i = 0; i < len; i++)
{
ret[i] = GetUTF();
}
return ret;
}
public T[] GetArray(GetData action)
{
int len = GetS32();
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
if (len < 0) return null;
T[] ret = new T[len];
for (int i = 0; i < len; i++)
{
T d = action.Invoke();
ret[i] = d;
}
return ret;
}
///
/// 不包括消息头,列表中元素必须保证类型一致
///
public T[] GetStructArray() where T : IExternalizable, new()
{
int len = GetS32();
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
if (len < 0) return null;
T[] array = new T[len];
for (int i = 0; i < len; i++)
{
array[i].ReadExternal(this);
}
return array;
}
///
/// 不包括消息头,列表中元素必须保证类型一致
///
public T[] GetExtArray() where T : IExternalizable, new()
{
int len = GetS32();
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
if (len < 0) return null;
T[] array = new T[len];
for (int i = 0; i < len; i++)
{
array[i] = new T();
array[i].ReadExternal(this);
}
return array;
}
public List GetUTFList()
{
int len = GetS32();
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
if (len < 0) return null;
List ret = new List(len);
for (int i = 0; i < len; i++)
{
string d = GetUTF();
ret.Add(d);
}
return ret;
}
public List GetList(GetData action)
{
int len = GetS32();
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
if (len < 0) return null;
List ret = new List(len);
for (int i = 0; i < len; i++)
{
T d = action.Invoke();
ret.Add(d);
}
return ret;
}
public List GetListAny() where T : IExternalizable
{
int len = GetS32();
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
if (len < 0) return null;
List ret = new List(len);
for (int i = 0; i < len; i++)
{
IExternalizable ext = GetExtAny();
if (ext != null)
{
ret.Add((T)ext);
}
}
return ret;
}
///
/// 不包括消息头,列表中元素必须保证类型一致
///
public List GetStructList() where T : IExternalizable, new()
{
int len = GetS32();
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
if (len < 0) return null;
List list = new List();
for (int i = 0; i < len; i++)
{
T item = new T();
item.ReadExternal(this);
list.Add(item);
}
return list;
}
///
/// 不包括消息头,列表中元素必须保证类型一致
///
public List GetExtList() where T : IExternalizable, new()
{
int len = GetS32();
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
if (len < 0) return null;
List list = new List();
for (int i = 0; i < len; i++)
{
T item = new T();
item.ReadExternal(this);
list.Add(item);
}
return list;
}
//--------------------------------------------------------------------------------------------
public L GetGenericUTFList() where L : class, IList, new()
{
int len = GetS32();
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
if (len < 0) return null;
var ret = new L();
for (int i = 0; i < len; i++)
{
string d = GetUTF();
ret.Add(d);
}
return ret;
}
public L GetGenericList(GetData action) where L : class, IList, new()
{
int len = GetS32();
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
if (len < 0) return null;
L ret = new L();
for (int i = 0; i < len; i++)
{
T d = action.Invoke();
ret.Add(d);
}
return ret;
}
public L GetGenericListAny()
where T : IExternalizable
where L : class, IList, new()
{
int len = GetS32();
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
if (len < 0) return null;
var ret = new L();
for (int i = 0; i < len; i++)
{
IExternalizable ext = GetExtAny();
if (ext != null)
{
ret.Add((T)ext);
}
}
return ret;
}
///
/// 不包括消息头,列表中元素必须保证类型一致
///
public L GetGenericStructList()
where T : struct, IExternalizable
where L : class, IList, new()
{
int len = GetS32();
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
if (len < 0) return null;
var list = new L();
for (int i = 0; i < len; i++)
{
T item = new T();
item.ReadExternal(this);
list.Add(item);
}
return list;
}
///
/// 不包括消息头,列表中元素必须保证类型一致
///
public L GetGenericExtList()
where T : IExternalizable, new()
where L : class, IList, new()
{
int len = GetS32();
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
if (len < 0) return null;
var list = new L();
for (int i = 0; i < len; i++)
{
T item = new T();
item.ReadExternal(this);
list.Add(item);
}
return list;
}
//--------------------------------------------------------------------------------------------
public HashMap GetMap(GetData k_action, GetData v_action)
{
int len = GetS32();
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
if (len < 0) return null;
HashMap ret = new HashMap(len);
for (int i = 0; i < len; i++)
{
K k = k_action.Invoke();
V v = v_action.Invoke();
ret[k] = v;
}
return ret;
}
public M GetGenericMap(GetData k_action, GetData v_action) where M : class, IDictionary, new()
{
int len = GetS32();
if (len > ARRAY_LIMIT) { throw new IOException("Collection overflow : " + len + " > " + ARRAY_LIMIT); }
if (len < 0) return null;
M ret = new M();
for (int i = 0; i < len; i++)
{
K k = k_action.Invoke();
V v = v_action.Invoke();
ret[k] = v;
}
return ret;
}
//--------------------------------------------------------------------------------------------
#endregion
}
}