UtilFunc = { }

-- Encodes a string as a series of hexadecimal characters in a string
function UtilFunc.HexEncode(str)

	local idx
	local result
	
	if type(str) == "string" then
		local strLen = str:len()
		result = ""
		for idx = 1,strLen do
			result = result..string.format("%.2X", str:byte(idx))
		end
	end
	
	return result
	
end

-- hexDecodeTable is a lookup for each character to its nybble value
UtilFunc.hexDecodeTable = { }

UtilFunc.hexDecodeTable['0'] = 0
UtilFunc.hexDecodeTable['1'] = 1
UtilFunc.hexDecodeTable['2'] = 2
UtilFunc.hexDecodeTable['3'] = 3
UtilFunc.hexDecodeTable['4'] = 4
UtilFunc.hexDecodeTable['5'] = 5
UtilFunc.hexDecodeTable['6'] = 6
UtilFunc.hexDecodeTable['7'] = 7
UtilFunc.hexDecodeTable['8'] = 8
UtilFunc.hexDecodeTable['9'] = 9
UtilFunc.hexDecodeTable['A'] = 10
UtilFunc.hexDecodeTable['B'] = 11
UtilFunc.hexDecodeTable['C'] = 12
UtilFunc.hexDecodeTable['D'] = 13
UtilFunc.hexDecodeTable['E'] = 14
UtilFunc.hexDecodeTable['F'] = 15
UtilFunc.hexDecodeTable['a'] = 10
UtilFunc.hexDecodeTable['b'] = 11
UtilFunc.hexDecodeTable['c'] = 12
UtilFunc.hexDecodeTable['d'] = 13
UtilFunc.hexDecodeTable['e'] = 14
UtilFunc.hexDecodeTable['f'] = 15

-- Decodes a string of hexadecimal characters into a string
function UtilFunc.HexDecode(str)

	local result
	
	if type(str) == "string" then
	
		local strLen = str:len()
		
		if (strLen % 2) == 0 then

			local idx
		
			result = ""
			
			for idx = 1,strLen,2 do
			
				local c1 = UtilFunc.hexDecodeTable[str:sub(idx,idx)]
				local c2 = UtilFunc.hexDecodeTable[str:sub(idx+1,idx+1)]
			
				if c1 and c2 then
					result = result..string.char(c1*16+c2)
				else
					result = nil
					break
				end
				
			end
		end
	end
end

-- determines if a variable has a metatable that defines tostring
function UtilFunc.HasToString(vx)

	local result
	local mt = getmetatable(vx)
	local mtidx = mt and mt.__index
	local mtidxtostr = mtidx and mtidx.__tostring

	return not not mtidxtostr

end


-- returns a string displaying all members of a table, recursively
function UtilFunc.ShowTable(vx, useToStringIfAvailable)

	if useToStringIfAvailable == nil then useToStringIfAvailable = true end

	local result = ""
	local typestr = type(vx)

	if useToStringIfAvailable and UtilFunc.HasToString(vx) then
		result = "{ "..tostring(vx).." }"
	elseif typestr == "table" then
		result = "{"
		for k,v in pairs(vx) do
			local ts = type(v)
			if ts ~= "function" then
				result = result.." ("..tostring(k)..","..UtilFunc.ShowTable(v)..")"
			end
		end
		result = result.." }"
	elseif typestr == "string" then
		result = "<"..typestr.."> '"..UtilFunc.TranslateString(vx).."'"
	elseif typestr ~= "function" then
		result = "<"..type(vx).."> "..tostring(vx)
	end
	
	return result
	
end

-- Returns a table of matches for patstr in str (nil if no matches)
function UtilFunc.SplitString(str, patstr)

	local result

	for part in str:gmatch(patstr) do
		if not result then result = {} end
		table.insert(result, part)
	end

	return result

end

-- Translates a binary string into something that can be printed without
-- control characters
function UtilFunc.TranslateString(s)

	local s0 = tostring(s)
	local i
	local t = { }

	for i = 1, #s0 do

	    local c = string.byte(s0,i)
	    local c2

	    if c==13 then 			c2="\\r" 
	    elseif c==10 then 			c2="\\n"
	    elseif c>=32 and c<127 then 	c2=string.char(c)
	    else 				c2="\\x"..string.format("%.2X", c)
	    end

	    table.insert(t, c2)

	end

	local result = table.concat(t)
	return result

end

return UtilFunc

