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.
meow-7.2.2
Nat Goodspeed 2011-02-06 21:32:25 -05:00
parent f4f3791a5f
commit 1a1563bb15
2 changed files with 54 additions and 24 deletions

View File

@ -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())
{
// 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;
// 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;
}
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;
}
else
{
// argsmap is in fact a map. Walk the map.
for (LLSD::map_const_iterator mi(argsmap.beginMap()), mend(argsmap.endMap());
mi != mend; ++mi)
{
// 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;
}
}
// Fill any remaining holes from _defaults.
LLSD unfilled(LLSD::emptyArray());
for (LLSD::Integer i = 0, iend = args.size(); i < iend; ++i)

View File

@ -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