local tableconcat = table.concat
local stringformat = string.format
local StringBuilder = {}
function StringBuilder:new(sep)
	local object = {}
	setmetatable(object, self)
	self.__index = self
	object.sep = sep
	object.buffer = {}
	return object
end
function StringBuilder:Append(str)
	self.buffer[#self.buffer + 1] = str
end
function StringBuilder:AppendFormat(format, ...)
	self:Append(stringformat(format, ...))
end
function StringBuilder:AppendLine(str)
	self:Append(str)
	self:Append("\r\n")
end
function StringBuilder:ToString()
	return tableconcat(self.buffer, self.sep)
end
function StringBuilder:Clear()
	local count = #self.buffer
	for i = 1, count do
		self.buffer[i] = nil
	end
end
local function __printTable(tb, sb, name, aPreText, bLast)
	if tb == nil then
		return
	end
	if bLast == nil then
		bLast = false
	end
	name = name or ""
	local preText = aPreText or ""
	local subPreText = ""
	if aPreText == nil then
		sb:AppendLine("[ROOT]")
	else
		if bLast then
			subPreText = preText .. "    "
		else
			subPreText = preText .. "│  "
		end
		if type(tb) == "table" then
			if bLast then
				sb:AppendLine(string.format("%s└─[%s]", preText, name))
			else
				sb:AppendLine(string.format("%s├─[%s]", preText, name))
			end
		elseif bLast then
			sb:AppendLine(string.format("%s└─%s= %s", preText, name, tostring(tb)))
		else
			sb:AppendLine(string.format("%s├─%s= %s", preText, name, tostring(tb)))
		end
	end
	if type(tb) == "table" then
		local counter = 0
		local count = 0
		for _, _ in pairs(tb) do
			count = count + 1
		end
		for key, obj in pairs(tb) do
			counter = counter + 1
			__printTable(obj, sb, key, subPreText, counter == count)
		end
	end
	if bLast then
		sb:AppendLine(preText)
	end
end
function PrintTable(tb, filename)
	local sb = StringBuilder:new()
	__printTable(tb, sb)
	local str = sb:ToString()
	if filename then
		local f = io.open(filename, "w")
		if f ~= nil then
			f:write(str)
			f:close()
		end
	else
		print(str)
	end
end
