mirror of
https://github.com/LDDestroier/CC/
synced 2025-08-29 17:07:59 +00:00
Add files via upload
This commit is contained in:
219
lstring.lua
Normal file
219
lstring.lua
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
-- Lengthed string API
|
||||||
|
-- by LDDestroier
|
||||||
|
|
||||||
|
local LString = {}
|
||||||
|
|
||||||
|
local default_key_size = 1
|
||||||
|
local default_value_size = 1
|
||||||
|
|
||||||
|
function LString.Error( sMsg, tContext )
|
||||||
|
LString.__error = {
|
||||||
|
message = sMsg,
|
||||||
|
context = tContext
|
||||||
|
}
|
||||||
|
error(sMsg, 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- converts number to a string of byte characters
|
||||||
|
function LString.NumToBytes( number, length )
|
||||||
|
length = length or default_value_size
|
||||||
|
assert(type(length) == "number", "must specify byte length")
|
||||||
|
local output = ""
|
||||||
|
for i = 1, length do
|
||||||
|
output = output .. string.char(
|
||||||
|
math.floor(number / 2^(8 * (i - 1))) % 256
|
||||||
|
)
|
||||||
|
end
|
||||||
|
return output
|
||||||
|
end
|
||||||
|
|
||||||
|
-- converts a string of bytes back into a number
|
||||||
|
function LString.BytesToNum( bytes, length )
|
||||||
|
assert( type(bytes) == "string", "bytes must be represented as string" )
|
||||||
|
length = length or #bytes
|
||||||
|
local output = 0
|
||||||
|
for i = 1, length do
|
||||||
|
output = output + (string.byte(bytes:sub(i, i)) * 2 ^ (8 * (i - 1)))
|
||||||
|
end
|
||||||
|
return output
|
||||||
|
end
|
||||||
|
|
||||||
|
-- returns lengthed string, and whether or not it was truncated to the byte limit
|
||||||
|
function LString.MakeLString( sInput, nSize )
|
||||||
|
local limit = 2^(nSize * 8) - 1
|
||||||
|
return LString.NumToBytes(math.min(tostring(sInput):len(), limit), nSize) .. tostring(sInput):sub(1, limit),
|
||||||
|
tostring(sInput):len() > limit
|
||||||
|
end
|
||||||
|
|
||||||
|
local tAbbr = {
|
||||||
|
string = "s",
|
||||||
|
number = "n",
|
||||||
|
table = "t",
|
||||||
|
boolean = "b"
|
||||||
|
}
|
||||||
|
|
||||||
|
function LString.GetLString( sInput, nSize, nIterator )
|
||||||
|
nIterator = nIterator or 1
|
||||||
|
nSize = nSize or default_value_size
|
||||||
|
local len = LString.BytesToNum(sInput:sub(nIterator), nSize)
|
||||||
|
return sInput:sub(nSize + nIterator, nSize + len + nIterator - 1), nIterator + len + nSize
|
||||||
|
end
|
||||||
|
|
||||||
|
function LString.GetLTypeString( sInput, nSize, nIterator, tTypeSizeOverride )
|
||||||
|
nIterator = nIterator or 1
|
||||||
|
local ltype = sInput:sub(nIterator, nIterator)
|
||||||
|
if (tTypeSizeOverride[ltype]) then
|
||||||
|
nSize = tTypeSizeOverride[ltype]
|
||||||
|
end
|
||||||
|
local output
|
||||||
|
nIterator = nIterator + 1
|
||||||
|
output, nIterator = LString.GetLString(sInput, nSize, nIterator)
|
||||||
|
return output, nIterator, ltype
|
||||||
|
end
|
||||||
|
|
||||||
|
-- serializes a table of strings, numbers, and tables containing them
|
||||||
|
|
||||||
|
function LString.serialize( tInput, nKeySize, nValueSize, bOmitType )
|
||||||
|
local output = ""
|
||||||
|
local count = 0
|
||||||
|
|
||||||
|
nKeySize = nKeySize or default_key_size
|
||||||
|
nValueSize = nValueSize or default_value_size
|
||||||
|
|
||||||
|
for k,v in pairs(tInput) do
|
||||||
|
if ( not tAbbr[type(k)] ) then
|
||||||
|
LString.Error("bad serialize! key must be string, number, boolean, or a table containing only them", {
|
||||||
|
tInput = tInput,
|
||||||
|
key = k,
|
||||||
|
value = v
|
||||||
|
})
|
||||||
|
|
||||||
|
elseif ( not tAbbr[type(v)] ) then
|
||||||
|
LString.Error("bad serialize! key must be string, number, boolean, or a table containing only them", {
|
||||||
|
tInput = tInput,
|
||||||
|
key = k,
|
||||||
|
value = v
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
if (bOmitType) then
|
||||||
|
if ( type(k) == "table" ) then
|
||||||
|
LString.Error("cannot use table as key if omitting type", {
|
||||||
|
tInput = tInput,
|
||||||
|
key = k,
|
||||||
|
value = v
|
||||||
|
})
|
||||||
|
else
|
||||||
|
output = output .. LString.MakeLString(k, nKeySize)
|
||||||
|
end
|
||||||
|
|
||||||
|
if ( type(v) == "table" ) then
|
||||||
|
LString.Error("cannot use table as value if omitting type", {
|
||||||
|
tInput = tInput,
|
||||||
|
key = k,
|
||||||
|
value = v
|
||||||
|
})
|
||||||
|
|
||||||
|
else
|
||||||
|
output = output .. LString.MakeLString(v, nValueSize)
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
output = output .. tAbbr[type(k)]
|
||||||
|
if ( type(k) == "table" ) then
|
||||||
|
-- table values must have a length of 32 bits
|
||||||
|
output = output .. LString.MakeLString(LString.serialize(k, nKeySize, nValueSize), 4)
|
||||||
|
|
||||||
|
elseif ( type(k) == "boolean" ) then
|
||||||
|
output = output .. LString.MakeLString(k and "T" or "F", 1)
|
||||||
|
|
||||||
|
else
|
||||||
|
output = output .. LString.MakeLString(k, nKeySize)
|
||||||
|
end
|
||||||
|
|
||||||
|
output = output .. tAbbr[type(v)]
|
||||||
|
if ( type(v) == "table" ) then
|
||||||
|
-- table values must have a length of 32 bits
|
||||||
|
output = output .. LString.MakeLString(LString.serialize(v, nKeySize, nValueSize), 4)
|
||||||
|
|
||||||
|
elseif ( type(v) == "boolean" ) then
|
||||||
|
output = output .. LString.MakeLString(v and "T" or "F", 1)
|
||||||
|
|
||||||
|
else
|
||||||
|
output = output .. LString.MakeLString(v, nValueSize)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
output = LString.NumToBytes(count, 2) .. output
|
||||||
|
|
||||||
|
return output
|
||||||
|
end
|
||||||
|
LString.serialise = LString.serialize
|
||||||
|
|
||||||
|
-- will assume every key and value are strings
|
||||||
|
function LString.serializeTypeless(sInput, nKeySize, nValueSize)
|
||||||
|
return LString.serialize(sInput, nKeySize, nValueSize, 1, true)
|
||||||
|
end
|
||||||
|
LString.serialiseTypeless = LString.serializeTypeless
|
||||||
|
|
||||||
|
function LString.unserialize( sInput, nKeySize, nValueSize, nIterator, bOmitType )
|
||||||
|
nKeySize = nKeySize or default_key_size
|
||||||
|
nValueSize = nValueSize or default_value_size
|
||||||
|
|
||||||
|
local tOutput = {}
|
||||||
|
nIterator = nIterator or 1
|
||||||
|
local count = LString.BytesToNum(sInput:sub(nIterator), 2)
|
||||||
|
nIterator = nIterator + 2
|
||||||
|
local lkey, lval, ltype
|
||||||
|
|
||||||
|
for i = 1, count do
|
||||||
|
if (bOmitType) then
|
||||||
|
ltype = "s"
|
||||||
|
lkey, nIterator = LString.GetLString(sInput, nKeySize, nIterator)
|
||||||
|
else
|
||||||
|
lkey, nIterator, ltype = LString.GetLTypeString(sInput, nKeySize, nIterator, {['t'] = 4, ['b'] = 1})
|
||||||
|
end
|
||||||
|
|
||||||
|
if (ltype == "n") then
|
||||||
|
lkey = tonumber(lkey)
|
||||||
|
|
||||||
|
elseif (ltype == "t") then
|
||||||
|
lkey = LString.unserialize(lkey, nKeySize, nValueSize)
|
||||||
|
|
||||||
|
elseif (ltype == "b") then
|
||||||
|
lkey = lkey == "T"
|
||||||
|
end
|
||||||
|
|
||||||
|
if (bOmitType) then
|
||||||
|
ltype = "s"
|
||||||
|
lval, nIterator = LString.GetLString(sInput, nValueSize, nIterator)
|
||||||
|
else
|
||||||
|
lval, nIterator, ltype = LString.GetLTypeString(sInput, nValueSize, nIterator, {['t'] = 4, ['b'] = 1})
|
||||||
|
end
|
||||||
|
|
||||||
|
if (ltype == "n") then
|
||||||
|
lval = tonumber(lval)
|
||||||
|
|
||||||
|
elseif (ltype == "t") then
|
||||||
|
lval = LString.unserialize(lval, nKeySize, nValueSize, 1, bOmitType)
|
||||||
|
|
||||||
|
elseif (ltype == "b") then
|
||||||
|
lval = lval == "T"
|
||||||
|
end
|
||||||
|
|
||||||
|
tOutput[lkey] = lval
|
||||||
|
end
|
||||||
|
|
||||||
|
return tOutput, nIterator
|
||||||
|
end
|
||||||
|
LString.unserialise = LString.unserialize
|
||||||
|
|
||||||
|
function LString.unserializeTypeless(sInput, nKeySize, nValueSize)
|
||||||
|
return LString.unserialize(sInput, nKeySize, nValueSize, 1, true)
|
||||||
|
end
|
||||||
|
LString.unserialiseTypeless = LString.unserializeTypeless
|
||||||
|
|
||||||
|
return LString
|
Reference in New Issue
Block a user