204 lines
No EOL
4.4 KiB
Lua
204 lines
No EOL
4.4 KiB
Lua
--[[local config = include "./config.lua"
|
|
if (SERVER) then
|
|
if (config and config.netstreamcompat) then
|
|
util.AddNetworkString "BITBUF_NETSTREAM"
|
|
end
|
|
AddCSLuaFile()
|
|
end
|
|
]]
|
|
if (SERVER) then
|
|
AddCSLuaFile()
|
|
end
|
|
local function bad(val, argn, name, err)
|
|
if (not val) then
|
|
error(("bad argument #%i to '%s' (%s)"):format(argn, name, err), 2)
|
|
end
|
|
end
|
|
|
|
local mt = {
|
|
__index = function(self, k)
|
|
return getmetatable(self)[k]
|
|
end,
|
|
__call = function(self, data)
|
|
return setmetatable({}, getmetatable(self)):Init(data)
|
|
end
|
|
}
|
|
|
|
local function nop() end
|
|
|
|
local bb_read = setmetatable({
|
|
SetupQueuedCallback = function(name, cb, filter)
|
|
bad(isfunction(cb), 2, "SetupQueuedCallback", "expected function")
|
|
local states = {}
|
|
net.Receive(name, function(len, cl)
|
|
states[cl] = states[cl] or {}
|
|
local ID = net.ReadUInt(32)
|
|
len = len - 32
|
|
local state = states[cl][ID] or (function()
|
|
len = len - 32
|
|
local datalen = net.ReadUInt(32)
|
|
;(filter or nop)(cl, datalen)
|
|
return {len = datalen, current = 0}
|
|
end)()
|
|
|
|
table.insert(state, net.ReadData(len / 8))
|
|
|
|
states[cl][ID] = state
|
|
state.current = state.current + len / 8
|
|
if (state.current >= state.len) then
|
|
states[cl][ID] = nil
|
|
cb(table.concat(state), cl)
|
|
end
|
|
|
|
|
|
end)
|
|
end
|
|
}, mt)
|
|
|
|
function mt:Init(data)
|
|
bad(isstring(data), 1, "Init", "string expected")
|
|
self:SetData(data)
|
|
return self
|
|
end
|
|
|
|
function mt:SetData(data)
|
|
self.RawData = {}
|
|
data:gsub("().", function(match)
|
|
self.RawData[match] = data:byte(match, match)
|
|
end)
|
|
self.Bits = 0
|
|
self.Bytes = 1
|
|
return self
|
|
end
|
|
|
|
function mt:Byte()
|
|
return self:UInt(8)
|
|
end
|
|
|
|
function mt:Data(len)
|
|
local dat = {}
|
|
for i = 1, len do
|
|
dat[i] = string.char(self:Byte())
|
|
end
|
|
|
|
return table.concat(dat)
|
|
end
|
|
|
|
function mt:String()
|
|
local b = self:Byte()
|
|
local dat = { n = 0 }
|
|
while (b ~= 0) do
|
|
dat[dat.n + 1] = string.char(b)
|
|
dat.n = dat.n + 1
|
|
b = self:Byte()
|
|
end
|
|
|
|
return table.concat(dat)
|
|
end
|
|
|
|
function mt:Int(totalbits)
|
|
bad(isnumber(totalbits), 1, "Int", "number expected")
|
|
bad(totalbits <= 32 and totalbits > 0, 1, "Int", "a number 1 through 32 expected")
|
|
|
|
local retnum = 0
|
|
|
|
for i = 1, totalbits do
|
|
local bitread = self.Bits % 8
|
|
|
|
local byte = self.RawData[self.Bytes]
|
|
|
|
-- retnum |= ((byte & (1 << bitread)) >> bitread) << (totalbits - i)
|
|
local bitmask = bit.lshift(1, 7-bitread)
|
|
local bitn = bit.rshift(bit.band(byte, bitmask), 7 - bitread)
|
|
retnum = bit.bor(retnum, bit.lshift(bitn, totalbits - i))
|
|
|
|
self.Bits = self.Bits + 1
|
|
if (self.Bits % 8 == 0) then
|
|
self.Bytes = self.Bytes + 1
|
|
end
|
|
end
|
|
|
|
if (retnum > 0 and bit.band(retnum, 2^(totalbits - 1)) ~= 0) then
|
|
retnum = retnum - 2^totalbits
|
|
end
|
|
|
|
return retnum
|
|
end
|
|
|
|
function mt:UInt(bits)
|
|
local r = self:Int(bits)
|
|
if (r < 0) then
|
|
r = r + 2^bits
|
|
end
|
|
return r
|
|
end
|
|
|
|
--[[ THE NEXT TWO FUNCTIONS ARE GIVEN RIGHTS TO ME FOR USAGE UNDER MIT LICENSE BY THE CREATOR ]]
|
|
|
|
local function UInt32sToDouble (low, high)
|
|
local negative = false
|
|
|
|
if high >= 0x80000000 then
|
|
negative = true
|
|
high = high - 0x80000000
|
|
end
|
|
|
|
local biasedExponent = bit.rshift (bit.band (high, 0x7FF00000), 20)
|
|
local mantissa = (bit.band (high, 0x000FFFFF) * 4294967296 + low) / 2 ^ 52
|
|
|
|
local f
|
|
if biasedExponent == 0x0000 then
|
|
f = mantissa == 0 and 0 or math.ldexp (mantissa, -1022)
|
|
elseif biasedExponent == 0x07FF then
|
|
f = mantissa == 0 and math.huge or (math.huge - math.huge)
|
|
else
|
|
f = math.ldexp (1 + mantissa, biasedExponent - 1023)
|
|
end
|
|
|
|
return negative and -f or f
|
|
end
|
|
|
|
local function UInt32ToFloat (n)
|
|
-- 1 sign bit
|
|
-- 8 biased exponent bits (bias of 127, biased value of 0 if 0 or denormal)
|
|
-- 23 mantissa bits (implicit 1, unless biased exponent is 0)
|
|
|
|
local negative = false
|
|
|
|
if n >= 0x80000000 then
|
|
negative = true
|
|
n = n - 0x80000000
|
|
end
|
|
|
|
local biasedExponent = bit.rshift (bit.band (n, 0x7F800000), 23)
|
|
local mantissa = bit.band (n, 0x007FFFFF) / (2 ^ 23)
|
|
|
|
local f
|
|
if biasedExponent == 0x00 then
|
|
f = mantissa == 0 and 0 or math.ldexp (mantissa, -126)
|
|
elseif biasedExponent == 0xFF then
|
|
f = mantissa == 0 and math.huge or (math.huge - math.huge)
|
|
else
|
|
f = math.ldexp (1 + mantissa, biasedExponent - 127)
|
|
end
|
|
|
|
return negative and -f or f
|
|
end
|
|
|
|
function mt:Float()
|
|
return UInt32ToFloat(self:UInt(32))
|
|
end
|
|
|
|
function mt:Double(dbl)
|
|
local low = self:UInt(32)
|
|
local high = self:UInt(32)
|
|
return UInt32sToDouble(low, high)
|
|
end
|
|
|
|
function mt:Write()
|
|
|
|
net.Start(self.Name)
|
|
|
|
end
|
|
|
|
return bb_read |