Xetrill

xs_utils.script

Aug 19th, 2013
280
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.11 KB | None | 0 0
  1. --[[-----------------------------------------------------------------------\\--
  2.     :: PRIVATE ::
  3. --\\-----------------------------------------------------------------------]]--
  4.  
  5. local type, tostring, getmetatable, setmetatable, rawset, srepeat, sprintf
  6.     = type, tostring, getmetatable, setmetatable, rawset, string.rep, string.format
  7. local insert, remove, concat
  8.     = table.insert, table.remove, table.concat
  9.  
  10.  
  11. --[[-----------------------------------------------------------------------\\--
  12.     :: PUBLIC ::
  13. --\\-----------------------------------------------------------------------]]--
  14.  
  15. __FILE__ = "xs_utils"
  16.  
  17.     --[[-------------------------------------------------------------------\\--
  18.         :: Category: Type Converters
  19.     --\\-------------------------------------------------------------------]]--
  20.  
  21.     function vec2tbl(v)
  22.         local t = { x = v.x, y = v.y, z = v.z, }
  23.         return t
  24.     end
  25.  
  26.     function tbl2vec(t)
  27.         local v = vector():set(t.x, t.y, t.z)
  28.         return v
  29.     end
  30.  
  31.  
  32.     --[[-------------------------------------------------------------------\\--
  33.         :: Category: Number Handling
  34.     --\\-------------------------------------------------------------------]]--
  35.  
  36.     function clamp(num, min, max)
  37.         if num < min then
  38.             return min
  39.         elseif num > max then
  40.             return max
  41.         else
  42.             return num
  43.         end
  44.     end
  45.  
  46.  
  47.     --[[-------------------------------------------------------------------\\--
  48.         :: Category: String Handling
  49.     --\\-------------------------------------------------------------------]]--
  50.  
  51.     function extractNo(text, offset, count)
  52.         if not text or text:len() == 0 then
  53.             return nil
  54.         end
  55.         count = tonumber(count) or math.huge
  56.         local index  = offset or 0
  57.         local length = text:len() + 1
  58.         local number = {}
  59.         while index < length and #number < count do
  60.             local digit = tonumber(text:sub(index, index))
  61.             if digit ~= nil then
  62.                 insert(number, digit)
  63.             end
  64.             index = index + 1
  65.         end
  66.         return tonumber(concat(number, ""))
  67.     end
  68.  
  69.     -- Concatinates all passed in strings into a single string.
  70.     -- Note that this function only expects string as arguments and assumes that.
  71.     -- @param string delimiter  The delimiter with which to concatenate.
  72.     -- @param string ...        The strings to be concatenated.
  73.     -- @return string
  74.     function join(delimiter, ...)
  75.         local p, t = { ... }, {}
  76.         for _, v in ipairs(p) do
  77.             insert(t, v)
  78.         end
  79.         return concat(t, delimiter)
  80.     end
  81.  
  82.     function split(separator, text)
  83.         if text:len() <= 1 then
  84.             return { text }
  85.         end
  86.  
  87.         local result, offset, current = {}, 0, 0
  88.         while true do
  89.             current = text:find(separator, offset, true)
  90.             if current ~= nil then
  91.                 insert(result, text:sub(offset, current - 1))
  92.                 offset = current + 1
  93.             else
  94.                 insert(result, text:sub(offset))
  95.                 break
  96.             end
  97.         end
  98.  
  99.         return result
  100.     end
  101.  
  102.     -- @see http:--lua-users.org/wiki/StringTrim (trim12)
  103.     function trim(s)
  104.         local from = s:match("^%s*()")
  105.         return from > #s and "" or s:match(".*%S", from)
  106.     end
  107.  
  108.  
  109.     --[[-------------------------------------------------------------------\\--
  110.         :: Category: Table Handling
  111.     --\\-------------------------------------------------------------------]]--
  112.  
  113.     function clone(t, deep, seen)
  114.         seen = seen or {}
  115.  
  116.         if t == nil then
  117.             return nil
  118.         end
  119.         if seen[t] then
  120.             return seen[t]
  121.         end
  122.  
  123.         local nt = {}
  124.         seen[t] = nt
  125.         for k, v in pairs(t) do
  126.             if deep and type(v) == 'table' then
  127.                 nt[k] = clone(v, deep, seen)
  128.             else
  129.                 nt[k] = v
  130.             end
  131.         end
  132.         setmetatable(nt, clone(getmetatable(t), deep, seen))
  133.  
  134.         return nt
  135.     end
  136.  
  137.  
  138.     -- TODO: test and use me ^^
  139.     function getIterator(obj)
  140.         local type = type(obj)
  141.         if type == "userdata" and obj.getIterator then
  142.             return obj:getIterator()
  143.         elseif type == "table" then
  144.             if obj[1] ~= nil then
  145.                 return ipairs(obj)
  146.             else
  147.                 return pairs(obj)
  148.             end
  149.         else
  150.             -- TODO: write custom iterator that returns the passed-in value.
  151.             return obj, function () return obj end, nil
  152.         end
  153.     end
  154.  
  155.     function toEnumTable(...)
  156.         local l = select('#', ...)
  157.         check(l, "[toEnumTable]: no arguments passed.")
  158.  
  159.         local table = {}
  160.         for i = 1, l do
  161.             table[v] = i
  162.         end
  163.  
  164.         return toReadOnlyTable(table)
  165.     end
  166.  
  167.     function toFlagsTable(...)
  168.         local l = select('#', ...)
  169.         check(l, "[toFlagsTable]: no arguments passed.")
  170.  
  171.         local pow = math.pow
  172.         local table = {}
  173.         for i = 1, l do
  174.             table[v] = pow(2, select(i, ...) - 1)
  175.         end
  176.  
  177.         return toReadOnlyTable(table)
  178.     end
  179.  
  180.     function toWeakTable(table, mode)
  181.         check(type(table) == "table")
  182.         check(mode == nil or (type(mode) == "string" and #mode == 1))
  183.  
  184.         local mt = getmetatable(table) or {}
  185.         mt.__mode = mode or "k"
  186.         setmetatable(table, mt)
  187.  
  188.         return table
  189.     end
  190.  
  191.     -- Using a metatable makes the specified table read only, by overloading
  192.     -- __newindex. Note that table.insert will not be prevented with this.
  193.     -- Also modifying a already specified key will be possible.
  194.     -- @param table t  The table to made read-only.
  195.     -- @return table
  196.     function toReadOnlyTable(t)
  197.         check(type(t) == "table",
  198.               "[toReadOnlyTable]: expects a table as its first argument not a [%s]",
  199.               type(t))
  200.         return setmetatable(t, {
  201.             __index = t,
  202.             __newindex = function (self, k, v)
  203.                 abort("Illegal attempt to modify a read-only table. [key: %s, value = %s]",
  204.                       tostring(k), tostring(v))
  205.             end,
  206.             __metatable = false
  207.         })
  208.     end
  209.  
  210.     -- Creates a lookup-only table, a table where each value is true.
  211.     -- @param number|string ...  The values you want to look-up.
  212.     -- @return table  An lookup-optimized table.
  213.     function toLookupTable(...)
  214.         local l, t = select('#', ...), {}
  215.         for i = 1, l do
  216.             rawset(t, select(i, ...), true)
  217.         end
  218.         return t
  219.     end
  220.  
  221.     function map(table, func, iter)
  222.         iter = iter or pairs
  223.         for k, v in iter(table) do
  224.             table[k] = func(v, k)
  225.         end
  226.         return table
  227.     end
  228.  
  229.     function count(table, selector, iter)
  230.         iter = iter or pairs
  231.         selector = selector or function (v, k) return true end
  232.         local c = 0
  233.         for k, v in iter(table) do
  234.             if selector(v, k) then
  235.                 c = c + 1
  236.             end
  237.         end
  238.         return c
  239.     end
  240.  
  241.     function sum(table, selector, iter)
  242.         iter = iter or pairs
  243.         selector = selector or function (v, k) return tonumber(v) end
  244.         local t = 0
  245.         for k, v in iter(table) do
  246.             t = t + selector(v, k)
  247.         end
  248.         return t
  249.     end
  250.  
  251.     function min(table, selector, iter)
  252.         iter = iter or pairs
  253.         selector = selector or function (v, k) return tonumber(v) end
  254.         local n, i = nil, nil
  255.         for k, v in iter(table) do
  256.             local c = selector(v, k)
  257.             if n == nil or c < n then
  258.                 n, i = c, k
  259.             end
  260.         end
  261.         return n, i
  262.     end
  263.  
  264.     function find(table, value, selector, iter)
  265.         iter = iter or pairs
  266.         selector = selector or function (v, k) return v end
  267.         for k, v in iter(table) do
  268.             if value == selector(v, k) then
  269.                 return k
  270.             end
  271.         end
  272.         return nil
  273.     end
  274.  
  275.     function all(table, predicate, iter)
  276.         iter = iter or pairs
  277.         predicate = predicate or function (v, k) return true end
  278.         local results = {}
  279.         if iter == ipairs then
  280.             for k, v in iter(table) do
  281.                 if predicate(v, k) then
  282.                     insert(results, v)
  283.                 end
  284.             end
  285.         else
  286.             for k, v in iter(table) do
  287.                 if predicate(v, k) then
  288.                     results[k] = v
  289.                 end
  290.             end
  291.         end
  292.         return results
  293.     end
  294.  
  295.     function any(table, predicate, iter)
  296.         iter = iter or pairs
  297.         predicate = predicate or function (v, k) return true end
  298.         for k, v in iter(table) do
  299.             if predicate(v, k) then
  300.                 return k, v
  301.             end
  302.         end
  303.         return nil
  304.     end
  305.  
  306.     function max(table, selector, iter)
  307.         iter = iter or pairs
  308.         selector = selector or function (v, k) return tonumber(v) end
  309.         local n, i = nil, nil
  310.         for k, v in iter(table) do
  311.             local c = selector(v, k)
  312.             if n == nil or c > n then
  313.                 n, i = c, k
  314.             end
  315.         end
  316.         return n, i
  317.     end
  318.  
  319.     function filter(table, selector, iter)
  320.         check(type(selector) == "function",
  321.               "[xs_utils.filter]: Invalid argument #1, function expected.")
  322.  
  323.         iter = iter or pairs
  324.  
  325.         local r = {}
  326.         for k, v in iter(table) do
  327.             if selector(v, k) then
  328.                 r[k] = v
  329.             end
  330.         end
  331.         return r
  332.     end
  333.  
  334.     function retain(table, selector, iter)
  335.         check(type(selector) == "function",
  336.               "[xs_utils.retain]: Invalid argument #1, function expected.")
  337.  
  338.         iter = iter or pairs
  339.  
  340.         for k, v in iter(table) do
  341.             if not selector(v, k) then
  342.                 remove(table, k)
  343.             end
  344.         end
  345.         return table
  346.     end
  347.  
  348.     -- Creates a new table that is a shallow copy of all tabled passed in.
  349.     -- Note that the passed in arguments are traversed in reverse order,
  350.     -- therefore the very first argument has the highest priority and the
  351.     -- very last one has the lowest priority.
  352.     -- @param table ...  Any table you want to merge.
  353.     -- @return table
  354.     function merge(...)
  355.         local t = {}
  356.         mergeInto(t, ...)
  357.         return t
  358.     end
  359.  
  360.     -- Merges any number of tables in a provided target table.
  361.     -- The shallow merge takes place in reverse order, meaning that
  362.     -- the very first table has the highest priority and will be copied
  363.     -- last.
  364.     -- @param table target  The target table into which all the others
  365.     --   are merged into.
  366.     -- @param table ...  All the tables to be merged into the target table.
  367.     -- @return void
  368.     function mergeInto(target, ...)
  369.         local a = { ... }
  370.         for i = #a, 1, -1 do
  371.             for k, v in pairs(a[i]) do
  372.                 target[k] = v
  373.             end
  374.         end
  375.     end
  376.  
  377.     -- Puts the content of some tables into a target table.
  378.     -- @param table target  The target table into which all the other table
  379.     --   values are put into.
  380.     -- @param table ...  All the tables to be 'put' into the target table.
  381.     -- @return void
  382.     function putInto(target, ...)
  383.         local a = { ... }
  384.         for i = #a, 1, -1 do
  385.             for _, v in pairs(a[i]) do
  386.                 insert(target, v)
  387.             end
  388.         end
  389.     end
  390.  
  391.  
  392.     --[[-------------------------------------------------------------------\\--
  393.         :: Category: Callbacks
  394.     --\\-------------------------------------------------------------------]]--
  395.  
  396.     -- TODO: test createCallback, parseCallback, combineCallbacks
  397.     -- TODO: add class support
  398.     function createCallback(file, func)
  399.         check(file == nil or type(file) == "string" and file:len() > 0,
  400.               "[xs_utils.createCallback]: Invalid #1 argument: '%s'.", tostring(file))
  401.         check(type(func) == "string" and func:len() > 0,
  402.               "[xs_utils.createCallback]: Invalid #2 argument: '%s'.", tostring(file))
  403.  
  404.         return { file, func }
  405.     end
  406.  
  407.     -- TODO: Check if its not better to use load or loadstring instead.
  408.     --     The JIT can inline code.
  409.     function parseCallback(callback)
  410.         check(type(callback) == "table",
  411.               "[xs_utils.parseCallback]: Invalid #1 argument must be a table.")
  412.         check(#callback >= 1 and #callback <= 2,
  413.               "[xs_utils.parseCallback]: Invalid #1 argument must be a table with 1 to 2 values in it.")
  414.  
  415.         local file, func = unpack(callback)
  416.         local result = (file ~= nil and _G[file][func]) or _G[func]
  417.  
  418.         check(type(result) == "function",
  419.               "[xs_utils.parseCallback]: Invalid callback '%s.%s', its not a function.",
  420.               file, func)
  421.  
  422.         return result
  423.     end
  424.  
  425.     -- Note: This uses loadstring which has to parse and lex what's passed to it.
  426.     -- And after that is gets JIT-ed, which all take their time, so result should be cached.
  427.     function combineCallbacks(callInfos)
  428.         local buffer = {}
  429.         for _, callInfo in ipairs(callInfos) do
  430.             local file, func = unpack(callInfo)
  431.             if file then
  432.                 insert(buffer, sprintf('%s.%s(...);\n', file, func))
  433.             else
  434.                 insert(buffer, sprintf('%s(...);\n', func))
  435.             end
  436.         end
  437.         local res, err = loadstring(concat(buffer, ''), '=(combineCallbacks)')
  438.         if err then
  439.             abort("[xs_utils.combineCallbacks]: Failed to combine callbacks, see Lua error:", err)
  440.         end
  441.         return res
  442.     end
  443.  
  444.  
  445.     --[[-------------------------------------------------------------------\\--
  446.         :: Category: Miscellaneous
  447.     --\\-------------------------------------------------------------------]]--
  448.  
  449.     function check(condition, fmt, ...)
  450.         if condition then
  451.             return
  452.         end
  453.  
  454.         if xs and xs.logClose then
  455.             pcall(xs.logClose)
  456.         end
  457.  
  458.         if ... == nil then
  459.             error(fmt, 2)
  460.         else
  461.             error(fmt:format(...), 2)
  462.         end
  463.     end
  464.  
  465.     local m_refTypes = toLookupTable("table", "userdata", "function", "thread")
  466.  
  467.     function isRefType(obj)
  468.         return m_refTypes[type(obj)] == true
  469.     end
  470.  
  471.     function isValueType(obj)
  472.         return m_refTypes[type(obj)] ~= true
  473.     end
Advertisement
Add Comment
Please, Sign In to add comment