Comparison

util/format.lua @ 8225:70cb72f46a3b

util.format: A string.format wrapper that gracefully handles invalid arguments
author Waqas Hussain <waqas20@gmail.com>
date Sun, 10 Sep 2017 12:42:05 -0400
child 8382:e5d00bf4a4d5
comparison
equal deleted inserted replaced
8207:8ea0484871e8 8225:70cb72f46a3b
1 --
2 -- A string.format wrapper that gracefully handles invalid arguments
3 --
4
5 local tostring = tostring;
6 local select = select;
7 local assert = assert;
8 local unpack = unpack;
9 local type = type;
10
11 local function format(format, ...)
12 local args, args_length = { ... }, select('#', ...);
13
14 -- format specifier spec:
15 -- 1. Start: '%%'
16 -- 2. Flags: '[%-%+ #0]'
17 -- 3. Width: '%d?%d?'
18 -- 4. Precision: '%.?%d?%d?'
19 -- 5. Option: '[cdiouxXaAeEfgGqs%%]'
20 --
21 -- 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.
22 -- This function does not accept string values containing embedded zeros, except as arguments to the q option.
23 -- a and A are only in Lua 5.2+
24
25
26 -- process each format specifier
27 local i = 0;
28 format = format:gsub("%%[^cdiouxXaAeEfgGqs%%]*[cdiouxXaAeEfgGqs%%]", function(spec)
29 if spec ~= "%%" then
30 i = i + 1;
31 local arg = args[i];
32 if arg == nil then -- special handling for nil
33 arg = "<nil>"
34 args[i] = "<nil>";
35 end
36
37 local option = spec:sub(-1);
38 if option == "q" or option == "s" then -- arg should be string
39 args[i] = tostring(arg);
40 elseif type(arg) ~= "number" then -- arg isn't number as expected?
41 args[i] = tostring(arg);
42 spec = "[%s]";
43 end
44 end
45 return spec;
46 end);
47
48 -- process extra args
49 while i < args_length do
50 i = i + 1;
51 local arg = args[i];
52 if arg == nil then
53 args[i] = "<nil>";
54 else
55 args[i] = tostring(arg);
56 end
57 format = format .. " [%s]"
58 end
59
60 return format:format(unpack(args));
61 end
62
63 local function test()
64 assert(format("%s", "hello") == "hello");
65 assert(format("%s") == "<nil>");
66 assert(format("%s", true) == "true");
67 assert(format("%d", true) == "[true]");
68 assert(format("%%", true) == "% [true]");
69 end
70
71 return {
72 format = format;
73 test = test;
74 };