-- Copyright (c) 2024 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at:
--         http://license.coscl.org.cn/MulanPSL2
-- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
-- EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
-- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.

local BinParser = {
    filename = "",
    size = 0
}

local log = require "log"
local cjson = require "cjson"

function BinParser:new(o, filename, size)
    o = o or {}
    setmetatable(o, self)
    self.__index = self
    self.filename = filename..".bin"
    self.size = size
    return o
end

function BinParser:create_file()
    local file = io.open(self.filename, "rb")
    if file then
        file:close()
        return
    end

    local cmd = 'dd if=/dev/zero of='..self.filename..' bs='..tostring(self.size)..' count=1'
    os.execute(cmd)
end

function BinParser:read_data(offset, length)
    self:create_file()
    local file, err_info = io.open(self.filename, "rb")
    if file == nil then
        log:print(LOG_ERROR, "open file fail. filename: %s, %s", self.filename, err_info)
        return
    end
    local result = {}
    local flen = file:seek("end")
    if offset + length <= flen then
        file:seek("set", offset)
        local read_buffer = file:read(length)
        for i = 1, #read_buffer do
            local ch = tonumber(string.byte(read_buffer, i, i))
            result[i] = ch
        end
    end
    file:close()
    return result
end

function BinParser:write_data(offset, data)
    self:create_file()
    local file, err_info = io.open(self.filename, "r+b")
    if file == nil then
        log:print(LOG_ERROR, "open file fail. filename: %s, %s", self.filename, err_info)
        return
    end
    local flen = file:seek("end")
    if offset + #data > flen then
        file:close()
        return
    end
    file:seek("set")
    local write_buffer = {}
    local read_buffer = file:read(flen)
    for i = 1, #read_buffer do
        local ch = tonumber(string.byte(read_buffer, i, i))
        write_buffer[i] = ch
    end
    local i = offset + 1
    local j = 1
    while i <= offset + #data do
        write_buffer[i] = data[j]
        i = i + 1
        j = j + 1
    end
    file:seek("set")
    for i = 1, #write_buffer do
        file:write(string.char(write_buffer[i]))
    end
    file:close()
end

return BinParser