mirror of
https://github.com/tiennm99/zfoo.git
synced 2026-09-10 06:21:21 +00:00
448 lines
12 KiB
Lua
448 lines
12 KiB
Lua
--默认为大端模式
|
|
--支持的lua版本为>=5.3
|
|
--支持标准的Lua是使用64-bit的int以及64-bit的双精度float
|
|
--当lua只能支持32位的整数类型时,可以考虑用Long来替代,需要修改原代码
|
|
|
|
--local Long = require("Long")
|
|
|
|
local maxInt = 2147483647
|
|
local minInt = -2147483648
|
|
local initSize = 128
|
|
local zeroByte = string.char(0)
|
|
|
|
local ByteBuffer = {}
|
|
|
|
local trueBooleanStrValue = string.char(1)
|
|
local falseBooleanStrValue = string.char(0)
|
|
|
|
-------------------------------------构造器-------------------------------------
|
|
function ByteBuffer:new()
|
|
--buffer里的每一个元素为一个长度为1的字符串
|
|
local obj = {
|
|
buffer = {},
|
|
writeOffset = 1,
|
|
readOffset = 1
|
|
}
|
|
setmetatable(obj, self)
|
|
self.__index = self
|
|
|
|
for i = 1, initSize do
|
|
table.insert(obj.buffer, zeroByte)
|
|
end
|
|
return obj
|
|
end
|
|
|
|
|
|
-------------------------------------UTF8-------------------------------------
|
|
-- 判断utf8字符byte长度
|
|
-- 0xxxxxxx - 1 byte
|
|
-- 110yxxxx - 192, 2 byte
|
|
-- 1110yyyy - 225, 3 byte
|
|
-- 11110zzz - 240, 4 byte
|
|
local function chsize(char)
|
|
if not char then
|
|
print("not char")
|
|
return 0
|
|
elseif char > 240 then
|
|
return 4
|
|
elseif char > 225 then
|
|
return 3
|
|
elseif char > 192 then
|
|
return 2
|
|
else
|
|
return 1
|
|
end
|
|
end
|
|
|
|
|
|
-- 截取utf8 字符串
|
|
-- str: 要截取的字符串
|
|
-- startChar: 开始字符下标,从1开始
|
|
-- numChars: 要截取的字符长度
|
|
local function utf8sub(str, startChar, numChars)
|
|
local startIndex = 1
|
|
while startChar > 1 do
|
|
local char = string.byte(str, startIndex)
|
|
startIndex = startIndex + chsize(char)
|
|
startChar = startChar - 1
|
|
end
|
|
|
|
local currentIndex = startIndex
|
|
|
|
while numChars > 0 and currentIndex <= #str do
|
|
local char = string.byte(str, currentIndex)
|
|
currentIndex = currentIndex + chsize(char)
|
|
numChars = numChars - 1
|
|
end
|
|
return str:sub(startIndex, currentIndex - 1)
|
|
end
|
|
|
|
|
|
-------------------------------------get和set-------------------------------------
|
|
function ByteBuffer:getWriteOffset()
|
|
return self.writeOffset
|
|
end
|
|
|
|
function ByteBuffer:setWriteOffset(writeOffset)
|
|
if writeOffset > #self.buffer then
|
|
error("index out of bounds exception: readerIndex: " + self.readOffset
|
|
+ ", writerIndex: " + self.writeOffset
|
|
+ "(expected: 0 <= readerIndex <= writerIndex <= capacity:" + #self.buffer)
|
|
end
|
|
self.writeOffset = writeOffset
|
|
return self
|
|
end
|
|
|
|
function ByteBuffer:getReadOffset()
|
|
return self.readOffset
|
|
end
|
|
|
|
function ByteBuffer:setReadOffset(readOffset)
|
|
if readOffset > self.writeOffset then
|
|
error("index out of bounds exception: readerIndex: " + self.readOffset
|
|
+ ", writerIndex: " + this.writeOffset
|
|
+ "(expected: 0 <= readerIndex <= writerIndex <= capacity:" + #self.buffer)
|
|
end
|
|
self.readOffset = readOffset
|
|
return self
|
|
end
|
|
|
|
function ByteBuffer:getLen()
|
|
return #self.buffer
|
|
end
|
|
|
|
function ByteBuffer:getAvailable()
|
|
return #self.buffer - self.writeOffset + 1
|
|
end
|
|
|
|
-------------------------------------write和read-------------------------------------
|
|
|
|
--bool
|
|
function ByteBuffer:writeBoolean(boolValue)
|
|
if boolValue then
|
|
self:writeRawByteStr(trueBooleanStrValue)
|
|
else
|
|
self:writeRawByteStr(falseBooleanStrValue)
|
|
end
|
|
return self
|
|
end
|
|
|
|
function ByteBuffer:readBoolean()
|
|
-- When char > 256, the readUByte method will show an error.
|
|
-- So, we have to use readChar
|
|
return self:readRawByteStr() == trueBooleanStrValue
|
|
end
|
|
|
|
|
|
--- byte
|
|
-- The byte is a number between -128 and 127, otherwise, the lua will get an error.
|
|
function ByteBuffer:writeByte(byteValue)
|
|
local str = string.pack("b", byteValue)
|
|
self:writeBuffer(str)
|
|
return self
|
|
end
|
|
|
|
function ByteBuffer:readByte()
|
|
local result = string.unpack("b", self:readRawByteStr())
|
|
return result
|
|
end
|
|
|
|
-- The byte is a number between 0 and 255, otherwise, the lua will get an error.
|
|
function ByteBuffer:writeUByte(ubyteValue)
|
|
self:writeRawByteStr(string.char(ubyteValue))
|
|
return self
|
|
end
|
|
|
|
function ByteBuffer:readUByte()
|
|
return string.byte(self:readRawByteStr())
|
|
end
|
|
|
|
|
|
-- short
|
|
function ByteBuffer:writeShort(shortValue)
|
|
local str = string.pack(">h", shortValue)
|
|
self:writeBuffer(str)
|
|
return self
|
|
end
|
|
|
|
function ByteBuffer:readShort()
|
|
local byteStrArray = self:readBuffer(2)
|
|
local result = string.unpack(">h", byteStrArray)
|
|
return result
|
|
end
|
|
|
|
|
|
-- int
|
|
function ByteBuffer:writeInt(intValue)
|
|
if (math.type(intValue) ~= "integer") then
|
|
error("intValue must be integer")
|
|
end
|
|
if ((minInt > intValue) or (intValue > maxInt)) then
|
|
error("intValue must range between minInt:-2147483648 and maxInt:2147483647")
|
|
end
|
|
|
|
return self:writeLong(intValue)
|
|
end
|
|
|
|
function ByteBuffer:readInt()
|
|
return self:readLong()
|
|
end
|
|
|
|
-- int
|
|
function ByteBuffer:writeRawInt(intValue)
|
|
local str = string.pack(">i", intValue)
|
|
self:writeBuffer(str)
|
|
return self
|
|
end
|
|
|
|
function ByteBuffer:readRawInt()
|
|
local byteStrArray = self:readBuffer(4)
|
|
local result = string.unpack(">i", byteStrArray)
|
|
return result
|
|
end
|
|
|
|
--long
|
|
function ByteBuffer:writeLong(longValue)
|
|
--Long:writeLong(self, longValue)
|
|
|
|
if (math.type(longValue) ~= "integer") then
|
|
error("longValue must be integer")
|
|
end
|
|
|
|
--lua中的右移为无符号右移,要特殊处理
|
|
local mask = longValue >> 63
|
|
local value = longValue << 1
|
|
if (mask == 1) then
|
|
value = value ~ 0xFFFFFFFFFFFFFFFF
|
|
end
|
|
|
|
if (value >> 7) == 0 then
|
|
self:writeUByte(value)
|
|
return
|
|
end
|
|
|
|
if (value >> 14) == 0 then
|
|
self:writeUByte(value & 0x7F | 0x80)
|
|
self:writeUByte((value >> 7) & 0x7F)
|
|
return
|
|
end
|
|
|
|
if (value >> 21) == 0 then
|
|
self:writeUByte((value & 0x7F) | 0x80)
|
|
self:writeUByte(((value >> 7) & 0x7F | 0x80))
|
|
self:writeUByte((value >> 14) & 0x7F)
|
|
return
|
|
end
|
|
|
|
if (value >> 28) == 0 then
|
|
self:writeUByte(value & 0x7F | 0x80)
|
|
self:writeUByte(((value >> 7) & 0x7F | 0x80))
|
|
self:writeUByte(((value >> 14) & 0x7F | 0x80))
|
|
self:writeUByte((value >> 21) & 0x7F)
|
|
return
|
|
end
|
|
|
|
if (value >> 35) == 0 then
|
|
self:writeUByte(value & 0x7F | 0x80)
|
|
self:writeUByte(((value >> 7) & 0x7F | 0x80))
|
|
self:writeUByte(((value >> 14) & 0x7F | 0x80))
|
|
self:writeUByte(((value >> 21) & 0x7F | 0x80))
|
|
self:writeUByte((value >> 28) & 0x7F)
|
|
return
|
|
end
|
|
|
|
if (value >> 42) == 0 then
|
|
self:writeUByte(value & 0x7F | 0x80)
|
|
self:writeUByte(((value >> 7) & 0x7F | 0x80))
|
|
self:writeUByte(((value >> 14) & 0x7F | 0x80))
|
|
self:writeUByte(((value >> 21) & 0x7F | 0x80))
|
|
self:writeUByte(((value >> 28) & 0x7F | 0x80))
|
|
self:writeUByte((value >> 35) & 0x7F)
|
|
return
|
|
end
|
|
|
|
if (value >> 49) == 0 then
|
|
self:writeUByte(value & 0x7F | 0x80)
|
|
self:writeUByte(((value >> 7) & 0x7F | 0x80))
|
|
self:writeUByte(((value >> 14) & 0x7F | 0x80))
|
|
self:writeUByte(((value >> 21) & 0x7F | 0x80))
|
|
self:writeUByte(((value >> 28) & 0x7F | 0x80))
|
|
self:writeUByte(((value >> 35) & 0x7F | 0x80))
|
|
self:writeUByte((value >> 42) & 0x7F)
|
|
return
|
|
end
|
|
|
|
if (value >> 56) == 0 then
|
|
self:writeUByte(value & 0x7F | 0x80)
|
|
self:writeUByte(((value >> 7) & 0x7F | 0x80))
|
|
self:writeUByte(((value >> 14) & 0x7F | 0x80))
|
|
self:writeUByte(((value >> 21) & 0x7F | 0x80))
|
|
self:writeUByte(((value >> 28) & 0x7F | 0x80))
|
|
self:writeUByte(((value >> 35) & 0x7F | 0x80))
|
|
self:writeUByte(((value >> 42) & 0x7F | 0x80))
|
|
self:writeUByte((value >> 49) & 0x7F)
|
|
return
|
|
end
|
|
|
|
self:writeUByte(value & 0x7F | 0x80)
|
|
self:writeUByte(((value >> 7) & 0x7F | 0x80))
|
|
self:writeUByte(((value >> 14) & 0x7F | 0x80))
|
|
self:writeUByte(((value >> 21) & 0x7F | 0x80))
|
|
self:writeUByte(((value >> 28) & 0x7F | 0x80))
|
|
self:writeUByte(((value >> 35) & 0x7F | 0x80))
|
|
self:writeUByte(((value >> 42) & 0x7F | 0x80))
|
|
self:writeUByte(((value >> 49) & 0x7F | 0x80))
|
|
self:writeUByte(value >> 56)
|
|
return self
|
|
end
|
|
|
|
function ByteBuffer:readLong()
|
|
--return Long:readLong(self):toString()
|
|
local b = self:readUByte()
|
|
local value = b & 0x7F
|
|
if (b & 0x80) ~= 0 then
|
|
b = self:readUByte()
|
|
value = value | ((b & 0x7F) << 7)
|
|
if (b & 0x80) ~= 0 then
|
|
b = self:readUByte()
|
|
value = value | ((b & 0x7F) << 14)
|
|
if (b & 0x80) ~= 0 then
|
|
b = self:readUByte()
|
|
value = value | ((b & 0x7F) << 21)
|
|
if (b & 0x80) ~= 0 then
|
|
b = self:readUByte()
|
|
value = value | ((b & 0x7F) << 28)
|
|
if (b & 0x80) ~= 0 then
|
|
b = self:readUByte()
|
|
value = value | ((b & 0x7F) << 35)
|
|
if (b & 0x80) ~= 0 then
|
|
b = self:readUByte()
|
|
value = value | ((b & 0x7F) << 42)
|
|
if (b & 0x80) ~= 0 then
|
|
b = self:readUByte()
|
|
value = value | ((b & 0x7F) << 49)
|
|
if (b & 0x80) ~= 0 then
|
|
b = self:readUByte()
|
|
value = value | (b << 56)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return (value >> 1) ~ -(value & 1)
|
|
end
|
|
|
|
--固定8位的lua数字类型
|
|
function ByteBuffer:writeLuaNumber(luaNumberValue)
|
|
local str = string.pack(">n", luaNumberValue)
|
|
self:writeBuffer(str)
|
|
return self
|
|
end
|
|
|
|
function ByteBuffer:readLuaNumber()
|
|
local result = string.unpack(">n", self:readBuffer(8))
|
|
return result
|
|
end
|
|
|
|
|
|
|
|
|
|
--float
|
|
function ByteBuffer:writeFloat(floatValue)
|
|
local str = string.pack(">f", floatValue)
|
|
self:writeBuffer(str)
|
|
return self
|
|
end
|
|
|
|
function ByteBuffer:readFloat()
|
|
local byteStrArray = self:readBuffer(4)
|
|
local result = string.unpack(">f", byteStrArray)
|
|
return result
|
|
end
|
|
|
|
|
|
--double
|
|
function ByteBuffer:writeDouble(doubleValue)
|
|
local str = string.pack(">d", doubleValue)
|
|
self:writeBuffer(str)
|
|
return self
|
|
end
|
|
|
|
function ByteBuffer:readDouble()
|
|
local byteStrArray = self:readBuffer(8)
|
|
local result = string.unpack(">d", byteStrArray)
|
|
return result
|
|
end
|
|
|
|
|
|
--string
|
|
function ByteBuffer:writeString(str)
|
|
if str == nil or #str == 0 then
|
|
self:writeInt(0)
|
|
return
|
|
end
|
|
self:writeInt(#str)
|
|
self:writeBuffer(str)
|
|
return self
|
|
end
|
|
|
|
function ByteBuffer:readString()
|
|
local length = self:readInt()
|
|
return self:readBuffer(length)
|
|
end
|
|
|
|
--char
|
|
function ByteBuffer:writeChar(charValue)
|
|
local str = utf8sub(charValue, 1, 1)
|
|
self:writeString(str)
|
|
return self
|
|
end
|
|
|
|
function ByteBuffer:readChar()
|
|
return self:readString()
|
|
end
|
|
|
|
--- Write a encoded char array into buf
|
|
function ByteBuffer:writeBuffer(str)
|
|
for i = 1, #str do
|
|
self:writeRawByteStr(string.sub(str, i, i))
|
|
end
|
|
return self
|
|
end
|
|
|
|
--- Read a byte array as string from current position, then update the position.
|
|
function ByteBuffer:readBuffer(length)
|
|
local byteStrArray = self:getBytes(self.readOffset, self.readOffset + length - 1)
|
|
self.readOffset = self.readOffset + length
|
|
return byteStrArray
|
|
end
|
|
|
|
function ByteBuffer:writeRawByteStr(byteStrValue)
|
|
if self.writeOffset > #self.buffer + 1 then
|
|
for i = #self.buffer + 1, self.writeOffset - 1 do
|
|
table.insert(self.buffer, zeroByte)
|
|
end
|
|
end
|
|
self.buffer[self.writeOffset] = string.sub(byteStrValue, 1, 1)
|
|
self.writeOffset = self.writeOffset + 1
|
|
return self
|
|
end
|
|
|
|
function ByteBuffer:readRawByteStr()
|
|
local byteStrValue = self.buffer[self.readOffset]
|
|
self.readOffset = self.readOffset + 1
|
|
return byteStrValue
|
|
end
|
|
|
|
--- Get all byte array as a lua string.
|
|
-- Do not update position.
|
|
function ByteBuffer:getBytes(startIndex, endIndex)
|
|
startIndex = startIndex or 1
|
|
endIndex = endIndex or #self.buffer
|
|
return table.concat(self.buffer, "", startIndex, endIndex)
|
|
end
|
|
|
|
return ByteBuffer |