335 lines
11 KiB
Lua
335 lines
11 KiB
Lua
|
|
do
|
|||
|
|
require("public.class")
|
|||
|
|
require("bio.BioType")
|
|||
|
|
|
|||
|
|
BioOutputStream = {}
|
|||
|
|
|
|||
|
|
local B2Type = BioType.B2Type;
|
|||
|
|
local IntB2TypeList = BioType.IntB2TypeList;
|
|||
|
|
local StringB2TypeList = BioType.StringB2TypeList;
|
|||
|
|
local MapB2TypeList = BioType.MapB2TypeList;
|
|||
|
|
local ListB2TypeList = BioType.ListB2TypeList
|
|||
|
|
|
|||
|
|
local type = type
|
|||
|
|
local sub = string.sub
|
|||
|
|
local strupper = string.upper;
|
|||
|
|
local strlen = string.len;
|
|||
|
|
local strbyte = string.byte
|
|||
|
|
local strchar = string.char
|
|||
|
|
local floorInt = math.floor
|
|||
|
|
--===================================================
|
|||
|
|
--===================================================
|
|||
|
|
-- 数据流
|
|||
|
|
LuaB2OutputStream = class("LuaB2OutputStream");
|
|||
|
|
function LuaB2OutputStream:ctor(v)
|
|||
|
|
self.content = {}
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
function LuaB2OutputStream:init(v)
|
|||
|
|
self.content = {}
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
function LuaB2OutputStream:writeByte(v)
|
|||
|
|
table.insert(self.content, strchar(v))
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
function LuaB2OutputStream:writeString(v)
|
|||
|
|
table.insert(self.content, v)
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
function LuaB2OutputStream:toBytes()
|
|||
|
|
--local ret = "";
|
|||
|
|
--for i, v in ipairs(self.content) do
|
|||
|
|
-- ret = ret .. v;
|
|||
|
|
--end
|
|||
|
|
return table.concat(self.content, "");
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
function LuaB2OutputStream:release()
|
|||
|
|
self.content = {};
|
|||
|
|
end
|
|||
|
|
--===================================================
|
|||
|
|
--===================================================
|
|||
|
|
--===================================================
|
|||
|
|
|
|||
|
|
-- 原始数据类型
|
|||
|
|
BioOutputStream.DataType = {
|
|||
|
|
NIL = "nil",
|
|||
|
|
BOOLEAN = "boolean",
|
|||
|
|
STRING = "string",
|
|||
|
|
NUMBER = "number",
|
|||
|
|
LONG = "long",
|
|||
|
|
DOUBLE = "double",
|
|||
|
|
USERDATA = "userdata",
|
|||
|
|
FUNCTION = "function",
|
|||
|
|
THREAD = "thread",
|
|||
|
|
TABLE = "table",
|
|||
|
|
INT4B = "int4b",
|
|||
|
|
INT16B = "int16b",
|
|||
|
|
INT32B = "int32b",
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
---@public 取得数据的类型,主要是对number做了处理
|
|||
|
|
function BioOutputStream.getDataType(obj)
|
|||
|
|
--nil, boolean, number, string, userdata, function, thread, table
|
|||
|
|
local val = nil;
|
|||
|
|
local t = type(obj);
|
|||
|
|
val = BioOutputStream.DataType[strupper(type(obj))];
|
|||
|
|
if val == nil then
|
|||
|
|
val = "undefined";
|
|||
|
|
end
|
|||
|
|
return val;
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
function BioOutputStream.getNumberType(obj)
|
|||
|
|
local val = nil;
|
|||
|
|
local t = type(obj);
|
|||
|
|
if t == "number" then
|
|||
|
|
local minInt = floorInt(obj);
|
|||
|
|
if minInt == obj then
|
|||
|
|
-- 说明是整数
|
|||
|
|
if (obj >= -128 and obj <= 127) then
|
|||
|
|
val = BioOutputStream.DataType.INT4B
|
|||
|
|
elseif (obj >= -32768 and obj <= 32767) then
|
|||
|
|
val = BioOutputStream.DataType.INT16B
|
|||
|
|
elseif (obj >= -2147483648 and obj <= 2147483647) then
|
|||
|
|
val = BioOutputStream.DataType.INT32B
|
|||
|
|
else
|
|||
|
|
val = BioOutputStream.DataType.LONG
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
val = BioOutputStream.DataType.DOUBLE
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
return val;
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
---@public 返回table是否为一个array, 第二返回值:如查是array的时候是table的count
|
|||
|
|
function BioOutputStream.isArray(t)
|
|||
|
|
if t == nil then
|
|||
|
|
return false, 0;
|
|||
|
|
end
|
|||
|
|
local i = 0
|
|||
|
|
local ret = true;
|
|||
|
|
for _ in pairs(t) do
|
|||
|
|
i = i + 1
|
|||
|
|
if t[i] == nil then
|
|||
|
|
ret = false
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
return ret, i
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--===================================================
|
|||
|
|
---public Void writeObject (LuaB2OutputStream os, obj)
|
|||
|
|
---@param optional LuaB2OutputStream os
|
|||
|
|
---@param optional object obj
|
|||
|
|
--[[
|
|||
|
|
local os = LuaB2OutputStream.new();
|
|||
|
|
BioOutputStream.writeObject(os, map)
|
|||
|
|
local bytes = os:toBytes()
|
|||
|
|
--]]
|
|||
|
|
function BioOutputStream.writeObject (os, obj)
|
|||
|
|
if os == nil then
|
|||
|
|
os = LuaB2OutputStream.new();
|
|||
|
|
end
|
|||
|
|
local objType = BioOutputStream.getDataType(obj)
|
|||
|
|
if (objType == BioOutputStream.DataType.NIL) then
|
|||
|
|
BioOutputStream.writeNil(os)
|
|||
|
|
elseif (objType == BioOutputStream.DataType.TABLE) then
|
|||
|
|
BioOutputStream.writeMap(os, obj);
|
|||
|
|
elseif (objType == BioOutputStream.DataType.NUMBER) then
|
|||
|
|
BioOutputStream.writeNumber(os, obj);
|
|||
|
|
elseif (objType == BioOutputStream.DataType.STRING) then
|
|||
|
|
BioOutputStream.writeString(os, obj);
|
|||
|
|
elseif (objType == BioOutputStream.DataType.BOOLEAN) then
|
|||
|
|
BioOutputStream.writeBoolean(os, obj);
|
|||
|
|
else
|
|||
|
|
--//throw new IOException("unsupported obj then" + obj);
|
|||
|
|
print("B2IO unsupported error then type=[" .. tostring(objType) .. "] val=[" .. obj .. "]");
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
function BioOutputStream.writeNil(os)
|
|||
|
|
BioOutputStream.WriteByte(os, B2Type.NULL);
|
|||
|
|
return os;
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
function BioOutputStream.WriteByte(os, v)
|
|||
|
|
local v2 = v;
|
|||
|
|
if v < 0 then
|
|||
|
|
v2 = v + 256;
|
|||
|
|
end
|
|||
|
|
os:writeByte(v2)
|
|||
|
|
return os;
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
function BioOutputStream.writeNumber(os, v)
|
|||
|
|
local numType = BioOutputStream.getNumberType(v)
|
|||
|
|
if numType == BioOutputStream.DataType.INT4B or
|
|||
|
|
numType == BioOutputStream.DataType.INT16B or
|
|||
|
|
numType == BioOutputStream.DataType.INT32B then
|
|||
|
|
BioOutputStream.writeInt(os, v)
|
|||
|
|
elseif numType == BioOutputStream.DataType.LONG then
|
|||
|
|
BioOutputStream.writeLong(os, v);
|
|||
|
|
elseif numType == BioOutputStream.DataType.DOUBLE then
|
|||
|
|
BioOutputStream.writeDouble(os, v);
|
|||
|
|
end
|
|||
|
|
return os;
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
function BioOutputStream.writeInt(os, v)
|
|||
|
|
if v == -1 then
|
|||
|
|
BioOutputStream.WriteByte(os, B2Type.INT_N1);
|
|||
|
|
elseif v >= 0 and v <= 32 then
|
|||
|
|
local t = IntB2TypeList[v + 1]
|
|||
|
|
BioOutputStream.WriteByte(os, t);
|
|||
|
|
else
|
|||
|
|
if (v >= -128 and v <= 127) then
|
|||
|
|
BioOutputStream.WriteByte(os, B2Type.INT_8B);
|
|||
|
|
BioOutputStream.WriteByte(os, v);
|
|||
|
|
elseif (v >= -32768 and v <= 32767) then
|
|||
|
|
BioOutputStream.WriteByte(os, B2Type.INT_16B);
|
|||
|
|
local v2 = v;
|
|||
|
|
--if v < 0 then
|
|||
|
|
-- v2 = v + 65536
|
|||
|
|
--end
|
|||
|
|
BioOutputStream.WriteByte(os, math.floor(v2 / 256));
|
|||
|
|
BioOutputStream.WriteByte(os, v2 % 256);
|
|||
|
|
else
|
|||
|
|
BioOutputStream.WriteByte(os, B2Type.INT_32B);
|
|||
|
|
local v2 = v;
|
|||
|
|
--if v < 0 then
|
|||
|
|
-- v2 = v + 4294967296
|
|||
|
|
--end
|
|||
|
|
BioOutputStream.WriteByte(os, math.floor(v2 / 16777216));
|
|||
|
|
v2 = v2 % 16777216
|
|||
|
|
BioOutputStream.WriteByte(os, math.floor(v2 / 65536));
|
|||
|
|
v2 = v2 % 65536
|
|||
|
|
BioOutputStream.WriteByte(os, math.floor(v2 / 256));
|
|||
|
|
BioOutputStream.WriteByte(os, v2 % 256);
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
return os;
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
function BioOutputStream.writeLong(os, v)
|
|||
|
|
BioOutputStream.WriteByte(os, B2Type.LONG_64B);
|
|||
|
|
local v2 = v;
|
|||
|
|
--if v < 0 then
|
|||
|
|
-- v2 = v + 4294967296
|
|||
|
|
--end
|
|||
|
|
BioOutputStream.WriteByte(os, math.floor(v2 / 72057594037927936));
|
|||
|
|
v2 = v2 % 72057594037927936
|
|||
|
|
BioOutputStream.WriteByte(os, math.floor(v2 / 281474976710656));
|
|||
|
|
v2 = v2 % 281474976710656
|
|||
|
|
BioOutputStream.WriteByte(os, math.floor(v2 / 1099511627776));
|
|||
|
|
v2 = v2 % 1099511627776
|
|||
|
|
BioOutputStream.WriteByte(os, math.floor(v2 / 4294967296));
|
|||
|
|
v2 = v2 % 4294967296
|
|||
|
|
BioOutputStream.WriteByte(os, math.floor(v2 / 16777216));
|
|||
|
|
v2 = v2 % 16777216
|
|||
|
|
BioOutputStream.WriteByte(os, math.floor(v2 / 65536));
|
|||
|
|
v2 = v2 % 65536
|
|||
|
|
BioOutputStream.WriteByte(os, math.floor(v2 / 256));
|
|||
|
|
BioOutputStream.WriteByte(os, v2 % 256);
|
|||
|
|
return os;
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
function BioOutputStream.writeDouble(os, v)
|
|||
|
|
BioOutputStream.WriteByte(os, B2Type.DOUBLE_64B);
|
|||
|
|
BioOutputStream.writeString(os, tostring(v));
|
|||
|
|
return os;
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
function BioOutputStream.writeString(os, v)
|
|||
|
|
if (v == nil) then
|
|||
|
|
BioOutputStream.writeNil(os);
|
|||
|
|
return os;
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local len = strlen(v);
|
|||
|
|
local t = StringB2TypeList[len + 1]
|
|||
|
|
if t then
|
|||
|
|
BioOutputStream.WriteByte(os, t);
|
|||
|
|
os:writeString(v);
|
|||
|
|
else
|
|||
|
|
BioOutputStream.WriteByte(os, B2Type.STR);
|
|||
|
|
BioOutputStream.writeInt(os, len);
|
|||
|
|
os:writeString(v);
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
function BioOutputStream.writeBoolean(os, v)
|
|||
|
|
if v then
|
|||
|
|
BioOutputStream.WriteByte(os, B2Type.BOOLEAN_TRUE);
|
|||
|
|
else
|
|||
|
|
BioOutputStream.WriteByte(os, B2Type.BOOLEAN_FALSE);
|
|||
|
|
end
|
|||
|
|
return os;
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
function BioOutputStream.writeMap(os, v)
|
|||
|
|
if (v == nil) then
|
|||
|
|
BioOutputStream.writeNil(os);
|
|||
|
|
end
|
|||
|
|
local isArray, len = BioOutputStream.isArray(v)
|
|||
|
|
if isArray then
|
|||
|
|
if len <= 24 then
|
|||
|
|
BioOutputStream.WriteByte(os, ListB2TypeList[len + 1]);
|
|||
|
|
else
|
|||
|
|
BioOutputStream.WriteByte(os, B2Type.VECTOR);
|
|||
|
|
BioOutputStream.writeInt(os, len);
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
for i, val in ipairs(v) do
|
|||
|
|
BioOutputStream.writeObject(os, val);
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
if len <= 15 then
|
|||
|
|
BioOutputStream.WriteByte(os, MapB2TypeList[len + 1]);
|
|||
|
|
else
|
|||
|
|
BioOutputStream.WriteByte(os, B2Type.HASHTABLE);
|
|||
|
|
BioOutputStream.writeInt(os, len);
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
for key, val in pairs(v) do
|
|||
|
|
BioOutputStream.writeObject(os, key);
|
|||
|
|
BioOutputStream.writeObject(os, val);
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--两个字节的and 操作
|
|||
|
|
function BioOutputStream.byte_xor(a, b)
|
|||
|
|
local bit_value_tb = {
|
|||
|
|
[8] = 2 ^ 7;
|
|||
|
|
[7] = 2 ^ 6;
|
|||
|
|
[6] = 2 ^ 5;
|
|||
|
|
[5] = 2 ^ 4;
|
|||
|
|
[4] = 2 ^ 3;
|
|||
|
|
[3] = 2 ^ 2;
|
|||
|
|
[2] = 2 ^ 1;
|
|||
|
|
[1] = 2 ^ 0; };
|
|||
|
|
local value = 0;
|
|||
|
|
for i = 8, 1, -1 do
|
|||
|
|
local bit_value = bit_value_tb[i];
|
|||
|
|
if a >= bit_value and b < bit_value then
|
|||
|
|
value = value + bit_value;
|
|||
|
|
elseif a < bit_value and b >= bit_value then
|
|||
|
|
value = value + bit_value;
|
|||
|
|
end
|
|||
|
|
if a >= bit_value then
|
|||
|
|
a = a - bit_value;
|
|||
|
|
end
|
|||
|
|
if b >= bit_value then
|
|||
|
|
b = b - bit_value;
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
return value;
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--------------------------------------------
|
|||
|
|
return BioOutputStream;
|
|||
|
|
end
|