I usually do the check by myself so I can provide correct errors (This is for a utf library that complements utf8):
Code: Select all
utf.sub = function (str, a, b)
-- Default for finish is the end of the string
local start, finish = tonumber(a), tonumber(b or -1)
-- Type checking
if type(str) ~= "string" then
error("bad argument #1 to 'sub' (string expected got "..type(str)..")", 2)
elseif type(start) ~= "number" then
error("bad argument #2 to 'sub' (number expected got "..type(a)..")", 2)
elseif type(finish) ~= "number" then
error("bad argument #3 to 'sub' (number expected got "..type(b)..")", 2)
end
local len = u.len(str)
-- Negative values count from the end
-- Minimum value for start is 1 and maximum value for finish is len
start = math.max(start < 0 and len + 1 + start or start, 1)
finish = math.min(finish < 0 and len + 1 + finish or finish, len)
-- Start comes after finish
if start > finish then return "" end
-- This lines fixes the position so that they are in bytes for string.sub
return string.sub(str, u.offset(str, start), finish == len and -1 or u.offset(str, finish + 1) - 1) or ""
end
Asserts make the function error and the error report points to the line where the assertion is, so if you want to see what called that function you have to check the stack overflow, the 2 in the error function actually tells Lua to pop 1 from the stack and instead of saying that the error is there, it tells you that the error is where you called the parent function
Also note that this is my coding style for functions, functions do one thing and one thing only and as I said before, files are modules, each handle one thing and can be used, pretty much like libraries (except most of the time they depend on other modules)