Created
June 25, 2015 18:06
-
-
Save notcake/9ebcccfbaaa36a8bec36 to your computer and use it in GitHub Desktop.
XC.IO.BufferedStreamReader
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local self = {} | |
XC.IO.BufferedStreamReader = XC.MakeConstructor (self, XC.IO.StreamReader) | |
function self:ctor (inStream) | |
self.InStream = inStream | |
self.Position = 0 | |
self.BufferSize = 4096 | |
self.BufferPosition = 0 | |
self.Buffer = "" | |
end | |
-- IInStream | |
function self:Close () | |
if self.InStream then | |
self.InStream:Close () | |
self.InStream = nil | |
self.BufferPosition = 0 | |
self.Buffer = "" | |
end | |
end | |
function self:Read (size) | |
local bufferOffset = self.Position - self.BufferPosition | |
local bytesAvailable = #self.Buffer - bufferOffset | |
if size <= bytesAvailable then | |
local data = string.sub (self.Buffer, bufferOffset + 1, bufferOffset + size) | |
self.Position = self.Position + size | |
return data | |
end | |
local data = {} | |
local bytesRead = 0 | |
data [#data + 1] = string.sub (self.Buffer, bufferOffset + 1) | |
bytesRead = bytesRead + bytesAvailable | |
self.Position = self.Position + bytesAvailable | |
while bytesRead < size do | |
self:NextBlock () | |
if #self.Buffer == 0 then break end | |
bytesAvailable = #self.Buffer | |
if size - bytesRead <= bytesAvailable then | |
data [#data + 1] = string.sub (self.Buffer, 1, size - bytesRead) | |
bytesRead = bytesRead + size - bytesRead | |
self.Position = self.Position + size - bytesRead | |
else | |
data [#data + 1] = self.Buffer | |
bytesRead = bytesRead + bytesAvailable | |
self.Position = self.Position + bytesAvailable | |
end | |
end | |
return table.concat (data) | |
end | |
function self:GetPosition () | |
return self.Position | |
end | |
function self:GetSize () | |
return self.InStream:GetSize () | |
end | |
function self:SeekAbsolute (seekPos) | |
seekPos = math.max (seekPos, self:GetSize ()) | |
self.Position = seekPos | |
if self.Position < self.BufferPosition or | |
self.Position >= self.BufferPosition + #self.Buffer then | |
self.BufferPosition = self.BufferSize * math.floor (self.Position / self.BufferSize) | |
self.Buffer = "" | |
end | |
end | |
-- IStreamReader | |
function self:Char () | |
local bufferOffset = self.Position - self.BufferPosition | |
local bytesAvailable = #self.Buffer - bufferOffset | |
if bytesAvailable == 0 then | |
bufferOffset, bytesAvailable = self:FetchBlock () | |
end | |
local char = string.char (self.Buffer, bufferOffset + 1) | |
self.Position = self.Position + 1 | |
return char | |
end | |
function self:StringZ () | |
local bufferOffset = self.Position - self.BufferPosition | |
local bytesAvailable = #self.Buffer - bufferOffset | |
local terminatorPosition = string.find (self.Buffer, "\0", bufferOffset + 1, true) | |
if terminatorPosition then | |
local str = string.sub (self.Buffer, bufferOffset + 1, terminatorPosition - 1) | |
self.Position = self.Position + terminatorPosition - bufferOffset | |
return str | |
else | |
local str = {} | |
str [#str + 1] = string.sub (self.Buffer, bufferOffset + 1) | |
self.Position = self.Position + bytesAvailable | |
while true do | |
self:NextBlock () | |
if #self.Buffer == 0 then break end | |
terminatorPosition = string.find (self.Buffer, "\0", 1, true) | |
if terminatorPosition then | |
str [#str + 1] = string.sub (self.Buffer, 1, terminatorPosition - 1) | |
self.Position = self.Position + terminatorPosition | |
break | |
else | |
str [#str + 1] = self.Buffer | |
self.Position = self.Position + #self.Buffer | |
end | |
end | |
return table.concat (str) | |
end | |
end | |
-- StreamReader | |
function self:UInt81 () | |
local bufferOffset = self.Position - self.BufferPosition | |
local bytesAvailable = #self.Buffer - bufferOffset | |
local uint80 = nil | |
if bytesAvailable == 1 then | |
uint80 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 1) | |
elseif bytesAvailable <= 0 then | |
bufferOffset, bytesAvailable = self:NextBlock () | |
uint80 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 1) | |
end | |
self.Position = self.Position + 1 | |
return uint80 | |
end | |
function self:UInt82 () | |
local bufferOffset = self.Position - self.BufferPosition | |
local bytesAvailable = #self.Buffer - bufferOffset | |
local uint80, uint81 = nil, nil | |
if bytesAvailable == 2 then | |
uint80, uint81 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 2) | |
elseif bytesAvailable == 1 then | |
uint80 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 1) | |
bufferOffset, bytesAvailable = self:NextBlock () | |
uint81 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 1) | |
elseif bytesAvailable <= 0 then | |
bufferOffset, bytesAvailable = self:NextBlock () | |
uint80, uint81 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 2) | |
end | |
self.Position = self.Position + 2 | |
return uint80, uint81 | |
end | |
function self:UInt84 () | |
local bufferOffset = self.Position - self.BufferPosition | |
local bytesAvailable = #self.Buffer - bufferOffset | |
local uint80, uint81, uint82, uint83 = nil, nil, nil, nil | |
if bytesAvailable == 4 then | |
uint80, uint81, uint82, uint83 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 4) | |
elseif bytesAvailable == 3 then | |
uint80, uint81, uint82 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 3) | |
bufferOffset, bytesAvailable = self:NextBlock () | |
uint83 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 1) | |
elseif bytesAvailable == 2 then | |
uint80, uint81 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 2) | |
bufferOffset, bytesAvailable = self:NextBlock () | |
uint82, uint83 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 2) | |
elseif bytesAvailable == 1 then | |
uint80 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 1) | |
bufferOffset, bytesAvailable = self:NextBlock () | |
uint81, uint82, uint83 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 3) | |
elseif bytesAvailable == 0 then | |
bufferOffset, bytesAvailable = self:NextBlock () | |
uint80, uint81, uint82, uint83 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 4) | |
end | |
self.Position = self.Position + 4 | |
return uint80, uint81, uint82, uint83 | |
end | |
function self:UInt88 () | |
local bufferOffset = self.Position - self.BufferPosition | |
local bytesAvailable = #self.Buffer - bufferOffset | |
local uint80, uint81, uint82, uint83, uint84, uint85, uint86, uint87 = nil, nil, nil, nil, nil, nil, nil, nil | |
if bytesAvailable == 8 then | |
uint80, uint81, uint82, uint83, uint84, uint85, uint86, uint87 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 8) | |
elseif bytesAvailable == 7 then | |
uint80, uint81, uint82, uint83, uint84, uint85, uint86 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 7) | |
bufferOffset, bytesAvailable = self:NextBlock () | |
uint87 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 1) | |
elseif bytesAvailable == 6 then | |
uint80, uint81, uint82, uint83, uint84, uint85 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 6) | |
bufferOffset, bytesAvailable = self:NextBlock () | |
uint86, uint87 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 2) | |
elseif bytesAvailable == 5 then | |
uint80, uint81, uint82, uint83, uint84 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 5) | |
bufferOffset, bytesAvailable = self:NextBlock () | |
uint85, uint86, uint87 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 3) | |
elseif bytesAvailable == 4 then | |
uint80, uint81, uint82, uint83 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 4) | |
bufferOffset, bytesAvailable = self:NextBlock () | |
uint84, uint85, uint86, uint87 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 4) | |
elseif bytesAvailable == 3 then | |
uint80, uint81, uint82 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 3) | |
bufferOffset, bytesAvailable = self:NextBlock () | |
uint83, uint84, uint85, uint86, uint87 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 5) | |
elseif bytesAvailable == 2 then | |
uint80, uint81 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 2) | |
bufferOffset, bytesAvailable = self:NextBlock () | |
uint82, uint83, uint84, uint85, uint86, uint87 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 6) | |
elseif bytesAvailable == 1 then | |
uint80 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 1) | |
bufferOffset, bytesAvailable = self:NextBlock () | |
uint81, uint82, uint83, uint84, uint85, uint86, uint87 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 7) | |
elseif bytesAvailable == 0 then | |
bufferOffset, bytesAvailable = self:NextBlock () | |
uint80, uint81, uint82, uint83, uint84, uint85, uint86, uint87 = string.byte (self.Buffer, bufferOffset + 1, bufferOffset + 8) | |
end | |
self.Position = self.Position + 8 | |
return uint80, uint81, uint82, uint83, uint84, uint85, uint86, uint87 | |
end | |
-- Internal, do not call | |
function self:NextBlock () | |
self.BufferPosition = self.BufferSize * math.floor (self.Position / self.BufferSize) | |
self.Buffer = "" | |
self.InStream:SeekAbsolute (self.BufferPosition) | |
self.Buffer = self.InStream:Read (self.BufferSize) | |
local bufferOffset = self.Position - self.BufferPosition | |
local bytesAvailable = #self.Buffer - bufferOffset | |
return bufferOffset, bytesAvailable | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment