-- vstruct, the versatile struct library

-- Copyright (C) 2011 Ben "ToxicFrog" Kelly; see COPYING

local table,math,type,require,assert,_unpack = table,math,type,require,assert,unpack
local debug = debug
local print = print

module "vstruct"

_VERSION = "1.1"

cursor = require "vstruct.cursor"

local ast    = require "vstruct.ast"

-- cache control for the parser
-- true: cache is read/write (new formats will be cached, old ones retrieved)
-- false: cache is read-only
-- nil: cache is disabled
cache = true

-- this is needed by some IO formats as well as init itself
-- FIXME: should it perhaps be a vstruct internal function rather than
-- installing it in math?
if not math.trunc then
	function math.trunc(n)
		if n < 0 then
			return math.ceil(n)
		else
			return math.floor(n)
		end
	end
end

-- turn an int into a list of booleans
-- the length of the list will be the smallest number of bits needed to
-- represent the int
function explode(int, size)
    assert(int, "vstruct.explode: missing argument")
    size = size or 0
    
    local mask = {}
    while int ~= 0 or #mask < size do
        table.insert(mask, int % 2 ~= 0)
        int = math.trunc(int/2)
    end
    return mask
end

-- turn a list of booleans into an int
-- the converse of explode
function implode(mask, size)
    size = size or #mask
    
    local int = 0
    for i=size,1,-1 do
        int = int*2 + ((mask[i] and 1) or 0)
    end
    return int
end

-- Given a format string, a buffer or file, and an optional third argument,
-- unpack data from the buffer or file according to the format string
function unpack(fmt, ...)
    assert(type(fmt) == "string", "invalid first argument to vstruct.unpack")
    
    local t = ast.parse(fmt)
    return t.unpack(...)
end

-- Given a format string, an optional file-like, and a table of data,
-- pack data into the file-like (or create and return a string of packed data)
-- according to the format string
function pack(fmt, ...)
    local t = ast.parse(fmt)
    return t.pack(...)
end

-- Given a format string, compile it and return a table containing the original
-- source and the pack/unpack functions derived from it.
function compile(fmt)
	return ast.parse(fmt)
end

return _M
