summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorMaxim Nikolenko <maximnproductengine@lindenlab.com>2024-07-04 14:06:57 +0300
committerGitHub <noreply@github.com>2024-07-04 14:06:57 +0300
commitfb11243dd0b3445ae8ad03faf09927f542412b46 (patch)
tree90e659aa194b15bf61eae93dd454aad75a3e9c4c /indra
parentd4aeeaf31511b3abe58d0c386fecf34e54632422 (diff)
parenta877e3a0994a19d522e77d6781844341197dd6dc (diff)
Use llsd::toMap() to return LLSD maps from "LLAppearance" listener.
Use llsd::toMap() to return LLSD maps from "LLAppearance" listener.
Diffstat (limited to 'indra')
-rw-r--r--indra/llcommon/llsdutil.h73
-rw-r--r--indra/newview/llappearancelistener.cpp31
2 files changed, 77 insertions, 27 deletions
diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h
index aa497c53c7..7c31dc8aa0 100644
--- a/indra/llcommon/llsdutil.h
+++ b/indra/llcommon/llsdutil.h
@@ -365,15 +365,14 @@ private:
// subject function has returned, so we must ensure that any constructed
// LLSDParam<T> lives just as long as this LLSDParam<LLSD> does. Putting
// each LLSDParam<T> on the heap and capturing a smart pointer in a vector
- // works. We would have liked to use std::unique_ptr, but vector entries
- // must be copyable.
+ // works.
// (Alternatively we could assume that every instance of LLSDParam<LLSD>
// will be asked for at most ONE conversion. We could store a scalar
// std::unique_ptr and, when constructing an new LLSDParam<T>, assert that
// the unique_ptr is empty. But some future change in usage patterns, and
// consequent failure of that assertion, would be very mysterious. Instead
// of explaining how to fix it, just fix it now.)
- mutable std::vector<std::shared_ptr<LLSDParamBase>> converters_;
+ mutable std::vector<std::unique_ptr<LLSDParamBase>> converters_;
public:
LLSDParam(const LLSD& value): value_(value) {}
@@ -389,9 +388,9 @@ public:
{
// capture 'ptr' with the specific subclass type because converters_
// only stores LLSDParamBase pointers
- auto ptr{ std::make_shared<LLSDParam<std::decay_t<T>>>(value_) };
+ auto ptr{ new LLSDParam<std::decay_t<T>>(value_) };
// keep the new converter alive until we ourselves are destroyed
- converters_.push_back(ptr);
+ converters_.emplace_back(ptr);
return *ptr;
}
};
@@ -474,12 +473,12 @@ public:
}
};
-namespace llsd
-{
-
/*****************************************************************************
* range-based for-loop helpers for LLSD
*****************************************************************************/
+namespace llsd
+{
+
/// Usage: for (LLSD item : inArray(someLLSDarray)) { ... }
class inArray
{
@@ -525,7 +524,9 @@ private:
} // namespace llsd
-
+/*****************************************************************************
+* deep and shallow clone
+*****************************************************************************/
// Creates a deep clone of an LLSD object. Maps, Arrays and binary objects
// are duplicated, atomic primitives (Boolean, Integer, Real, etc) simply
// use a shared reference.
@@ -553,6 +554,60 @@ LLSD shallow(LLSD value, LLSD filter=LLSD()) { return llsd_shallow(value, filter
} // namespace llsd
+/*****************************************************************************
+* toArray(), toMap()
+*****************************************************************************/
+namespace llsd
+{
+
+// For some T convertible to LLSD, given std::vector<T> myVec,
+// toArray(myVec) returns an LLSD array whose entries correspond to the
+// items in myVec.
+// For some U convertible to LLSD, given function U xform(const T&),
+// toArray(myVec, xform) returns an LLSD array whose every entry is
+// xform(item) of the corresponding item in myVec.
+// toArray() actually works with any container<C> usable with range
+// 'for', not just std::vector.
+// (Once we get C++20 we can use std::identity instead of this default lambda.)
+template <typename C, typename FUNC>
+LLSD toArray(const C& container, FUNC&& func=[](const auto& arg){ return arg; })
+{
+ LLSD array;
+ for (const auto& item : container)
+ {
+ array.append(std::forward<FUNC>(func)(item));
+ }
+ return array;
+}
+
+// For some T convertible to LLSD, given std::map<std::string, T> myMap,
+// toMap(myMap) returns an LLSD map whose entries correspond to the
+// (key, value) pairs in myMap.
+// For some U convertible to LLSD, given function
+// std::pair<std::string, U> xform(const std::pair<std::string, T>&),
+// toMap(myMap, xform) returns an LLSD map whose every entry is
+// xform(pair) of the corresponding (key, value) pair in myMap.
+// toMap() actually works with any container usable with range 'for', not
+// just std::map. It need not even be an associative container, as long as
+// you pass an xform function that returns std::pair<std::string, U>.
+// (Once we get C++20 we can use std::identity instead of this default lambda.)
+template <typename C, typename FUNC>
+LLSD toMap(const C& container, FUNC&& func=[](const auto& arg){ return arg; })
+{
+ LLSD map;
+ for (const auto& pair : container)
+ {
+ const auto& [key, value] = std::forward<FUNC>(func)(pair);
+ map[key] = value;
+ }
+ return map;
+}
+
+} // namespace llsd
+
+/*****************************************************************************
+* boost::hash<LLSD>
+*****************************************************************************/
// Specialization for generating a hash value from an LLSD block.
namespace boost
{
diff --git a/indra/newview/llappearancelistener.cpp b/indra/newview/llappearancelistener.cpp
index b29eb48a1b..2a3133433a 100644
--- a/indra/newview/llappearancelistener.cpp
+++ b/indra/newview/llappearancelistener.cpp
@@ -127,12 +127,9 @@ void LLAppearanceListener::getOutfitsList(LLSD const &data)
LLIsType is_category(LLAssetType::AT_CATEGORY);
gInventory.collectDescendentsIf(outfits_id, cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH, is_category);
- LLSD outfits_data;
- for (const LLPointer<LLViewerInventoryCategory> &cat : cat_array)
- {
- outfits_data[cat->getUUID().asString()] = cat->getName();
- }
- response["outfits"] = outfits_data;
+ response["outfits"] = llsd::toMap(cat_array,
+ [](const LLPointer<LLViewerInventoryCategory> &cat)
+ { return std::make_pair(cat->getUUID().asString(), cat->getName()); });
}
void LLAppearanceListener::getOutfitItems(LLSD const &data)
@@ -150,16 +147,14 @@ void LLAppearanceListener::getOutfitItems(LLSD const &data)
LLFindOutfitItems collector = LLFindOutfitItems();
gInventory.collectDescendentsIf(outfit_id, cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH, collector);
- LLSD items_data;
- for (const LLPointer<LLViewerInventoryItem> &it : item_array)
- {
- LLSD info;
- info["name"] = it->getName();
- info["wearable_type"] = LLWearableType::getInstance()->getTypeName(it->isWearableType() ? it->getWearableType() : LLWearableType::WT_NONE);
- info["is_worn"] = get_is_item_worn(it);
-
- items_data[it->getUUID().asString()] = info;
- }
-
- response["items"] = items_data;
+ response["items"] = llsd::toMap(item_array,
+ [](const LLPointer<LLViewerInventoryItem> &it)
+ {
+ return std::make_pair(
+ it->getUUID().asString(),
+ llsd::map(
+ "name", it->getName(),
+ "wearable_type", LLWearableType::getInstance()->getTypeName(it->isWearableType() ? it->getWearableType() : LLWearableType::WT_NONE),
+ "is_worn", get_is_item_worn(it)));
+ });
}