util.format: Also handle the %p format added in Lua 5.4
authorKim Alvefur <zash@zash.se>
Sat, 11 Dec 2021 13:39:58 +0100
changeset 12037 161f8268c4b3
parent 12036 3db09eb4c43b
child 12038 ee94ac51b2dd
util.format: Also handle the %p format added in Lua 5.4
spec/util_format_spec.lua
util/format.lua
--- a/spec/util_format_spec.lua	Sat Dec 11 13:30:34 2021 +0100
+++ b/spec/util_format_spec.lua	Sat Dec 11 13:39:58 2021 +0100
@@ -25,5 +25,14 @@
 			assert.equal("\"Hello w\\195rld\"", format("%s", "Hello w\195rld"));
 		end);
 
+		if _VERSION >= "Lua 5.4" then
+			it("handles %p formats", function ()
+				assert.matches("a 0x%x+ b", format("%s %p %s", "a", {}, "b"));
+			end)
+		else
+			it("does something with %p formats", function ()
+				assert.string(format("%p", {}));
+			end)
+		end
 	end);
 end);
--- a/util/format.lua	Sat Dec 11 13:30:34 2021 +0100
+++ b/util/format.lua	Sat Dec 11 13:39:58 2021 +0100
@@ -29,6 +29,7 @@
 	["\027"] = "\226\144\155", ["\028"] = "\226\144\156", ["\029"] = "\226\144\157",
 	["\030"] = "\226\144\158", ["\031"] = "\226\144\159", ["\127"] = "\226\144\161",
 };
+local supports_p = pcall(string.format, "%p", "");
 
 local function format(formatstring, ...)
 	local args = pack(...);
@@ -44,11 +45,12 @@
 	-- 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.
 	-- This function does not accept string values containing embedded zeros, except as arguments to the q option.
 	-- a and A are only in Lua 5.2+
+	-- Lua 5.4 adds a p format that produces a pointer
 
 
 	-- process each format specifier
 	local i = 0;
-	formatstring = formatstring:gsub("%%[^cdiouxXaAeEfgGqs%%]*[cdiouxXaAeEfgGqs%%]", function(spec)
+	formatstring = formatstring:gsub("%%[^cdiouxXaAeEfgGpqs%%]*[cdiouxXaAeEfgGpqs%%]", function(spec)
 		if spec == "%%" then return end
 		i = i + 1;
 		local arg = args[i];
@@ -66,7 +68,7 @@
 			return
 		end
 
-		if option ~= "s" and option ~= "q" then
+		if option ~= "s" and option ~= "q" and option ~= "p" then
 			-- all other options expect numbers
 			if t ~= "number" then
 				-- arg isn't number as expected?
@@ -82,7 +84,15 @@
 			end
 		end
 
-		if t == "string" then
+
+		if option == "p" and not supports_p then
+			arg = tostring(arg);
+			option = "s";
+			spec = "[%s]";
+			t = "string";
+		end
+
+		if t == "string" and option ~= "p" then
 			if not valid_utf8(arg) then
 				option = "q";
 			else
@@ -95,6 +105,11 @@
 			args[i] = dump(arg);
 			return "%s";
 		end
+
+		if option == "p" and (t == "boolean" or t == "number") then
+			args[i] = tostring(arg);
+			return "[%s]";
+		end
 	end);
 
 	-- process extra args