util/format.lua
author Kim Alvefur <zash@zash.se>
Fri, 12 Oct 2018 01:29:34 +0200
changeset 9697 6ed0d6224d64
parent 9691 8c92ef4270c9
child 10038 4fca92d60040
permissions -rw-r--r--
util.format: Serialize values for the %q format Improves eg debug logs
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
8228
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
     1
--
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
     2
-- A string.format wrapper that gracefully handles invalid arguments
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
     3
--
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
     4
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
     5
local tostring = tostring;
8420
e88db5668cfb util.format: Import unpack from table lib in Lua 5.2+
Kim Alvefur <zash@zash.se>
parents: 8386
diff changeset
     6
local unpack = table.unpack or unpack; -- luacheck: ignore 113/unpack
9691
8c92ef4270c9 util.format: Use pack from util.table
Kim Alvefur <zash@zash.se>
parents: 9660
diff changeset
     7
local pack = require "util.table".pack; -- TODO table.pack in 5.2+
8228
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
     8
local type = type;
9697
6ed0d6224d64 util.format: Serialize values for the %q format
Kim Alvefur <zash@zash.se>
parents: 9691
diff changeset
     9
local dump = require "util.serialization".new("debug");
8228
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    10
8385
e5d00bf4a4d5 util: Various minor changes to please [luacheck]
Kim Alvefur <zash@zash.se>
parents: 8228
diff changeset
    11
local function format(formatstring, ...)
9691
8c92ef4270c9 util.format: Use pack from util.table
Kim Alvefur <zash@zash.se>
parents: 9660
diff changeset
    12
	local args = pack(...);
8c92ef4270c9 util.format: Use pack from util.table
Kim Alvefur <zash@zash.se>
parents: 9660
diff changeset
    13
	local args_length = args.n;
8228
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    14
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    15
	-- format specifier spec:
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    16
	-- 1. Start: '%%'
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    17
	-- 2. Flags: '[%-%+ #0]'
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    18
	-- 3. Width: '%d?%d?'
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    19
	-- 4. Precision: '%.?%d?%d?'
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    20
	-- 5. Option: '[cdiouxXaAeEfgGqs%%]'
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    21
	--
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    22
	-- The options c, d, E, e, f, g, G, i, o, u, X, and x all expect a number as argument, whereas q and s expect a string.
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    23
	-- This function does not accept string values containing embedded zeros, except as arguments to the q option.
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    24
	-- a and A are only in Lua 5.2+
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    25
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    26
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    27
	-- process each format specifier
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    28
	local i = 0;
8385
e5d00bf4a4d5 util: Various minor changes to please [luacheck]
Kim Alvefur <zash@zash.se>
parents: 8228
diff changeset
    29
	formatstring = formatstring:gsub("%%[^cdiouxXaAeEfgGqs%%]*[cdiouxXaAeEfgGqs%%]", function(spec)
8228
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    30
		if spec ~= "%%" then
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    31
			i = i + 1;
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    32
			local arg = args[i];
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    33
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    34
			local option = spec:sub(-1);
9660
3da6cc927ee6 util.format: Tweak how nil values are handled
Kim Alvefur <zash@zash.se>
parents: 8420
diff changeset
    35
			if arg == nil then
3da6cc927ee6 util.format: Tweak how nil values are handled
Kim Alvefur <zash@zash.se>
parents: 8420
diff changeset
    36
				args[i] = "nil";
3da6cc927ee6 util.format: Tweak how nil values are handled
Kim Alvefur <zash@zash.se>
parents: 8420
diff changeset
    37
				spec = "<%s>";
9697
6ed0d6224d64 util.format: Serialize values for the %q format
Kim Alvefur <zash@zash.se>
parents: 9691
diff changeset
    38
			elseif option == "q" then
6ed0d6224d64 util.format: Serialize values for the %q format
Kim Alvefur <zash@zash.se>
parents: 9691
diff changeset
    39
				args[i] = dump(arg);
6ed0d6224d64 util.format: Serialize values for the %q format
Kim Alvefur <zash@zash.se>
parents: 9691
diff changeset
    40
				spec = "%s";
6ed0d6224d64 util.format: Serialize values for the %q format
Kim Alvefur <zash@zash.se>
parents: 9691
diff changeset
    41
			elseif option == "s" then
8228
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    42
				args[i] = tostring(arg);
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    43
			elseif type(arg) ~= "number" then -- arg isn't number as expected?
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    44
				args[i] = tostring(arg);
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    45
				spec = "[%s]";
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    46
			end
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    47
		end
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    48
		return spec;
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    49
	end);
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    50
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    51
	-- process extra args
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    52
	while i < args_length do
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    53
		i = i + 1;
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    54
		local arg = args[i];
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    55
		if arg == nil then
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    56
			args[i] = "<nil>";
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    57
		else
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    58
			args[i] = tostring(arg);
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    59
		end
8385
e5d00bf4a4d5 util: Various minor changes to please [luacheck]
Kim Alvefur <zash@zash.se>
parents: 8228
diff changeset
    60
		formatstring = formatstring .. " [%s]"
8228
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    61
	end
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    62
8385
e5d00bf4a4d5 util: Various minor changes to please [luacheck]
Kim Alvefur <zash@zash.se>
parents: 8228
diff changeset
    63
	return formatstring:format(unpack(args));
8228
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    64
end
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    65
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    66
return {
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    67
	format = format;
70cb72f46a3b util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    68
};