Created
March 2, 2014 06:46
-
-
Save balaam/9302863 to your computer and use it in GitHub Desktop.
Everyone writes a PrintTable function in Lua. This one is mind. It's written with the idea of encoding using the same code - like printing to JSON for instance.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -- | |
| -- Call PrintTable on a table to print a nicely formated lua table to the console. | |
| -- The print table can also be overloaded with a different type of printer to output the table in a new representation | |
| -- like a blob. | |
| -- | |
| -- In the final version both these should be changed to local | |
| TabSize = 4 | |
| DataType = | |
| { | |
| Key = "Key", | |
| Value = "Value", | |
| ArrayEntry = "ArrayEntry", | |
| } | |
| DefaultPrinter = {} | |
| -- | |
| -- value - the current type being written out | |
| -- stack - the stack of tables, representing the position in the data structure that the | |
| -- printer is printing. | |
| -- output - the table of strings that represents the output (better the basic string concatination) | |
| -- datatype - the type of value being in, a key, value or array entry. | |
| -- [key] - an object that points to a value in a table | |
| -- [value] - an object that is indexed by a key object | |
| -- [array entry] - if keys in a table are consecutive numbers starting from 1 lua | |
| -- optimizes the table and the keys are not explicitly stored. | |
| -- | |
| function DefaultPrinter:_printType(value, stack, output, dataType) | |
| if dataType ~= DataType.Value then | |
| table.insert(output, string.rep(" ", #stack * TabSize)) | |
| end | |
| if dataType == DataType.Key then | |
| table.insert(output, string.format("[%s]", tostring(value))) | |
| else | |
| table.insert(output, tostring(value)) | |
| table.insert(output, ",\n") | |
| end | |
| end | |
| DefaultPrinter.number = DefaultPrinter._printType | |
| DefaultPrinter['function'] = DefaultPrinter._printType | |
| DefaultPrinter.boolean = DefaultPrinter._printType | |
| DefaultPrinter.thread = DefaultPrinter._printType | |
| function DefaultPrinter:string(str, ...) | |
| self:_printType(string.format('%q', str), ...) | |
| end | |
| function DefaultPrinter:userdata(value, stack, output, dataType) | |
| -- An extra look up will be needed here using Type instead of type | |
| self:_printType(value, stack, output, dataType) | |
| end | |
| function DefaultPrinter:OpenTable(t, stack, output, dataType) | |
| if not next(t) then | |
| -- Empty table | |
| if dataType ~= DataType.Value then | |
| table.insert(output, string.rep(" ", #stack * TabSize)) | |
| end | |
| if dataType == DataType.Key then | |
| table.insert(output, "[{") | |
| else | |
| table.insert(output, "{") | |
| end | |
| return | |
| end | |
| if dataType == DataType.Value then | |
| table.insert(output, "\n") | |
| end | |
| table.insert(output, string.rep(" ", #stack * TabSize)) | |
| if dataType == DataType.Key then | |
| table.insert(output, "[") | |
| end | |
| table.insert(output, "{\n") | |
| end | |
| function DefaultPrinter:CloseTable(t, stack, output, dataType) | |
| if next(t) then | |
| table.insert(output, string.rep(" ", #stack * TabSize)) | |
| end | |
| table.insert(output, "}") | |
| if dataType == DataType.Key then | |
| table.insert(output, "]") | |
| else | |
| table.insert(output, ",\n") | |
| end | |
| end | |
| function DefaultPrinter:KeyPairAssign(output) | |
| table.insert(output, " = ") | |
| end | |
| function DefaultPrinter:HitLoop(t, stack, output, dataType) | |
| table.insert(output, "[LOOP]\n") | |
| end | |
| function IterTable(t, stack, output, dataType, printer) | |
| local _stack = stack or {} | |
| local _data = output or {} | |
| local _dataType = dataType or DataType.Value | |
| local _printer = printer or DefaultPrinter | |
| _printer.table = function(self, ...) IterTable(...) end | |
| -- Do a check for recursion | |
| for _, v in ipairs(_stack) do | |
| if v == t then | |
| _printer:HitLoop(v, _stack, _data, DataType.ArrayEntry, _printer) | |
| return | |
| end | |
| end | |
| _printer:OpenTable(t, _stack, _data, _dataType) | |
| -- Push table to visited-stack | |
| table.insert(_stack, t) | |
| local _ipairsKey = {} | |
| for k, v in ipairs(t) do | |
| _ipairsKey[k] = v | |
| _printer[type(v)](_printer, v, _stack, _data, DataType.ArrayEntry, _printer) | |
| end | |
| for k, v in pairs(t) do | |
| if _ipairsKey[k] ~= v then | |
| _printer[type(k)](_printer, k, _stack, _data, DataType.Key, _printer) | |
| _printer:KeyPairAssign(_data) | |
| _printer[type(v)](_printer, v, _stack, _data, DataType.Value, _printer) | |
| end | |
| end | |
| table.remove(_stack) | |
| _printer:CloseTable(t, _stack, _data, _dataType) | |
| if not next(_stack) then | |
| return table.concat(_data) | |
| end | |
| end | |
| function PrintTable(t) | |
| if type(t) ~= "table" then | |
| print(tostring(t)) | |
| end | |
| print(IterTable(t, nil, nil, DefaultPrinter)) | |
| end | |
| --PrintTable({{},{{}},{{},{},{}}}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment