summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2011-02-06 21:32:25 -0500
committerNat Goodspeed <nat@lindenlab.com>2011-02-06 21:32:25 -0500
commit1a1563bb154102c09a172235081d8db62e4fbec9 (patch)
tree7207634d5b4c485a52a40815748775517ca8ffb0
parentf4f3791a5ff1cc76b9d1054c269e69d44cdaf8d6 (diff)
Untested support for passing array to map-registered function.
An array-registered function has no param names, so you can only pass an array: a map would be meaningless. Initial implementation of map-registered functions assumed that since you CAN pass a map, you MUST pass a map. But in fact it's meaningful to pass an array as well -- for whatever reason -- and easy to implement, so there you are. Tests to follow.
-rw-r--r--indra/llcommon/lleventdispatcher.cpp72
-rw-r--r--indra/llcommon/tests/lleventdispatcher_test.cpp6
2 files changed, 54 insertions, 24 deletions
diff --git a/indra/llcommon/lleventdispatcher.cpp b/indra/llcommon/lleventdispatcher.cpp
index 52660105c4..5b6d4efbe9 100644
--- a/indra/llcommon/lleventdispatcher.cpp
+++ b/indra/llcommon/lleventdispatcher.cpp
@@ -269,9 +269,10 @@ LLSDArgsMapper::LLSDArgsMapper(const std::string& function,
LLSD LLSDArgsMapper::map(const LLSD& argsmap) const
{
- if (! (argsmap.isUndefined() || argsmap.isMap()))
+ if (! (argsmap.isUndefined() || argsmap.isMap() || argsmap.isArray()))
{
- LL_ERRS("LLSDArgsMapper") << _function << " map() needs a map, not " << argsmap << LL_ENDL;
+ LL_ERRS("LLSDArgsMapper") << _function << " map() needs a map or array, not "
+ << argsmap << LL_ENDL;
}
// Initialize the args array. Indexing a non-const LLSD array grows it
// to appropriate size, but we don't want to resize this one on each
@@ -295,30 +296,57 @@ LLSD LLSDArgsMapper::map(const LLSD& argsmap) const
// holes. (Avoid std::vector<bool> which is known to be odd -- can we
// iterate?)
FilledVector filled(args.size());
- // Walk the map.
- for (LLSD::map_const_iterator mi(argsmap.beginMap()), mend(argsmap.endMap());
- mi != mend; ++mi)
+
+ if (argsmap.isArray())
{
- // mi->first is a parameter-name string, with mi->second its
- // value. Look up the name's position index in _indexes.
- IndexMap::const_iterator ixit(_indexes.find(mi->first));
- if (ixit == _indexes.end())
+ // Fill args from array. If there are too many args in passed array,
+ // ignore the rest.
+ LLSD::Integer size(argsmap.size());
+ if (size > args.size())
+ {
+ // We don't just use std::min() because we want to sneak in this
+ // warning if caller passes too many args.
+ LL_WARNS("LLSDArgsMapper") << _function << " needs " << args.size()
+ << " params, ignoring last " << (size - args.size())
+ << " of passed " << size << ": " << argsmap << LL_ENDL;
+ size = args.size();
+ }
+ for (LLSD::Integer i(0); i < size; ++i)
+ {
+ // Copy the actual argument from argsmap
+ args[i] = argsmap[i];
+ // Note that it's been filled
+ filled[i] = 1;
+ }
+ }
+ else
+ {
+ // argsmap is in fact a map. Walk the map.
+ for (LLSD::map_const_iterator mi(argsmap.beginMap()), mend(argsmap.endMap());
+ mi != mend; ++mi)
{
- // Allow for a map containing more params than were passed in
- // our names array. Caller typically receives a map containing
- // the function name, cruft such as reqid, etc. Ignore keys
- // not defined in _indexes.
- LL_DEBUGS("LLSDArgsMapper") << _function << " ignoring "
- << mi->first << "=" << mi->second << LL_ENDL;
- continue;
+ // mi->first is a parameter-name string, with mi->second its
+ // value. Look up the name's position index in _indexes.
+ IndexMap::const_iterator ixit(_indexes.find(mi->first));
+ if (ixit == _indexes.end())
+ {
+ // Allow for a map containing more params than were passed in
+ // our names array. Caller typically receives a map containing
+ // the function name, cruft such as reqid, etc. Ignore keys
+ // not defined in _indexes.
+ LL_DEBUGS("LLSDArgsMapper") << _function << " ignoring "
+ << mi->first << "=" << mi->second << LL_ENDL;
+ continue;
+ }
+ LLSD::Integer pos = ixit->second;
+ // Store the value at that position in the args array.
+ args[pos] = mi->second;
+ // Don't forget to record the fact that we've filled this
+ // position.
+ filled[pos] = 1;
}
- LLSD::Integer pos = ixit->second;
- // Store the value at that position in the args array.
- args[pos] = mi->second;
- // Don't forget to record the fact that we've filled this
- // position.
- filled[pos] = 1;
}
+
// Fill any remaining holes from _defaults.
LLSD unfilled(LLSD::emptyArray());
for (LLSD::Integer i = 0, iend = args.size(); i < iend; ++i)
diff --git a/indra/llcommon/tests/lleventdispatcher_test.cpp b/indra/llcommon/tests/lleventdispatcher_test.cpp
index bdd8c16cec..c599672bc5 100644
--- a/indra/llcommon/tests/lleventdispatcher_test.cpp
+++ b/indra/llcommon/tests/lleventdispatcher_test.cpp
@@ -682,7 +682,7 @@ namespace tut
// (scalar | map | array (too short | too long | just right))
// [trap LL_WARNS for too-long case?]
// - (Free function | non-static method), arbitrary args, map style with
- // (scalar | array | map (all | too many | holes (with | without) defaults))
+ // (scalar | (array | map) (all | too many | holes (with | without) defaults))
// - const char* param gets ("" | NULL)
// Query cases:
@@ -1108,7 +1108,9 @@ namespace tut
std::string map_exc("needs a map");
call_exc("free0_map", 17, map_exc);
- call_exc("free0_map", LLSDArray("a")("b"), map_exc);
+ // Passing an array to a map-style function works now! No longer an
+ // error case!
+// call_exc("free0_map", LLSDArray("a")("b"), map_exc);
}
struct FunctionsTriple