Software /
code /
prosody
Comparison
util/format.lua @ 12033:161f8268c4b3
util.format: Also handle the %p format added in Lua 5.4
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sat, 11 Dec 2021 13:39:58 +0100 |
parent | 12032:3db09eb4c43b |
child | 12035:dc7ab05005e8 |
comparison
equal
deleted
inserted
replaced
12032:3db09eb4c43b | 12033:161f8268c4b3 |
---|---|
27 ["\021"] = "\226\144\149", ["\022"] = "\226\144\150", ["\023"] = "\226\144\151", | 27 ["\021"] = "\226\144\149", ["\022"] = "\226\144\150", ["\023"] = "\226\144\151", |
28 ["\024"] = "\226\144\152", ["\025"] = "\226\144\153", ["\026"] = "\226\144\154", | 28 ["\024"] = "\226\144\152", ["\025"] = "\226\144\153", ["\026"] = "\226\144\154", |
29 ["\027"] = "\226\144\155", ["\028"] = "\226\144\156", ["\029"] = "\226\144\157", | 29 ["\027"] = "\226\144\155", ["\028"] = "\226\144\156", ["\029"] = "\226\144\157", |
30 ["\030"] = "\226\144\158", ["\031"] = "\226\144\159", ["\127"] = "\226\144\161", | 30 ["\030"] = "\226\144\158", ["\031"] = "\226\144\159", ["\127"] = "\226\144\161", |
31 }; | 31 }; |
32 local supports_p = pcall(string.format, "%p", ""); | |
32 | 33 |
33 local function format(formatstring, ...) | 34 local function format(formatstring, ...) |
34 local args = pack(...); | 35 local args = pack(...); |
35 local args_length = args.n; | 36 local args_length = args.n; |
36 | 37 |
42 -- 5. Option: '[cdiouxXaAeEfgGqs%%]' | 43 -- 5. Option: '[cdiouxXaAeEfgGqs%%]' |
43 -- | 44 -- |
44 -- 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. | 45 -- 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. |
45 -- This function does not accept string values containing embedded zeros, except as arguments to the q option. | 46 -- This function does not accept string values containing embedded zeros, except as arguments to the q option. |
46 -- a and A are only in Lua 5.2+ | 47 -- a and A are only in Lua 5.2+ |
48 -- Lua 5.4 adds a p format that produces a pointer | |
47 | 49 |
48 | 50 |
49 -- process each format specifier | 51 -- process each format specifier |
50 local i = 0; | 52 local i = 0; |
51 formatstring = formatstring:gsub("%%[^cdiouxXaAeEfgGqs%%]*[cdiouxXaAeEfgGqs%%]", function(spec) | 53 formatstring = formatstring:gsub("%%[^cdiouxXaAeEfgGpqs%%]*[cdiouxXaAeEfgGpqs%%]", function(spec) |
52 if spec == "%%" then return end | 54 if spec == "%%" then return end |
53 i = i + 1; | 55 i = i + 1; |
54 local arg = args[i]; | 56 local arg = args[i]; |
55 | 57 |
56 if arg == nil then | 58 if arg == nil then |
64 if option == "s" and t == "string" and not arg:find("[%z\1-\31\128-\255]") then | 66 if option == "s" and t == "string" and not arg:find("[%z\1-\31\128-\255]") then |
65 -- No UTF-8 or control characters, assumed to be the common case. | 67 -- No UTF-8 or control characters, assumed to be the common case. |
66 return | 68 return |
67 end | 69 end |
68 | 70 |
69 if option ~= "s" and option ~= "q" then | 71 if option ~= "s" and option ~= "q" and option ~= "p" then |
70 -- all other options expect numbers | 72 -- all other options expect numbers |
71 if t ~= "number" then | 73 if t ~= "number" then |
72 -- arg isn't number as expected? | 74 -- arg isn't number as expected? |
73 arg = tostring(arg); | 75 arg = tostring(arg); |
74 option = "s"; | 76 option = "s"; |
80 else | 82 else |
81 return -- acceptable number | 83 return -- acceptable number |
82 end | 84 end |
83 end | 85 end |
84 | 86 |
85 if t == "string" then | 87 |
88 if option == "p" and not supports_p then | |
89 arg = tostring(arg); | |
90 option = "s"; | |
91 spec = "[%s]"; | |
92 t = "string"; | |
93 end | |
94 | |
95 if t == "string" and option ~= "p" then | |
86 if not valid_utf8(arg) then | 96 if not valid_utf8(arg) then |
87 option = "q"; | 97 option = "q"; |
88 else | 98 else |
89 args[i] = arg:gsub("[%z\1-\8\11-\31\127]", control_symbols):gsub("\n\t?", "\n\t"); | 99 args[i] = arg:gsub("[%z\1-\8\11-\31\127]", control_symbols):gsub("\n\t?", "\n\t"); |
90 return spec; | 100 return spec; |
92 end | 102 end |
93 | 103 |
94 if option == "q" then | 104 if option == "q" then |
95 args[i] = dump(arg); | 105 args[i] = dump(arg); |
96 return "%s"; | 106 return "%s"; |
107 end | |
108 | |
109 if option == "p" and (t == "boolean" or t == "number") then | |
110 args[i] = tostring(arg); | |
111 return "[%s]"; | |
97 end | 112 end |
98 end); | 113 end); |
99 | 114 |
100 -- process extra args | 115 -- process extra args |
101 while i < args_length do | 116 while i < args_length do |