5f9c609f65c8da89b462dbb7326ceea9259faaa9
[project/luci.git] / libs / core / luasrc / util.lua
1 --[[
2 LuCI - Utility library
3
4 Description:
5 Several common useful Lua functions
6
7 FileId:
8 $Id$
9
10 License:
11 Copyright 2008 Steven Barth <steven@midlink.org>
12
13 Licensed under the Apache License, Version 2.0 (the "License");
14 you may not use this file except in compliance with the License.
15 You may obtain a copy of the License at
16
17 http://www.apache.org/licenses/LICENSE-2.0
18
19 Unless required by applicable law or agreed to in writing, software
20 distributed under the License is distributed on an "AS IS" BASIS,
21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 See the License for the specific language governing permissions and
23 limitations under the License.
24
25 ]]--
26
27 local io = require "io"
28 local math = require "math"
29 local table = require "table"
30 local debug = require "debug"
31 local ldebug = require "luci.debug"
32 local string = require "string"
33 local coroutine = require "coroutine"
34
35 local getmetatable, setmetatable = getmetatable, setmetatable
36 local rawget, rawset, unpack = rawget, rawset, unpack
37 local tostring, type, assert = tostring, type, assert
38 local ipairs, pairs, loadstring = ipairs, pairs, loadstring
39 local require, pcall, xpcall = require, pcall, xpcall
40
41 --- LuCI utility functions.
42 module "luci.util"
43
44 --
45 -- Pythonic string formatting extension
46 --
47 getmetatable("").__mod = function(a, b)
48 if not b then
49 return a
50 elseif type(b) == "table" then
51 return a:format(unpack(b))
52 else
53 return a:format(b)
54 end
55 end
56
57
58 --
59 -- Class helper routines
60 --
61
62 --- Create a Class object (Python-style object model).
63 -- The class object can be instantiated by calling itself.
64 -- Any class functions or shared parameters can be attached to this object.
65 -- Attaching a table to the class object makes this table shared between
66 -- all instances of this class. For object parameters use the __init__ function.
67 -- Classes can inherit member functions and values from a base class.
68 -- Class can be instantiated by calling them. All parameters will be passed
69 -- to the __init__ function of this class - if such a function exists.
70 -- The __init__ function must be used to set any object parameters that are not shared
71 -- with other objects of this class. Any return values will be ignored.
72 -- @param base The base class to inherit from (optional)
73 -- @return A class object
74 -- @see instanceof
75 -- @see clone
76 function class(base)
77 local class = {}
78
79 local create = function(class, ...)
80 local inst = setmetatable({}, {__index = class})
81
82 if inst.__init__ then
83 inst:__init__(...)
84 end
85
86 return inst
87 end
88
89 local classmeta = {__call = create}
90
91 if base then
92 classmeta.__index = base
93 end
94
95 setmetatable(class, classmeta)
96 return class
97 end
98
99 --- Test whether the given object is an instance of the given class.
100 -- @param object Object instance
101 -- @param class Class object to test against
102 -- @return Boolean indicating whether the object is an instance
103 -- @see class
104 -- @see clone
105 function instanceof(object, class)
106 local meta = getmetatable(object)
107 while meta and meta.__index do
108 if meta.__index == class then
109 return true
110 end
111 meta = getmetatable(meta.__index)
112 end
113 return false
114 end
115
116
117 --
118 -- Scope manipulation routines
119 --
120
121 --- Create a new or get an already existing thread local store associated with
122 -- the current active coroutine. A thread local store is private a table object
123 -- whose values can't be accessed from outside of the running coroutine.
124 -- @return Table value representing the corresponding thread local store
125 function threadlocal()
126 local tbl = {}
127
128 local function get(self, key)
129 local c = coroutine.running()
130 local thread = coxpt[c] or c or 0
131 if not rawget(self, thread) then
132 return nil
133 end
134 return rawget(self, thread)[key]
135 end
136
137 local function set(self, key, value)
138 local c = coroutine.running()
139 local thread = coxpt[c] or c or 0
140 if not rawget(self, thread) then
141 rawset(self, thread, {})
142 end
143 rawget(self, thread)[key] = value
144 end
145
146 setmetatable(tbl, {__index = get, __newindex = set, __mode = "k"})
147
148 return tbl
149 end
150
151
152 --
153 -- Debugging routines
154 --
155
156 --- Write given object to stderr.
157 -- @param obj Value to write to stderr
158 -- @return Boolean indicating whether the write operation was successful
159 function perror(obj)
160 return io.stderr:write(tostring(obj) .. "\n")
161 end
162
163 --- Recursively dumps a table to stdout, useful for testing and debugging.
164 -- @param t Table value to dump
165 -- @param maxdepth Maximum depth
166 -- @return Always nil
167 function dumptable(t, maxdepth, i, seen)
168 i = i or 0
169 seen = seen or setmetatable({}, {__mode="k"})
170
171 for k,v in pairs(t) do
172 perror(string.rep("\t", i) .. tostring(k) .. "\t" .. tostring(v))
173 if type(v) == "table" and (not maxdepth or i < maxdepth) then
174 if not seen[v] then
175 seen[v] = true
176 dumptable(v, maxdepth, i+1, seen)
177 else
178 perror(string.rep("\t", i) .. "*** RECURSION ***")
179 end
180 end
181 end
182 end
183
184
185 --
186 -- String and data manipulation routines
187 --
188
189 --- Escapes all occurrences of the given character in given string.
190 -- @param s String value containing unescaped characters
191 -- @param c String value with character to escape (optional, defaults to "\")
192 -- @return String value with each occurrence of character escaped with "\"
193 function escape(s, c)
194 c = c or "\\"
195 return s:gsub(c, "\\" .. c)
196 end
197
198 --- Create valid XML PCDATA from given string.
199 -- @param value String value containing the data to escape
200 -- @return String value containing the escaped data
201 function pcdata(value)
202 if not value then return end
203 value = tostring(value)
204 value = value:gsub("&", "&amp;")
205 value = value:gsub('"', "&quot;")
206 value = value:gsub("'", "&apos;")
207 value = value:gsub("<", "&lt;")
208 return value:gsub(">", "&gt;")
209 end
210
211 --- Strip HTML tags from given string.
212 -- @param value String containing the HTML text
213 -- @return String with HTML tags stripped of
214 function striptags(s)
215 return pcdata(s:gsub("</?[A-Za-z][A-Za-z0-9:_%-]*[^>]*>", " "):gsub("%s+", " "))
216 end
217
218 --- Splits given string on a defined separator sequence and return a table
219 -- containing the resulting substrings. The optional max parameter specifies
220 -- the number of bytes to process, regardless of the actual length of the given
221 -- string. The optional last parameter, regex, specifies whether the separator
222 -- sequence is interpreted as regular expression.
223 -- @param str String value containing the data to split up
224 -- @param pat String with separator pattern (optional, defaults to "\n")
225 -- @param max Maximum times to split (optional)
226 -- @param regex Boolean indicating whether to interpret the separator
227 -- pattern as regular expression (optional, default is false)
228 -- @return Table containing the resulting substrings
229 function split(str, pat, max, regex)
230 pat = pat or "\n"
231 max = max or #str
232
233 local t = {}
234 local c = 1
235
236 if #str == 0 then
237 return {""}
238 end
239
240 if #pat == 0 then
241 return nil
242 end
243
244 if max == 0 then
245 return str
246 end
247
248 repeat
249 local s, e = str:find(pat, c, not regex)
250 max = max - 1
251 if s and max < 0 then
252 t[#t+1] = str:sub(c)
253 else
254 t[#t+1] = str:sub(c, s and s - 1)
255 end
256 c = e and e + 1 or #str + 1
257 until not s or max < 0
258
259 return t
260 end
261
262 --- Remove leading and trailing whitespace from given string value.
263 -- @param str String value containing whitespace padded data
264 -- @return String value with leading and trailing space removed
265 function trim(str)
266 return (str:gsub("^%s*(.-)%s*$", "%1"))
267 end
268
269 --- Parse certain units from the given string and return the canonical integer
270 -- value or 0 if the unit is unknown. Upper- or lower case is irrelevant.
271 -- Recognized units are:
272 -- o "y" - one year (60*60*24*366)
273 -- o "m" - one month (60*60*24*31)
274 -- o "w" - one week (60*60*24*7)
275 -- o "d" - one day (60*60*24)
276 -- o "h" - one hour (60*60)
277 -- o "min" - one minute (60)
278 -- o "kb" - one kilobyte (1024)
279 -- o "mb" - one megabyte (1024*1024)
280 -- o "gb" - one gigabyte (1024*1024*1024)
281 -- o "kib" - one si kilobyte (1000)
282 -- o "mib" - one si megabyte (1000*1000)
283 -- o "gib" - one si gigabyte (1000*1000*1000)
284 -- @param ustr String containing a numerical value with trailing unit
285 -- @return Number containing the canonical value
286 function parse_units(ustr)
287
288 local val = 0
289
290 -- unit map
291 local map = {
292 -- date stuff
293 y = 60 * 60 * 24 * 366,
294 m = 60 * 60 * 24 * 31,
295 w = 60 * 60 * 24 * 7,
296 d = 60 * 60 * 24,
297 h = 60 * 60,
298 min = 60,
299
300 -- storage sizes
301 kb = 1024,
302 mb = 1024 * 1024,
303 gb = 1024 * 1024 * 1024,
304
305 -- storage sizes (si)
306 kib = 1000,
307 mib = 1000 * 1000,
308 gib = 1000 * 1000 * 1000
309 }
310
311 -- parse input string
312 for spec in ustr:lower():gmatch("[0-9%.]+[a-zA-Z]*") do
313
314 local num = spec:gsub("[^0-9%.]+$","")
315 local spn = spec:gsub("^[0-9%.]+", "")
316
317 if map[spn] or map[spn:sub(1,1)] then
318 val = val + num * ( map[spn] or map[spn:sub(1,1)] )
319 else
320 val = val + num
321 end
322 end
323
324
325 return val
326 end
327
328 --- Combines two or more numerically indexed tables into one.
329 -- @param tbl1 Table value to combine
330 -- @param tbl2 Table value to combine
331 -- @param ... More tables to combine
332 -- @return Table value containing all values of given tables
333 function combine(...)
334 local result = {}
335 for i, a in ipairs(arg) do
336 for j, v in ipairs(a) do
337 result[#result+1] = v
338 end
339 end
340 return result
341 end
342
343 --- Checks whether the given table contains the given value.
344 -- @param table Table value
345 -- @param value Value to search within the given table
346 -- @return Boolean indicating whether the given value occurs within table
347 function contains(table, value)
348 for k, v in pairs(table) do
349 if value == v then
350 return k
351 end
352 end
353 return false
354 end
355
356 --- Update values in given table with the values from the second given table.
357 -- Both table are - in fact - merged together.
358 -- @param t Table which should be updated
359 -- @param updates Table containing the values to update
360 -- @return Always nil
361 function update(t, updates)
362 for k, v in pairs(updates) do
363 t[k] = v
364 end
365 end
366
367 --- Retrieve all keys of given associative table.
368 -- @param t Table to extract keys from
369 -- @return Sorted table containing the keys
370 function keys(t)
371 local keys = { }
372 if t then
373 for k, _ in kspairs(t) do
374 keys[#keys+1] = k
375 end
376 end
377 return keys
378 end
379
380 --- Clones the given object and return it's copy.
381 -- @param object Table value to clone
382 -- @param deep Boolean indicating whether to do recursive cloning
383 -- @return Cloned table value
384 function clone(object, deep)
385 local copy = {}
386
387 for k, v in pairs(object) do
388 if deep and type(v) == "table" then
389 v = clone(v, deep)
390 end
391 copy[k] = v
392 end
393
394 return setmetatable(copy, getmetatable(object))
395 end
396
397
398 --- Create a dynamic table which automatically creates subtables.
399 -- @return Dynamic Table
400 function dtable()
401 return setmetatable({}, { __index =
402 function(tbl, key)
403 return rawget(tbl, key)
404 or rawget(rawset(tbl, key, dtable()), key)
405 end
406 })
407 end
408
409
410 -- Serialize the contents of a table value.
411 function _serialize_table(t, seen)
412 assert(not seen[t], "Recursion detected.")
413 seen[t] = true
414
415 local data = ""
416 local idata = ""
417 local ilen = 0
418
419 for k, v in pairs(t) do
420 if type(k) ~= "number" or k < 1 or math.floor(k) ~= k or ( k - #t ) > 3 then
421 k = serialize_data(k, seen)
422 v = serialize_data(v, seen)
423 data = data .. ( #data > 0 and ", " or "" ) ..
424 '[' .. k .. '] = ' .. v
425 elseif k > ilen then
426 ilen = k
427 end
428 end
429
430 for i = 1, ilen do
431 local v = serialize_data(t[i], seen)
432 idata = idata .. ( #idata > 0 and ", " or "" ) .. v
433 end
434
435 return idata .. ( #data > 0 and #idata > 0 and ", " or "" ) .. data
436 end
437
438 --- Recursively serialize given data to lua code, suitable for restoring
439 -- with loadstring().
440 -- @param val Value containing the data to serialize
441 -- @return String value containing the serialized code
442 -- @see restore_data
443 -- @see get_bytecode
444 function serialize_data(val, seen)
445 seen = seen or setmetatable({}, {__mode="k"})
446
447 if val == nil then
448 return "nil"
449 elseif type(val) == "number" then
450 return val
451 elseif type(val) == "string" then
452 return "%q" % val
453 elseif type(val) == "boolean" then
454 return val and "true" or "false"
455 elseif type(val) == "function" then
456 return "loadstring(%q)" % get_bytecode(val)
457 elseif type(val) == "table" then
458 return "{ " .. _serialize_table(val, seen) .. " }"
459 else
460 return '"[unhandled data type:' .. type(val) .. ']"'
461 end
462 end
463
464 --- Restore data previously serialized with serialize_data().
465 -- @param str String containing the data to restore
466 -- @return Value containing the restored data structure
467 -- @see serialize_data
468 -- @see get_bytecode
469 function restore_data(str)
470 return loadstring("return " .. str)()
471 end
472
473
474 --
475 -- Byte code manipulation routines
476 --
477
478 --- Return the current runtime bytecode of the given data. The byte code
479 -- will be stripped before it is returned.
480 -- @param val Value to return as bytecode
481 -- @return String value containing the bytecode of the given data
482 function get_bytecode(val)
483 local code
484
485 if type(val) == "function" then
486 code = string.dump(val)
487 else
488 code = string.dump( loadstring( "return " .. serialize_data(val) ) )
489 end
490
491 return code and strip_bytecode(code)
492 end
493
494 --- Strips unnescessary lua bytecode from given string. Information like line
495 -- numbers and debugging numbers will be discarded. Original version by
496 -- Peter Cawley (http://lua-users.org/lists/lua-l/2008-02/msg01158.html)
497 -- @param code String value containing the original lua byte code
498 -- @return String value containing the stripped lua byte code
499 function strip_bytecode(code)
500 local version, format, endian, int, size, ins, num, lnum = code:byte(5, 12)
501 local subint
502 if endian == 1 then
503 subint = function(code, i, l)
504 local val = 0
505 for n = l, 1, -1 do
506 val = val * 256 + code:byte(i + n - 1)
507 end
508 return val, i + l
509 end
510 else
511 subint = function(code, i, l)
512 local val = 0
513 for n = 1, l, 1 do
514 val = val * 256 + code:byte(i + n - 1)
515 end
516 return val, i + l
517 end
518 end
519
520 local strip_function
521 strip_function = function(code)
522 local count, offset = subint(code, 1, size)
523 local stripped, dirty = string.rep("\0", size), offset + count
524 offset = offset + count + int * 2 + 4
525 offset = offset + int + subint(code, offset, int) * ins
526 count, offset = subint(code, offset, int)
527 for n = 1, count do
528 local t
529 t, offset = subint(code, offset, 1)
530 if t == 1 then
531 offset = offset + 1
532 elseif t == 4 then
533 offset = offset + size + subint(code, offset, size)
534 elseif t == 3 then
535 offset = offset + num
536 elseif t == 254 or t == 9 then
537 offset = offset + lnum
538 end
539 end
540 count, offset = subint(code, offset, int)
541 stripped = stripped .. code:sub(dirty, offset - 1)
542 for n = 1, count do
543 local proto, off = strip_function(code:sub(offset, -1))
544 stripped, offset = stripped .. proto, offset + off - 1
545 end
546 offset = offset + subint(code, offset, int) * int + int
547 count, offset = subint(code, offset, int)
548 for n = 1, count do
549 offset = offset + subint(code, offset, size) + size + int * 2
550 end
551 count, offset = subint(code, offset, int)
552 for n = 1, count do
553 offset = offset + subint(code, offset, size) + size
554 end
555 stripped = stripped .. string.rep("\0", int * 3)
556 return stripped, offset
557 end
558
559 return code:sub(1,12) .. strip_function(code:sub(13,-1))
560 end
561
562
563 --
564 -- Sorting iterator functions
565 --
566
567 function _sortiter( t, f )
568 local keys = { }
569
570 for k, v in pairs(t) do
571 keys[#keys+1] = k
572 end
573
574 local _pos = 0
575 local _len = table.getn( keys )
576
577 table.sort( keys, f )
578
579 return function()
580 _pos = _pos + 1
581 if _pos <= _len then
582 return keys[_pos], t[keys[_pos]]
583 end
584 end
585 end
586
587 --- Return a key, value iterator which returns the values sorted according to
588 -- the provided callback function.
589 -- @param t The table to iterate
590 -- @param f A callback function to decide the order of elements
591 -- @return Function value containing the corresponding iterator
592 function spairs(t,f)
593 return _sortiter( t, f )
594 end
595
596 --- Return a key, value iterator for the given table.
597 -- The table pairs are sorted by key.
598 -- @param t The table to iterate
599 -- @return Function value containing the corresponding iterator
600 function kspairs(t)
601 return _sortiter( t )
602 end
603
604 --- Return a key, value iterator for the given table.
605 -- The table pairs are sorted by value.
606 -- @param t The table to iterate
607 -- @return Function value containing the corresponding iterator
608 function vspairs(t)
609 return _sortiter( t, function (a,b) return t[a] < t[b] end )
610 end
611
612
613 --
614 -- System utility functions
615 --
616
617 --- Test whether the current system is operating in big endian mode.
618 -- @return Boolean value indicating whether system is big endian
619 function bigendian()
620 return string.byte(string.dump(function() end), 7) == 0
621 end
622
623 --- Execute given commandline and gather stdout.
624 -- @param command String containing command to execute
625 -- @return String containing the command's stdout
626 function exec(command)
627 local pp = io.popen(command)
628 local data = pp:read("*a")
629 pp:close()
630
631 return data
632 end
633
634 --- Return a line-buffered iterator over the output of given command.
635 -- @param command String containing the command to execute
636 -- @return Iterator
637 function execi(command)
638 local pp = io.popen(command)
639
640 return pp and function()
641 local line = pp:read()
642
643 if not line then
644 pp:close()
645 end
646
647 return line
648 end
649 end
650
651 -- Deprecated
652 function execl(command)
653 local pp = io.popen(command)
654 local line = ""
655 local data = {}
656
657 while true do
658 line = pp:read()
659 if (line == nil) then break end
660 data[#data+1] = line
661 end
662 pp:close()
663
664 return data
665 end
666
667 --- Returns the absolute path to LuCI base directory.
668 -- @return String containing the directory path
669 function libpath()
670 return require "luci.fs".dirname(ldebug.__file__)
671 end
672
673
674 --
675 -- Coroutine safe xpcall and pcall versions modified for Luci
676 -- original version:
677 -- coxpcall 1.13 - Copyright 2005 - Kepler Project (www.keplerproject.org)
678 --
679 -- Copyright © 2005 Kepler Project.
680 -- Permission is hereby granted, free of charge, to any person obtaining a
681 -- copy of this software and associated documentation files (the "Software"),
682 -- to deal in the Software without restriction, including without limitation
683 -- the rights to use, copy, modify, merge, publish, distribute, sublicense,
684 -- and/or sell copies of the Software, and to permit persons to whom the
685 -- Software is furnished to do so, subject to the following conditions:
686 --
687 -- The above copyright notice and this permission notice shall be
688 -- included in all copies or substantial portions of the Software.
689 --
690 -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
691 -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
692 -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
693 -- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
694 -- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
695 -- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
696 -- OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
697
698 local performResume, handleReturnValue
699 local oldpcall, oldxpcall = pcall, xpcall
700 coxpt = {}
701 setmetatable(coxpt, {__mode = "kv"})
702
703 -- Identity function for copcall
704 local function copcall_id(trace, ...)
705 return ...
706 end
707
708 --- This is a coroutine-safe drop-in replacement for Lua's "xpcall"-function
709 -- @param f Lua function to be called protected
710 -- @param err Custom error handler
711 -- @param ... Parameters passed to the function
712 -- @return A boolean whether the function call succeeded and the return
713 -- values of either the function or the error handler
714 function coxpcall(f, err, ...)
715 local res, co = oldpcall(coroutine.create, f)
716 if not res then
717 local params = {...}
718 local newf = function() return f(unpack(params)) end
719 co = coroutine.create(newf)
720 end
721 local c = coroutine.running()
722 coxpt[co] = coxpt[c] or c or 0
723
724 return performResume(err, co, ...)
725 end
726
727 --- This is a coroutine-safe drop-in replacement for Lua's "pcall"-function
728 -- @param f Lua function to be called protected
729 -- @param ... Parameters passed to the function
730 -- @return A boolean whether the function call succeeded and the returns
731 -- values of the function or the error object
732 function copcall(f, ...)
733 return coxpcall(f, copcall_id, ...)
734 end
735
736 -- Handle return value of protected call
737 function handleReturnValue(err, co, status, ...)
738 if not status then
739 return false, err(debug.traceback(co, (...)), ...)
740 end
741 if coroutine.status(co) == 'suspended' then
742 return performResume(err, co, coroutine.yield(...))
743 else
744 return true, ...
745 end
746 end
747
748 -- Resume execution of protected function call
749 function performResume(err, co, ...)
750 return handleReturnValue(err, co, coroutine.resume(co, ...))
751 end