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