Software /
code /
prosody
Annotate
util/format.lua @ 11875:210a785dfa8a
mod_mam: Use util.dataforms timestamp validation
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Tue, 26 Oct 2021 13:31:40 +0200 |
parent | 11648:96d3cbeb9275 |
child | 12031:87bc26f23d9b |
rev | line source |
---|---|
8225
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; |
8417
e88db5668cfb
util.format: Import unpack from table lib in Lua 5.2+
Kim Alvefur <zash@zash.se>
parents:
8383
diff
changeset
|
6 local unpack = table.unpack or unpack; -- luacheck: ignore 113/unpack |
9687
8c92ef4270c9
util.format: Use pack from util.table
Kim Alvefur <zash@zash.se>
parents:
9656
diff
changeset
|
7 local pack = require "util.table".pack; -- TODO table.pack in 5.2+ |
8225
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
8 local type = type; |
9693
6ed0d6224d64
util.format: Serialize values for the %q format
Kim Alvefur <zash@zash.se>
parents:
9687
diff
changeset
|
9 local dump = require "util.serialization".new("debug"); |
10035
386f085820e6
util.format: Handle integer formats the same way on Lua versions without integer support
Kim Alvefur <zash@zash.se>
parents:
10034
diff
changeset
|
10 local num_type = math.type or function (n) |
386f085820e6
util.format: Handle integer formats the same way on Lua versions without integer support
Kim Alvefur <zash@zash.se>
parents:
10034
diff
changeset
|
11 return n % 1 == 0 and n <= 9007199254740992 and n >= -9007199254740992 and "integer" or "float"; |
386f085820e6
util.format: Handle integer formats the same way on Lua versions without integer support
Kim Alvefur <zash@zash.se>
parents:
10034
diff
changeset
|
12 end |
10034
4fca92d60040
util.format: Handle formats expecting an integer in Lua 5.3+ (fixes #1371)
Kim Alvefur <zash@zash.se>
parents:
9693
diff
changeset
|
13 |
10035
386f085820e6
util.format: Handle integer formats the same way on Lua versions without integer support
Kim Alvefur <zash@zash.se>
parents:
10034
diff
changeset
|
14 -- In Lua 5.3+ these formats throw an error if given a float |
386f085820e6
util.format: Handle integer formats the same way on Lua versions without integer support
Kim Alvefur <zash@zash.se>
parents:
10034
diff
changeset
|
15 local expects_integer = { c = true, d = true, i = true, o = true, u = true, X = true, x = true, }; |
11638
5f4a657136bc
util.format: Escape ASCII control characters in output
Kim Alvefur <zash@zash.se>
parents:
10035
diff
changeset
|
16 -- Printable Unicode replacements for control characters |
5f4a657136bc
util.format: Escape ASCII control characters in output
Kim Alvefur <zash@zash.se>
parents:
10035
diff
changeset
|
17 local control_symbols = { |
5f4a657136bc
util.format: Escape ASCII control characters in output
Kim Alvefur <zash@zash.se>
parents:
10035
diff
changeset
|
18 -- 0x00 .. 0x1F --> U+2400 .. U+241F, 0x7F --> U+2421 |
5f4a657136bc
util.format: Escape ASCII control characters in output
Kim Alvefur <zash@zash.se>
parents:
10035
diff
changeset
|
19 ["\000"] = "\226\144\128", ["\001"] = "\226\144\129", ["\002"] = "\226\144\130", |
5f4a657136bc
util.format: Escape ASCII control characters in output
Kim Alvefur <zash@zash.se>
parents:
10035
diff
changeset
|
20 ["\003"] = "\226\144\131", ["\004"] = "\226\144\132", ["\005"] = "\226\144\133", |
5f4a657136bc
util.format: Escape ASCII control characters in output
Kim Alvefur <zash@zash.se>
parents:
10035
diff
changeset
|
21 ["\006"] = "\226\144\134", ["\007"] = "\226\144\135", ["\008"] = "\226\144\136", |
5f4a657136bc
util.format: Escape ASCII control characters in output
Kim Alvefur <zash@zash.se>
parents:
10035
diff
changeset
|
22 ["\009"] = "\226\144\137", ["\010"] = "\226\144\138", ["\011"] = "\226\144\139", |
5f4a657136bc
util.format: Escape ASCII control characters in output
Kim Alvefur <zash@zash.se>
parents:
10035
diff
changeset
|
23 ["\012"] = "\226\144\140", ["\013"] = "\226\144\141", ["\014"] = "\226\144\142", |
5f4a657136bc
util.format: Escape ASCII control characters in output
Kim Alvefur <zash@zash.se>
parents:
10035
diff
changeset
|
24 ["\015"] = "\226\144\143", ["\016"] = "\226\144\144", ["\017"] = "\226\144\145", |
5f4a657136bc
util.format: Escape ASCII control characters in output
Kim Alvefur <zash@zash.se>
parents:
10035
diff
changeset
|
25 ["\018"] = "\226\144\146", ["\019"] = "\226\144\147", ["\020"] = "\226\144\148", |
5f4a657136bc
util.format: Escape ASCII control characters in output
Kim Alvefur <zash@zash.se>
parents:
10035
diff
changeset
|
26 ["\021"] = "\226\144\149", ["\022"] = "\226\144\150", ["\023"] = "\226\144\151", |
5f4a657136bc
util.format: Escape ASCII control characters in output
Kim Alvefur <zash@zash.se>
parents:
10035
diff
changeset
|
27 ["\024"] = "\226\144\152", ["\025"] = "\226\144\153", ["\026"] = "\226\144\154", |
5f4a657136bc
util.format: Escape ASCII control characters in output
Kim Alvefur <zash@zash.se>
parents:
10035
diff
changeset
|
28 ["\027"] = "\226\144\155", ["\028"] = "\226\144\156", ["\029"] = "\226\144\157", |
5f4a657136bc
util.format: Escape ASCII control characters in output
Kim Alvefur <zash@zash.se>
parents:
10035
diff
changeset
|
29 ["\030"] = "\226\144\158", ["\031"] = "\226\144\159", ["\127"] = "\226\144\161", |
5f4a657136bc
util.format: Escape ASCII control characters in output
Kim Alvefur <zash@zash.se>
parents:
10035
diff
changeset
|
30 }; |
8225
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
31 |
8382
e5d00bf4a4d5
util: Various minor changes to please [luacheck]
Kim Alvefur <zash@zash.se>
parents:
8225
diff
changeset
|
32 local function format(formatstring, ...) |
9687
8c92ef4270c9
util.format: Use pack from util.table
Kim Alvefur <zash@zash.se>
parents:
9656
diff
changeset
|
33 local args = pack(...); |
8c92ef4270c9
util.format: Use pack from util.table
Kim Alvefur <zash@zash.se>
parents:
9656
diff
changeset
|
34 local args_length = args.n; |
8225
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
35 |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
36 -- format specifier spec: |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
37 -- 1. Start: '%%' |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
38 -- 2. Flags: '[%-%+ #0]' |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
39 -- 3. Width: '%d?%d?' |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
40 -- 4. Precision: '%.?%d?%d?' |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
41 -- 5. Option: '[cdiouxXaAeEfgGqs%%]' |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
42 -- |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
43 -- 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
|
44 -- 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
|
45 -- 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
|
46 |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
47 |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
48 -- process each format specifier |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
49 local i = 0; |
8382
e5d00bf4a4d5
util: Various minor changes to please [luacheck]
Kim Alvefur <zash@zash.se>
parents:
8225
diff
changeset
|
50 formatstring = formatstring:gsub("%%[^cdiouxXaAeEfgGqs%%]*[cdiouxXaAeEfgGqs%%]", function(spec) |
8225
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
51 if spec ~= "%%" then |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
52 i = i + 1; |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
53 local arg = args[i]; |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
54 |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
55 local option = spec:sub(-1); |
9656
3da6cc927ee6
util.format: Tweak how nil values are handled
Kim Alvefur <zash@zash.se>
parents:
8417
diff
changeset
|
56 if arg == nil then |
3da6cc927ee6
util.format: Tweak how nil values are handled
Kim Alvefur <zash@zash.se>
parents:
8417
diff
changeset
|
57 args[i] = "nil"; |
11644
fc1b8fe94d04
util.format: Change formatting of nil values to avoid looking like XML
Kim Alvefur <zash@zash.se>
parents:
11638
diff
changeset
|
58 spec = "(%s)"; |
9693
6ed0d6224d64
util.format: Serialize values for the %q format
Kim Alvefur <zash@zash.se>
parents:
9687
diff
changeset
|
59 elseif option == "q" then |
6ed0d6224d64
util.format: Serialize values for the %q format
Kim Alvefur <zash@zash.se>
parents:
9687
diff
changeset
|
60 args[i] = dump(arg); |
6ed0d6224d64
util.format: Serialize values for the %q format
Kim Alvefur <zash@zash.se>
parents:
9687
diff
changeset
|
61 spec = "%s"; |
6ed0d6224d64
util.format: Serialize values for the %q format
Kim Alvefur <zash@zash.se>
parents:
9687
diff
changeset
|
62 elseif option == "s" then |
11647
0fe6a9a3676f
util.format: Allow newlines but ensure following lines are indented
Kim Alvefur <zash@zash.se>
parents:
11646
diff
changeset
|
63 args[i] = tostring(arg):gsub("[%z\1-\8\11-\31\127]", control_symbols):gsub("\n\t?", "\n\t"); |
8225
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
64 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
|
65 args[i] = tostring(arg); |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
66 spec = "[%s]"; |
10034
4fca92d60040
util.format: Handle formats expecting an integer in Lua 5.3+ (fixes #1371)
Kim Alvefur <zash@zash.se>
parents:
9693
diff
changeset
|
67 elseif expects_integer[option] and num_type(arg) ~= "integer" then |
4fca92d60040
util.format: Handle formats expecting an integer in Lua 5.3+ (fixes #1371)
Kim Alvefur <zash@zash.se>
parents:
9693
diff
changeset
|
68 args[i] = tostring(arg); |
4fca92d60040
util.format: Handle formats expecting an integer in Lua 5.3+ (fixes #1371)
Kim Alvefur <zash@zash.se>
parents:
9693
diff
changeset
|
69 spec = "[%s]"; |
8225
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
70 end |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
71 end |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
72 return spec; |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
73 end); |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
74 |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
75 -- process extra args |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
76 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
|
77 i = i + 1; |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
78 local arg = args[i]; |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
79 if arg == nil then |
11644
fc1b8fe94d04
util.format: Change formatting of nil values to avoid looking like XML
Kim Alvefur <zash@zash.se>
parents:
11638
diff
changeset
|
80 args[i] = "(nil)"; |
8225
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
81 else |
11648
96d3cbeb9275
util.format: Escape ASCII control characters also in extra arguments
Kim Alvefur <zash@zash.se>
parents:
11647
diff
changeset
|
82 args[i] = tostring(arg):gsub("[%z\1-\8\11-\31\127]", control_symbols):gsub("\n\t?", "\n\t"); |
8225
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
83 end |
8382
e5d00bf4a4d5
util: Various minor changes to please [luacheck]
Kim Alvefur <zash@zash.se>
parents:
8225
diff
changeset
|
84 formatstring = formatstring .. " [%s]" |
8225
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
85 end |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
86 |
8382
e5d00bf4a4d5
util: Various minor changes to please [luacheck]
Kim Alvefur <zash@zash.se>
parents:
8225
diff
changeset
|
87 return formatstring:format(unpack(args)); |
8225
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
88 end |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
89 |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
90 return { |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
91 format = format; |
70cb72f46a3b
util.format: A string.format wrapper that gracefully handles invalid arguments
Waqas Hussain <waqas20@gmail.com>
parents:
diff
changeset
|
92 }; |