Explorar o código

Add vector.to_string and vector.from_string (#10323)

Writing vectors as strings is very common and should belong to `vector.*`. `minetest.pos_to_string` is also too long to write, implies that one should only use it for positions and leaves no spaces after the commas.
DS %!s(int64=3) %!d(string=hai) anos
pai
achega
2332527765
Modificáronse 3 ficheiros con 45 adicións e 0 borrados
  1. 19 0
      builtin/common/tests/vector_spec.lua
  2. 16 0
      builtin/common/vector.lua
  3. 10 0
      doc/lua_api.txt

+ 19 - 0
builtin/common/tests/vector_spec.lua

@@ -48,6 +48,25 @@ describe("vector", function()
 		assert.same({ x = 41, y = 52, z = 63 }, vector.offset(vector.new(1, 2, 3), 40, 50, 60))
 	end)
 
+	it("to_string()", function()
+		local v = vector.new(1, 2, 3.14)
+		assert.same("(1, 2, 3.14)", vector.to_string(v))
+	end)
+
+	it("from_string()", function()
+		local v = vector.new(1, 2, 3.14)
+		assert.same({v, 13}, {vector.from_string("(1, 2, 3.14)")})
+		assert.same({v, 12}, {vector.from_string("(1,2 ,3.14)")})
+		assert.same({v, 12}, {vector.from_string("(1,2,3.14,)")})
+		assert.same({v, 11}, {vector.from_string("(1 2 3.14)")})
+		assert.same({v, 15}, {vector.from_string("( 1, 2, 3.14 )")})
+		assert.same({v, 15}, {vector.from_string(" ( 1, 2, 3.14) ")})
+		assert.same({vector.new(), 8}, {vector.from_string("(0,0,0) ( 1, 2, 3.14) ")})
+		assert.same({v, 22}, {vector.from_string("(0,0,0) ( 1, 2, 3.14) ", 8)})
+		assert.same({v, 22}, {vector.from_string("(0,0,0) ( 1, 2, 3.14) ", 9)})
+		assert.same(nil, vector.from_string("nothing"))
+	end)
+
 	-- This function is needed because of floating point imprecision.
 	local function almost_equal(a, b)
 		if type(a) == "number" then

+ 16 - 0
builtin/common/vector.lua

@@ -12,6 +12,22 @@ function vector.new(a, b, c)
 	return {x=0, y=0, z=0}
 end
 
+function vector.from_string(s, init)
+	local x, y, z, np = string.match(s, "^%s*%(%s*([^%s,]+)%s*[,%s]%s*([^%s,]+)%s*[,%s]" ..
+			"%s*([^%s,]+)%s*[,%s]?%s*%)()", init)
+	x = tonumber(x)
+	y = tonumber(y)
+	z = tonumber(z)
+	if not (x and y and z) then
+		return nil
+	end
+	return {x = x, y = y, z = z}, np
+end
+
+function vector.to_string(v)
+	return string.format("(%g, %g, %g)", v.x, v.y, v.z)
+end
+
 function vector.equals(a, b)
 	return a.x == b.x and
 	       a.y == b.y and

+ 10 - 0
doc/lua_api.txt

@@ -3149,6 +3149,16 @@ For the following functions, `v`, `v1`, `v2` are vectors,
     * Returns a vector.
     * A copy of `a` if `a` is a vector.
     * `{x = a, y = b, z = c}`, if all of `a`, `b`, `c` are defined numbers.
+* `vector.from_string(s[, init])`:
+    * Returns `v, np`, where `v` is a vector read from the given string `s` and
+      `np` is the next position in the string after the vector.
+    * Returns `nil` on failure.
+    * `s`: Has to begin with a substring of the form `"(x, y, z)"`. Additional
+           spaces, leaving away commas and adding an additional comma to the end
+           is allowed.
+    * `init`: If given starts looking for the vector at this string index.
+* `vector.to_string(v)`:
+    * Returns a string of the form `"(x, y, z)"`.
 * `vector.direction(p1, p2)`:
     * Returns a vector of length 1 with direction `p1` to `p2`.
     * If `p1` and `p2` are identical, returns `{x = 0, y = 0, z = 0}`.