dobrograd-13-06-2022/garrysmod/addons/admin-sg/lua/modules/bitbuf_glua/read.lua
Jonny_Bro (Nikita) e4d5311906 first commit
2023-11-16 15:01:19 +05:00

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