Mercurial > prosody-hg
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 |
| parents | |
| children | 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 }; |
