--****************************************************************************** --* * --* File: Lua_02_Lib.lua Revision: 1.0 * --* * --* Purpose: provides functions from "Lua_02" for other scripts * --* * --* Creation: 06.03.2002 Last Modification: 06.03.2002 * --* * --* Platform: IBM-compatible PC running Windows 98SE * --* * --* Environment: Lua 4.0, TkLua 4.0 * --* * --* Author: Andreas Rozek Phone: ++49 (711) 6770682 * --* Kirschblütenweg 15 Fax: - * --* D-70569 Stuttgart EMail: Andreas.Rozek@T-Online.De * --* Germany * --* * --* URL: http://www.Andreas-Rozek.de/ * --* * --* Copyright: the software is published under the "GNU Lesser General Pub- * --* lic License" (see "http://www.fsf.org/copyleft/lesser.html" * --* for additional information) * --* * --* Comments: (none) * --* * --****************************************************************************** true,false = 1,nil; -- because the author is used to explicit boolean types --**** preserve intrinsic functions **** local _print = print; local _tostring = tostring; local _write = write; --****************************************************************************** --* * --* encodedString yields a copy of 'Original' with special characters encoded * --* * --****************************************************************************** local _ReplacementTable = { ["\a"]="\\a", ["\b"]="\\b", ["\f"]="\\f", ["\n"]="\\n", ["\r"]="\\r", ["\t"]="\\t", ["\v"]="\\v", ["\\"]="\\\\", ["\""]="\\\"", ["\'"]="\\\'", ["\0"]="\\0" }; local _ReplacementFunction = function (oldSequence) local newSequence = rawget(%_ReplacementTable, oldSequence); if (newSequence ~= nil) then return newSequence; -- yields predefined escape sequence else return "\\"..strbyte(oldSequence); -- yields numerically encoded character end; end; function encodedString (Original) assert( type(Original) == "string", "given 'Original' is not a string (but a \""..type(Original).."\")" ); return gsub(Original, "(['\"%c%z])", %_ReplacementFunction); end; --****************************************************************************** --* * --* print extends the intrinsic 'print' function to handle more data types * --* * --****************************************************************************** function print (...) call(write,arg); -- uses 'write' to handle individual data types write("\n"); end; --****************************************************************************** --* * --* tostring extends the intrinsic function to handle more data types * --* * --****************************************************************************** toString_DefaultNestLevel = 4; -- limit "tostring" nesting to 4 levels function tostring (Argument,NestLevel) NestLevel = NestLevel or toString_DefaultNestLevel; local Result = ""; ArgType = type(Argument); if (ArgType == "nil") then Result = Result.."(nil)"; elseif (ArgType == "number") then Result = Result..%_tostring(Argument); elseif (ArgType == "string") then Result = Result..Argument; elseif (ArgType == "function") then Result = Result.."(function)"; elseif (ArgType == "userdata") then Result = Result.."(userdata)"; else -- ArgType == "table" local specificMethod = Argument.tostring or Argument.toString; if (type(specificMethod) == "function") then Result = Result..specificMethod(Argument,NestLevel-1); else local isList = true; -- check if the given argument is a "list" for Key,Value in Argument do if ((type(Key) ~= "number") and (Key ~= "n")) then isList = false; break; end; end; Result = Result.."{"; if (isList) then local Count = getn(Argument); for j = 1,Count do local Value = Argument[j]; if (type(Value) == "string") then Result = Result.."\""..encodedString(Value).."\""; else Result = Result..tostring(Value,NestLevel-1); end; if (j < Count) then Result = Result..","; end; end; else local firstItem = true; -- used to handle comma separators local Key,Value = next(Argument,nil); while (Key ~= nil) do if (firstItem) then firstItem = false; else Result = Result..","; end; if (validSymbol(Key)) then Result = Result..Key.."="; elseif (type(Key) == "string") then Result = Result.."[\""..encodedString(Key).."\"]="; else -- since ANY kind of object may be used as a key... Result = Result.."[\""..type(Key).."\"]="; -- experimental end; if (type(Value) == "string") then Result = Result.."\""..encodedString(Value).."\""; else Result = Result..tostring(Value,NestLevel-1); end; Key,Value = next(Argument,Key); end; end; Result = Result.."}"; end; end; return Result; end; --****************************************************************************** --* * --* validSymbol checks if 'Candidate' is a valid Lua symbol * --* * --****************************************************************************** function validSymbol (Candidate) if (type(Candidate) ~= "string") then return false; end; return (strfind(Candidate, "^[%a_][%w_]*$") ~= nil); end; --****************************************************************************** --* * --* write extends the intrinsic 'write' function to handle more data types * --* * --****************************************************************************** function write (...) for i = 1,getn(arg) do ArgType = type(arg[i]); if (ArgType == "nil") then %_write("(nil)"); elseif (ArgType == "number") then %_write(%_tostring(arg[i])); elseif (ArgType == "string") then %_write(arg[i]); elseif (ArgType == "function") then %_write("(function)"); elseif (ArgType == "userdata") then %_write("(userdata)"); else -- ArgType == "table" %_write(tostring(arg[i])); end; end; end; --****************************************************************************** --* * --* writeln provides an alternative to 'print' * --* * --****************************************************************************** function writeln (...) call(write,arg); -- uses 'write' to handle individual data types write("\n"); end;