From 52d15b64456f2afc54d2fcc30e22c1078e2db12c Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Mon, 14 Oct 2019 15:49:37 -0400
Subject: [PATCH] DRTVWR-476: Add llsd::array() and llsd::map() variadic
 functions.

llsd::array(), as one might suspect, takes an arbitrary number of arguments of
arbitrary convertible types and returns an LLSD::Array constructed from those
elements. This supercedes the older LLSDArray class.

llsd::map() takes an even number of arguments paired as (LLSD::String,
arbitrary convertible type) and returns an LLSD::Map constructed from those
(key, value) pairs. This supercedes the older LLSDMap class.

These two functions not only have a simpler API -- arbitrary function
arguments rather than an (arg list)(arg list) sequence -- but also
specifically return a final LLSD object, rather than needing conversion to
LLSD from the LLSDArray or LLSDMap object.

Also support LLSD == LLSD and LLSD != LLSD comparisons, using llsd_equals()
with default exact-float-equality semantics.
---
 indra/llcommon/llsdutil.h | 70 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)

diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h
index e659aa574ea..2a8b44ec4e0 100644
--- a/indra/llcommon/llsdutil.h
+++ b/indra/llcommon/llsdutil.h
@@ -129,6 +129,16 @@ LL_COMMON_API std::string llsd_matches(const LLSD& prototype, const LLSD& data,
 /// equality rather than bitwise equality, pass @a bits as for
 /// is_approx_equal_fraction().
 LL_COMMON_API bool llsd_equals(const LLSD& lhs, const LLSD& rhs, int bits=-1);
+/// If you don't care about LLSD::Real equality
+inline bool operator==(const LLSD& lhs, const LLSD& rhs)
+{
+    return llsd_equals(lhs, rhs);
+}
+inline bool operator!=(const LLSD& lhs, const LLSD& rhs)
+{
+    // operator!=() should always be the negation of operator==()
+    return ! (lhs == rhs);
+}
 
 // Simple function to copy data out of input & output iterators if
 // there is no need for casting.
@@ -236,6 +246,36 @@ class LLSDArray
     LLSD _data;
 };
 
+namespace llsd
+{
+
+/**
+ * Construct an LLSD::Array inline, using modern C++ variadic arguments.
+ */
+
+// recursion tail
+inline
+void array_(LLSD&) {}
+
+// recursive call
+template <typename T0, typename... Ts>
+void array_(LLSD& data, T0&& v0, Ts&&... vs)
+{
+    data.append(std::forward<T0>(v0));
+    array_(data, std::forward<Ts>(vs)...);
+}
+
+// public interface
+template <typename... Ts>
+LLSD array(Ts&&... vs)
+{
+    LLSD data;
+    array_(data, std::forward<Ts>(vs)...);
+    return data;
+}
+
+} // namespace llsd
+
 /*****************************************************************************
 *   LLSDMap
 *****************************************************************************/
@@ -280,6 +320,36 @@ class LLSDMap
     LLSD _data;
 };
 
+namespace llsd
+{
+
+/**
+ * Construct an LLSD::Map inline, using modern C++ variadic arguments.
+ */
+
+// recursion tail
+inline
+void map_(LLSD&) {}
+
+// recursive call
+template <typename T0, typename... Ts>
+void map_(LLSD& data, const LLSD::String& k0, T0&& v0, Ts&&... vs)
+{
+    data[k0] = v0;
+    map_(data, std::forward<Ts>(vs)...);
+}
+
+// public interface
+template <typename... Ts>
+LLSD map(Ts&&... vs)
+{
+    LLSD data;
+    map_(data, std::forward<Ts>(vs)...);
+    return data;
+}
+
+} // namespace llsd
+
 /*****************************************************************************
 *   LLSDParam
 *****************************************************************************/
-- 
GitLab