Commits

nat_linden  committed 031d6a3

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.

  • Participants
  • Parent commits 8971d95

Comments (0)

Files changed (2)

File indra/llcommon/lleventdispatcher.cpp

 
 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
     // 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();
         }
-        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;
+        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)
+        {
+            // 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)

File indra/llcommon/tests/lleventdispatcher_test.cpp

     //   (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:
 
         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