4
Copyright (c) 2010 Carnegie Mellon University
6
Permission is hereby granted, free of charge, to any person obtaining a copy
7
of this software and associated documentation files (the "Software"), to deal
8
in the Software without restriction, including without limitation the rights
9
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
copies of the Software, and to permit persons to whom the Software is
11
furnished to do so, subject to the following conditions:
13
The above copyright notice and this permission notice shall be included in
14
all copies or substantial portions of the Software.
16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
-- A collection of utility functions for Lua
29
-----------------------------------------------
32
table.sortedkeys(tab [,comp])
34
Returns a list of the keys in table, in sorted order.
37
function table.sortedkeys(tab, comp)
40
for k,v in pairs(tab) do
41
table.insert(sorted, k)
43
table.sort(sorted, comp)
47
sandboxScope(table, "sortedkeys", "USER")
49
-----------------------------------------------
54
Prints the contents of the table. Mostly for
58
function table.print(tab)
60
print("Table contents:")
61
for k,v in pairs(tab) do
70
sandboxScope(table, "print", "USER")
72
-----------------------------------------------
75
table.equal(tab1,tab2)
77
checks to see if the contents of two tables are equal.
78
So while {1,2,3} == {1,2,3} returns false
79
table.equal({1,2,3},{1,2,3}) will return true
81
This function does recursively check tables within tables
82
with the same function.
86
function table.equal(tab1,tab2,seen)
87
if type(tab1) ~= "table" then return false end
88
if type(tab2) ~= "table" then return false end
96
for k,v in pairs(tab1) do
97
if (type(v) == "table") then
98
if (seen[v]==nil) and seen[tab2[k]] == nil then
100
if not (table.equal(v,tab2[k],seen)) then
104
if (v ~= tab2[k]) then
109
if (v ~= tab2[k]) then
117
sandboxScope(table, "equal", "USER")
119
-----------------------------------------------
126
Finds an object in a table and returns the
127
location(key) where it is located.
129
Returns nil if object is not found.
132
function table.find(tab,elem)
133
for k,v in pairs(tab) do
141
sandboxScope(table, "find", "USER")
143
-----------------------------------------------
148
Prints the contents of the table, and any tables
149
it contains. Mostly for debugging purposes.
152
function table.deepprint(tab,seen)
162
for k,v in pairs(tab) do
167
if type(k)=='table' then
169
out = out .. table.deepprint(k,seen)
171
out = out .. "(loop)"
174
out = out .. tostring(k)
177
if type(v)=='table' then
179
out = out .. table.deepprint(v,seen)
181
out = out .. "(loop)"
184
out = out .. tostring(v)
196
sandboxScope(table, "deepprint", "USER")
202
Prints the contents of the table, and any tables
203
it contains. Mostly for debugging purposes.
206
function table.toString(tab,seen)
216
for k,v in pairs(tab) do
221
if type(k)=='table' then
223
out = out .. "WTF" --table.toString(k,seen)
225
--out = out .. "(loop)"
228
if type(k) == "string" then
229
out = out .. '["' .. tostring(k).. '"]'
231
out = out .. '['..tostring(k)..']'
235
if type(v)=='table' then
237
out = out .. table.toString(v,seen)
239
--out = out .. "(loop)"
242
if type(v) == "string" then
243
out = out .. '"' .. tostring(v).. '"'
245
out = out ..tostring(v)
255
sandboxScope(table, "toString", "USER")
262
-----------------------------------------------
265
result = table.copy(tab)
267
Makes a shallow copy of the table.
269
function table.copy(tab)
271
for k,v in pairs(tab) do
277
sandboxScope(table, "copy", "USER")
279
-----------------------------------------------
282
result = table.deepcopy(tab)
284
Makes a deep copy of the table. The function below also
285
copies the metatable to the new table if there is one,
286
so the behaviour of the copied table is the same as the original.
288
function table.deepcopy(tab)
289
local lookup_table = {}
290
local function _copy(tab)
291
if type(tab) ~= "table" then
293
elseif lookup_table[tab] then
294
return lookup_table[tab]
297
lookup_table[tab] = new_table
298
for index, value in pairs(tab) do
299
new_table[_copy(index)] = _copy(value)
301
return setmetatable(new_table, _copy( getmetatable(object)))
305
sandboxScope(table, "deepcopy", "KERNEL")
307
-----------------------------------------------
310
table.copyelts(srcTab, dstTab, keylist)
312
For every key in keylist, copies the value
313
from srcTab to dstTab.
315
function table.copyelts(srcTab, dstTab, keylist)
316
for i,value in ipairs(keylist) do
317
dstTab[value] = srcTab[value]
320
sandboxScope(table, "copyelts", "USER")
322
-----------------------------------------------
324
function Utils.sprintf(pattern, ...)
325
return string.format(pattern, ...)
327
sandboxScope(Utils, "sprintf", "KERNEL")
329
function Utils.printf(...)
330
print(Utils.sprintf(...))
332
sandboxScope(Utils, "printf", "KERNEL")
334
function Utils.splitToPathAndName(fullPath)
335
fullPath = fullPath:reverse()
336
local firstSlash = fullPath:find("/")
337
if firstSlash == nil then
338
return nil, fullPath:reverse()
340
local path = fullPath:sub(firstSlash):reverse()
341
local name = fullPath:sub(1,firstSlash-1):reverse()
344
sandboxScope(Utils, "splitToPathAndName", "KERNEL")
347
local printf = Utils.printf
348
local sprintf = Utils.sprintf
350
local function checktype(value_name, value, expected)
351
assert(type(value_name) == "string")
352
assert(type(expected) == "string")
354
local value_type = type(value)
356
if (type(value)) ~= expected then
357
error(("expected argument %s to be of type %s but got type %s"):format(value_name, expected, value_type))
363
local DEPTH_STEPSIZE = 2
365
-- increases print indenting depth
366
local increase_depth = function ()
367
depth = depth + DEPTH_STEPSIZE
370
-- decreases print indenting depth
371
local decrease_depth = function ()
372
depth = depth - DEPTH_STEPSIZE
376
local function indent(str)
383
-- getstring_simple(v)
384
-- Gets a simple one-word string representing a value
385
local getstring_simple
388
["string"] = function (str)
389
return ("\"%s\""):format(str)
391
["boolean"] = function (b)
392
return ("%s"):format(tostring(b))
394
["number"] = function (n)
395
return ("%d"):format(n)
397
["userdata"] = function (data)
398
return ("%s"):format(tostring(userdata))
400
["nil"] = function ()
401
return ("(%s)"):format(tostring(nil))
403
["table"] = function (t)
404
return ("%s"):format(tostring(t))
406
["function"] = function (f)
407
return ("%s"):format(tostring(f))
411
getstring_simple = function (v)
412
return funcs[type(v)](v)
417
-- Gets a detailed string, possibly with nested printing
418
local getstring_detailed
422
funcs["string"] = getstring_simple
423
funcs["boolean"] = getstring_simple
424
funcs["number"] = getstring_simple
425
funcs["userdata"] = getstring_simple
426
funcs["nil"] = getstring_simple
427
funcs["function"] = getstring_simple
431
-- don't recur indefinitely
433
return ("(%s - nested)"):format(tostring(t))
435
-- mark that we've been here
438
local s = ("(%s ---) {\n"):format(tostring(t))
441
-- print our contents
442
for key, val in pairs(t) do
443
local line = indent("[" .. getstring_simple(key) .. "]")
444
line = ("%s = %s,\n"):format(line, getstring_detailed(val))
449
s = ("%s%s"):format(s, indent(("} (--- %s)"):format(tostring(t))))
455
getstring_detailed = function(v)
456
return funcs[type(v)](v)
460
function Utils.dodump(label, value)
461
checktype("label", label, "string")
465
printf("%s = %s", getstring_simple(label), getstring_detailed(value))
469
-- Performs a dump on _G[global_key]. global_key should be
471
function Utils.dump(global_key)
472
Utils.dodump(global_key, _G[global_key])
477
sandboxScope(Utils, "dodump", "KERNEL")
478
sandboxScope(Utils, "dump", "KERNEL")
480
alreadyTookFocus = false
484
Captures keyboard focus to Wild Pockets. This function may only be called from onSceneStart
485
to prevent abuse, and may only be called once.
487
function Utils.takeFocus()
488
-- compare to false specifically; can also return nil
489
if Kernel.isOnSceneStartCompleted() == false then
490
if not alreadyTookFocus then
491
Utils.kernelTakeFocus()
492
alreadyTookFocus = true
494
warnOnce("Utils.takeFocus() may only be called once.")
497
warnOnce("Utils.takeFocus() may only be called from onSceneStart.")
500
sandboxScope(Utils, "takeFocus", "USER")
503
browser, version = Utils.guessBrowser()
505
Tries to figure out what web browser the user is using.
507
function Utils.guessBrowser()
509
local firefoxVersion, chromeVersion, iexploreVersion, operaVersion, safariVersion
510
local ua = Kernel.getPluginProperty("useragent")
511
a, b, firefoxVersion = string.find(ua, "Firefox/([^%s]*)")
512
a, b, chromeVersion = string.find(ua, "Chrome/([^%s]*)")
513
a, b, safariVersion = string.find(ua, "Safari/([^%s]*)")
514
a, b, operaVersion = string.find(ua, "Opera/([^%s]*)")
515
a, b, iexploreVersion = string.find(ua, "MSIE ([^;]*);")
517
if firefoxVersion ~= nil then
518
return "Firefox", firefoxVersion
520
if chromeVersion ~= nil then
521
return "Chrome", chromeVersion
523
if safariVersion ~= nil then -- after chrome check since chrome also claims safari
524
return "Safari", safariVersion
526
if operaVersion ~= nil then
527
return "Opera", operaVersion
529
if iexploreVersion ~= nil then
530
return "Internet Explorer", iexploreVersion
532
return "Unknown", nil
534
sandboxScope(Utils, "guessBrowser", "KERNEL")