RosettaCodeData/Task/Bitwise-IO/Lua/bitwise-io-1.lua

71 lines
1.9 KiB
Lua

local function BitWriter() return {
accumulator = 0, -- For current byte.
bitCount = 0, -- Bits set in current byte.
outChars = {},
-- writer:writeBit( bit )
writeBit = function(writer, bit)
writer.bitCount = writer.bitCount + 1
if bit > 0 then
writer.accumulator = writer.accumulator + 2^(8-writer.bitCount)
end
if writer.bitCount == 8 then
writer:_flush()
end
end,
-- writer:writeLsb( value, width )
writeLsb = function(writer, value, width)
for i = 1, width do
writer:writeBit(value%2)
value = math.floor(value/2)
end
end,
-- dataString = writer:getOutput( )
getOutput = function(writer)
writer:_flush()
return table.concat(writer.outChars)
end,
_flush = function(writer)
if writer.bitCount == 0 then return end
table.insert(writer.outChars, string.char(writer.accumulator))
writer.accumulator = 0
writer.bitCount = 0
end,
} end
local function BitReader(data) return {
bitPosition = 0, -- Absolute position in 'data'.
-- bit = reader:readBit( ) -- Returns nil at end-of-data.
readBit = function(reader)
reader.bitPosition = reader.bitPosition + 1
local bytePosition = math.floor((reader.bitPosition-1)/8) + 1
local byte = data:byte(bytePosition)
if not byte then return nil end
local bitIndex = ((reader.bitPosition-1)%8) + 1
return math.floor(byte / 2^(8-bitIndex)) % 2
end,
-- value = reader:readLsb( width ) -- Returns nil at end-of-data.
readLsb = function(reader, width)
local accumulator = 0
for i = 1, width do
local bit = reader:readBit()
if not bit then return nil end
if bit > 0 then
accumulator = accumulator + 2^(i-1)
end
end
return accumulator
end,
} end