671 lines
23 KiB
C++
671 lines
23 KiB
C++
/**
|
|
* @file lleventdispatcher.cpp
|
|
* @author Nat Goodspeed
|
|
* @date 2009-06-18
|
|
* @brief Implementation for lleventdispatcher.
|
|
*
|
|
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
|
|
* Second Life Viewer Source Code
|
|
* Copyright (C) 2010, Linden Research, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation;
|
|
* version 2.1 of the License only.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#if LL_WINDOWS
|
|
#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
|
|
#endif
|
|
|
|
// Precompiled header
|
|
#include "linden_common.h"
|
|
// associated header
|
|
#include "lleventdispatcher.h"
|
|
// STL headers
|
|
// std headers
|
|
// external library headers
|
|
// other Linden headers
|
|
#include "llevents.h"
|
|
#include "llerror.h"
|
|
#include "llsdutil.h"
|
|
#include "stringize.h"
|
|
#include <memory> // std::auto_ptr
|
|
|
|
/*****************************************************************************
|
|
* LLSDArgsSource
|
|
*****************************************************************************/
|
|
/**
|
|
* Store an LLSD array, producing its elements one at a time. Die with LL_ERRS
|
|
* if the consumer requests more elements than the array contains.
|
|
*/
|
|
class LL_COMMON_API LLSDArgsSource
|
|
{
|
|
public:
|
|
LLSDArgsSource(const std::string function, const LLSD& args);
|
|
~LLSDArgsSource();
|
|
|
|
LLSD next();
|
|
|
|
void done() const;
|
|
|
|
private:
|
|
std::string _function;
|
|
LLSD _args;
|
|
LLSD::Integer _index;
|
|
};
|
|
|
|
LLSDArgsSource::LLSDArgsSource(const std::string function, const LLSD& args):
|
|
_function(function),
|
|
_args(args),
|
|
_index(0)
|
|
{
|
|
if (! (_args.isUndefined() || _args.isArray()))
|
|
{
|
|
LL_ERRS("LLSDArgsSource") << _function << " needs an args array instead of "
|
|
<< _args << LL_ENDL;
|
|
}
|
|
}
|
|
|
|
LLSDArgsSource::~LLSDArgsSource()
|
|
{
|
|
done();
|
|
}
|
|
|
|
LLSD LLSDArgsSource::next()
|
|
{
|
|
if (_index >= _args.size())
|
|
{
|
|
LL_ERRS("LLSDArgsSource") << _function << " requires more arguments than the "
|
|
<< _args.size() << " provided: " << _args << LL_ENDL;
|
|
}
|
|
return _args[_index++];
|
|
}
|
|
|
|
void LLSDArgsSource::done() const
|
|
{
|
|
if (_index < _args.size())
|
|
{
|
|
LL_WARNS("LLSDArgsSource") << _function << " only consumed " << _index
|
|
<< " of the " << _args.size() << " arguments provided: "
|
|
<< _args << LL_ENDL;
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* LLSDArgsMapper
|
|
*****************************************************************************/
|
|
/**
|
|
* From a formal parameters description and a map of arguments, construct an
|
|
* arguments array.
|
|
*
|
|
* That is, given:
|
|
* - an LLSD array of length n containing parameter-name strings,
|
|
* corresponding to the arguments of a function of interest
|
|
* - an LLSD collection specifying default parameter values, either:
|
|
* - an LLSD array of length m <= n, matching the rightmost m params, or
|
|
* - an LLSD map explicitly stating default name=value pairs
|
|
* - an LLSD map of parameter names and actual values for a particular
|
|
* function call
|
|
* construct an LLSD array of actual argument values for this function call.
|
|
*
|
|
* The parameter-names array and the defaults collection describe the function
|
|
* being called. The map might vary with every call, providing argument values
|
|
* for the described parameters.
|
|
*
|
|
* The array of parameter names must match the number of parameters expected
|
|
* by the function of interest.
|
|
*
|
|
* If you pass a map of default parameter values, it provides default values
|
|
* as you might expect. It is an error to specify a default value for a name
|
|
* not listed in the parameters array.
|
|
*
|
|
* If you pass an array of default parameter values, it is mapped to the
|
|
* rightmost m of the n parameter names. It is an error if the default-values
|
|
* array is longer than the parameter-names array. Consider the following
|
|
* parameter names: ["a", "b", "c", "d"].
|
|
*
|
|
* - An empty array of default values (or an isUndefined() value) asserts that
|
|
* every one of the above parameter names is required.
|
|
* - An array of four default values [1, 2, 3, 4] asserts that every one of
|
|
* the above parameters is optional. If the current parameter map is empty,
|
|
* they will be passed to the function as [1, 2, 3, 4].
|
|
* - An array of two default values [11, 12] asserts that parameters "a" and
|
|
* "b" are required, while "c" and "d" are optional, having default values
|
|
* "c"=11 and "d"=12.
|
|
*
|
|
* The arguments array is constructed as follows:
|
|
*
|
|
* - Arguments-map keys not found in the parameter-names array are ignored.
|
|
* - Entries from the map provide values for an improper subset of the
|
|
* parameters named in the parameter-names array. This results in a
|
|
* tentative values array with "holes." (size of map) + (number of holes) =
|
|
* (size of names array)
|
|
* - Holes are filled with the default values.
|
|
* - Any remaining holes constitute an error.
|
|
*/
|
|
class LL_COMMON_API LLSDArgsMapper
|
|
{
|
|
public:
|
|
/// Accept description of function: function name, param names, param
|
|
/// default values
|
|
LLSDArgsMapper(const std::string& function, const LLSD& names, const LLSD& defaults);
|
|
|
|
/// Given arguments map, return LLSD::Array of parameter values, or LL_ERRS.
|
|
LLSD map(const LLSD& argsmap) const;
|
|
|
|
private:
|
|
static std::string formatlist(const LLSD&);
|
|
|
|
// The function-name string is purely descriptive. We want error messages
|
|
// to be able to indicate which function's LLSDArgsMapper has the problem.
|
|
std::string _function;
|
|
// Store the names array pretty much as given.
|
|
LLSD _names;
|
|
// Though we're handed an array of name strings, it's more useful to us to
|
|
// store it as a map from name string to position index. Of course that's
|
|
// easy to generate from the incoming names array, but why do it more than
|
|
// once?
|
|
typedef std::map<LLSD::String, LLSD::Integer> IndexMap;
|
|
IndexMap _indexes;
|
|
// Generated array of default values, aligned with the array of param names.
|
|
LLSD _defaults;
|
|
// Indicate whether we have a default value for each param.
|
|
typedef std::vector<char> FilledVector;
|
|
FilledVector _has_dft;
|
|
};
|
|
|
|
LLSDArgsMapper::LLSDArgsMapper(const std::string& function,
|
|
const LLSD& names, const LLSD& defaults):
|
|
_function(function),
|
|
_names(names),
|
|
_has_dft(names.size())
|
|
{
|
|
if (! (_names.isUndefined() || _names.isArray()))
|
|
{
|
|
LL_ERRS("LLSDArgsMapper") << function << " names must be an array, not " << names << LL_ENDL;
|
|
}
|
|
LLSD::Integer nparams(_names.size());
|
|
// From _names generate _indexes.
|
|
for (LLSD::Integer ni = 0, nend = _names.size(); ni < nend; ++ni)
|
|
{
|
|
_indexes[_names[ni]] = ni;
|
|
}
|
|
|
|
// Presize _defaults() array so we don't have to resize it more than once.
|
|
// All entries are initialized to LLSD(); but since _has_dft is still all
|
|
// 0, they're all "holes" for now.
|
|
if (nparams)
|
|
{
|
|
_defaults[nparams - 1] = LLSD();
|
|
}
|
|
|
|
if (defaults.isUndefined() || defaults.isArray())
|
|
{
|
|
LLSD::Integer ndefaults = defaults.size();
|
|
// defaults is a (possibly empty) array. Right-align it with names.
|
|
if (ndefaults > nparams)
|
|
{
|
|
LL_ERRS("LLSDArgsMapper") << function << " names array " << names
|
|
<< " shorter than defaults array " << defaults << LL_ENDL;
|
|
}
|
|
|
|
// Offset by which we slide defaults array right to right-align with
|
|
// _names array
|
|
LLSD::Integer offset = nparams - ndefaults;
|
|
// Fill rightmost _defaults entries from defaults, and mark them as
|
|
// filled
|
|
for (LLSD::Integer i = 0, iend = ndefaults; i < iend; ++i)
|
|
{
|
|
_defaults[i + offset] = defaults[i];
|
|
_has_dft[i + offset] = 1;
|
|
}
|
|
}
|
|
else if (defaults.isMap())
|
|
{
|
|
// defaults is a map. Use it to populate the _defaults array.
|
|
LLSD bogus;
|
|
for (LLSD::map_const_iterator mi(defaults.beginMap()), mend(defaults.endMap());
|
|
mi != mend; ++mi)
|
|
{
|
|
IndexMap::const_iterator ixit(_indexes.find(mi->first));
|
|
if (ixit == _indexes.end())
|
|
{
|
|
bogus.append(mi->first);
|
|
continue;
|
|
}
|
|
|
|
LLSD::Integer pos = ixit->second;
|
|
// Store default value at that position in the _defaults array.
|
|
_defaults[pos] = mi->second;
|
|
// Don't forget to record the fact that we've filled this
|
|
// position.
|
|
_has_dft[pos] = 1;
|
|
}
|
|
if (bogus.size())
|
|
{
|
|
LL_ERRS("LLSDArgsMapper") << function << " defaults specified for nonexistent params "
|
|
<< formatlist(bogus) << LL_ENDL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LL_ERRS("LLSDArgsMapper") << function << " defaults must be a map or an array, not "
|
|
<< defaults << LL_ENDL;
|
|
}
|
|
}
|
|
|
|
LLSD LLSDArgsMapper::map(const LLSD& argsmap) const
|
|
{
|
|
if (! (argsmap.isUndefined() || argsmap.isMap() || argsmap.isArray()))
|
|
{
|
|
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
|
|
// new operation. Just make it as big as we need before we start
|
|
// stuffing values into it.
|
|
LLSD args(LLSD::emptyArray());
|
|
if (_defaults.size() == 0)
|
|
{
|
|
// If this function requires no arguments, fast exit. (Don't try to
|
|
// assign to args[-1].)
|
|
return args;
|
|
}
|
|
args[_defaults.size() - 1] = LLSD();
|
|
|
|
// Get a vector of chars to indicate holes. It's tempting to just scan
|
|
// for LLSD::isUndefined() values after filling the args array from
|
|
// the map, but it's plausible for caller to explicitly pass
|
|
// isUndefined() as the value of some parameter name. That's legal
|
|
// since isUndefined() has well-defined conversions (default value)
|
|
// for LLSD data types. So use a whole separate array for detecting
|
|
// holes. (Avoid std::vector<bool> which is known to be odd -- can we
|
|
// iterate?)
|
|
FilledVector filled(args.size());
|
|
|
|
if (argsmap.isArray())
|
|
{
|
|
// 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)
|
|
{
|
|
// 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)
|
|
{
|
|
if (! filled[i])
|
|
{
|
|
// If there's no default value for this parameter, that's an
|
|
// error.
|
|
if (! _has_dft[i])
|
|
{
|
|
unfilled.append(_names[i]);
|
|
}
|
|
else
|
|
{
|
|
args[i] = _defaults[i];
|
|
}
|
|
}
|
|
}
|
|
// If any required args -- args without defaults -- were left unfilled
|
|
// by argsmap, that's a problem.
|
|
if (unfilled.size())
|
|
{
|
|
LL_ERRS("LLSDArgsMapper") << _function << " missing required arguments "
|
|
<< formatlist(unfilled) << " from " << argsmap << LL_ENDL;
|
|
}
|
|
|
|
// done
|
|
return args;
|
|
}
|
|
|
|
std::string LLSDArgsMapper::formatlist(const LLSD& list)
|
|
{
|
|
std::ostringstream out;
|
|
const char* delim = "";
|
|
for (auto const& entry : list.array())
|
|
{
|
|
out << delim << entry.asString();
|
|
delim = ", ";
|
|
}
|
|
return out.str();
|
|
}
|
|
|
|
LLEventDispatcher::LLEventDispatcher(const std::string& desc, const std::string& key):
|
|
mDesc(desc),
|
|
mKey(key)
|
|
{
|
|
}
|
|
|
|
LLEventDispatcher::~LLEventDispatcher()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* DispatchEntry subclass used for callables accepting(const LLSD&)
|
|
*/
|
|
struct LLEventDispatcher::LLSDDispatchEntry: public LLEventDispatcher::DispatchEntry
|
|
{
|
|
LLSDDispatchEntry(const std::string& desc, const Callable& func, const LLSD& required):
|
|
DispatchEntry(desc),
|
|
mFunc(func),
|
|
mRequired(required)
|
|
{}
|
|
|
|
Callable mFunc;
|
|
LLSD mRequired;
|
|
|
|
virtual void call(const std::string& desc, const LLSD& event) const
|
|
{
|
|
// Validate the syntax of the event itself.
|
|
std::string mismatch(llsd_matches(mRequired, event));
|
|
if (! mismatch.empty())
|
|
{
|
|
LL_ERRS("LLEventDispatcher") << desc << ": bad request: " << mismatch << LL_ENDL;
|
|
}
|
|
// Event syntax looks good, go for it!
|
|
mFunc(event);
|
|
}
|
|
|
|
virtual LLSD addMetadata(LLSD meta) const
|
|
{
|
|
meta["required"] = mRequired;
|
|
return meta;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* DispatchEntry subclass for passing LLSD to functions accepting
|
|
* arbitrary argument types (convertible via LLSDParam)
|
|
*/
|
|
struct LLEventDispatcher::ParamsDispatchEntry: public LLEventDispatcher::DispatchEntry
|
|
{
|
|
ParamsDispatchEntry(const std::string& desc, const invoker_function& func):
|
|
DispatchEntry(desc),
|
|
mInvoker(func)
|
|
{}
|
|
|
|
invoker_function mInvoker;
|
|
|
|
virtual void call(const std::string& desc, const LLSD& event) const
|
|
{
|
|
LLSDArgsSource src(desc, event);
|
|
mInvoker(std::bind(&LLSDArgsSource::next, std::ref(src)));
|
|
}
|
|
};
|
|
|
|
/**
|
|
* DispatchEntry subclass for dispatching LLSD::Array to functions accepting
|
|
* arbitrary argument types (convertible via LLSDParam)
|
|
*/
|
|
struct LLEventDispatcher::ArrayParamsDispatchEntry: public LLEventDispatcher::ParamsDispatchEntry
|
|
{
|
|
ArrayParamsDispatchEntry(const std::string& desc, const invoker_function& func,
|
|
LLSD::Integer arity):
|
|
ParamsDispatchEntry(desc, func),
|
|
mArity(arity)
|
|
{}
|
|
|
|
LLSD::Integer mArity;
|
|
|
|
virtual LLSD addMetadata(LLSD meta) const
|
|
{
|
|
LLSD array(LLSD::emptyArray());
|
|
// Resize to number of arguments required
|
|
if (mArity)
|
|
array[mArity - 1] = LLSD();
|
|
llassert_always(array.size() == mArity);
|
|
meta["required"] = array;
|
|
return meta;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* DispatchEntry subclass for dispatching LLSD::Map to functions accepting
|
|
* arbitrary argument types (convertible via LLSDParam)
|
|
*/
|
|
struct LLEventDispatcher::MapParamsDispatchEntry: public LLEventDispatcher::ParamsDispatchEntry
|
|
{
|
|
MapParamsDispatchEntry(const std::string& name, const std::string& desc,
|
|
const invoker_function& func,
|
|
const LLSD& params, const LLSD& defaults):
|
|
ParamsDispatchEntry(desc, func),
|
|
mMapper(name, params, defaults),
|
|
mRequired(LLSD::emptyMap())
|
|
{
|
|
// Build the set of all param keys, then delete the ones that are
|
|
// optional. What's left are the ones that are required.
|
|
for (auto const& entry : params.array())
|
|
{
|
|
mRequired[entry.asString()] = LLSD();
|
|
}
|
|
|
|
if (defaults.isArray() || defaults.isUndefined())
|
|
{
|
|
// Right-align the params and defaults arrays.
|
|
LLSD::Integer offset = params.size() - defaults.size();
|
|
// Now the name of every defaults[i] is at params[i + offset].
|
|
for (LLSD::Integer i(0), iend(defaults.size()); i < iend; ++i)
|
|
{
|
|
// Erase this optional param from mRequired.
|
|
mRequired.erase(params[i + offset].asString());
|
|
// Instead, make an entry in mOptional with the default
|
|
// param's name and value.
|
|
mOptional[params[i + offset].asString()] = defaults[i];
|
|
}
|
|
}
|
|
else if (defaults.isMap())
|
|
{
|
|
// if defaults is already a map, then it's already in the form we
|
|
// intend to deliver in metadata
|
|
mOptional = defaults;
|
|
// Just delete from mRequired every key appearing in mOptional.
|
|
for (LLSD::map_const_iterator mi(mOptional.beginMap()), mend(mOptional.endMap());
|
|
mi != mend; ++mi)
|
|
{
|
|
mRequired.erase(mi->first);
|
|
}
|
|
}
|
|
}
|
|
|
|
LLSDArgsMapper mMapper;
|
|
LLSD mRequired;
|
|
LLSD mOptional;
|
|
|
|
virtual void call(const std::string& desc, const LLSD& event) const
|
|
{
|
|
// Just convert from LLSD::Map to LLSD::Array using mMapper, then pass
|
|
// to base-class call() method.
|
|
ParamsDispatchEntry::call(desc, mMapper.map(event));
|
|
}
|
|
|
|
virtual LLSD addMetadata(LLSD meta) const
|
|
{
|
|
meta["required"] = mRequired;
|
|
meta["optional"] = mOptional;
|
|
return meta;
|
|
}
|
|
};
|
|
|
|
void LLEventDispatcher::addArrayParamsDispatchEntry(const std::string& name,
|
|
const std::string& desc,
|
|
const invoker_function& invoker,
|
|
LLSD::Integer arity)
|
|
{
|
|
mDispatch.insert(
|
|
DispatchMap::value_type(name, DispatchMap::mapped_type(
|
|
new ArrayParamsDispatchEntry(desc, invoker, arity))));
|
|
}
|
|
|
|
void LLEventDispatcher::addMapParamsDispatchEntry(const std::string& name,
|
|
const std::string& desc,
|
|
const invoker_function& invoker,
|
|
const LLSD& params,
|
|
const LLSD& defaults)
|
|
{
|
|
mDispatch.insert(
|
|
DispatchMap::value_type(name, DispatchMap::mapped_type(
|
|
new MapParamsDispatchEntry(name, desc, invoker, params, defaults))));
|
|
}
|
|
|
|
/// Register a callable by name
|
|
void LLEventDispatcher::add(const std::string& name, const std::string& desc,
|
|
const Callable& callable, const LLSD& required)
|
|
{
|
|
mDispatch.insert(
|
|
DispatchMap::value_type(name, DispatchMap::mapped_type(
|
|
new LLSDDispatchEntry(desc, callable, required))));
|
|
}
|
|
|
|
void LLEventDispatcher::addFail(const std::string& name, const std::string& classname) const
|
|
{
|
|
LL_ERRS("LLEventDispatcher") << "LLEventDispatcher(" << mDesc << ")::add(" << name
|
|
<< "): " << classname << " is not a subclass "
|
|
<< "of LLEventDispatcher" << LL_ENDL;
|
|
}
|
|
|
|
/// Unregister a callable
|
|
bool LLEventDispatcher::remove(const std::string& name)
|
|
{
|
|
DispatchMap::iterator found = mDispatch.find(name);
|
|
if (found == mDispatch.end())
|
|
{
|
|
return false;
|
|
}
|
|
mDispatch.erase(found);
|
|
return true;
|
|
}
|
|
|
|
/// Call a registered callable with an explicitly-specified name. If no
|
|
/// such callable exists, die with LL_ERRS.
|
|
void LLEventDispatcher::operator()(const std::string& name, const LLSD& event) const
|
|
{
|
|
if (! try_call(name, event))
|
|
{
|
|
LL_ERRS("LLEventDispatcher") << "LLEventDispatcher(" << mDesc << "): '" << name
|
|
<< "' not found" << LL_ENDL;
|
|
}
|
|
}
|
|
|
|
/// Extract the @a key value from the incoming @a event, and call the
|
|
/// callable whose name is specified by that map @a key. If no such
|
|
/// callable exists, die with LL_ERRS.
|
|
void LLEventDispatcher::operator()(const LLSD& event) const
|
|
{
|
|
// This could/should be implemented in terms of the two-arg overload.
|
|
// However -- we can produce a more informative error message.
|
|
std::string name(event[mKey]);
|
|
if (! try_call(name, event))
|
|
{
|
|
LL_ERRS("LLEventDispatcher") << "LLEventDispatcher(" << mDesc << "): bad " << mKey
|
|
<< " value '" << name << "'" << LL_ENDL;
|
|
}
|
|
}
|
|
|
|
bool LLEventDispatcher::try_call(const LLSD& event) const
|
|
{
|
|
return try_call(event[mKey], event);
|
|
}
|
|
|
|
bool LLEventDispatcher::try_call(const std::string& name, const LLSD& event) const
|
|
{
|
|
DispatchMap::const_iterator found = mDispatch.find(name);
|
|
if (found == mDispatch.end())
|
|
{
|
|
return false;
|
|
}
|
|
// Found the name, so it's plausible to even attempt the call.
|
|
found->second->call(STRINGIZE("LLEventDispatcher(" << mDesc << ") calling '" << name << "'"),
|
|
event);
|
|
return true; // tell caller we were able to call
|
|
}
|
|
|
|
LLSD LLEventDispatcher::getMetadata(const std::string& name) const
|
|
{
|
|
DispatchMap::const_iterator found = mDispatch.find(name);
|
|
if (found == mDispatch.end())
|
|
{
|
|
return LLSD();
|
|
}
|
|
LLSD meta;
|
|
meta["name"] = name;
|
|
meta["desc"] = found->second->mDesc;
|
|
return found->second->addMetadata(meta);
|
|
}
|
|
|
|
LLDispatchListener::LLDispatchListener(const std::string& pumpname, const std::string& key):
|
|
LLEventDispatcher(pumpname, key),
|
|
mPump(pumpname, true), // allow tweaking for uniqueness
|
|
mBoundListener(mPump.listen("self", boost::bind(&LLDispatchListener::process, this, _1)))
|
|
{
|
|
}
|
|
|
|
bool LLDispatchListener::process(const LLSD& event)
|
|
{
|
|
(*this)(event);
|
|
return false;
|
|
}
|
|
|
|
LLEventDispatcher::DispatchEntry::DispatchEntry(const std::string& desc):
|
|
mDesc(desc)
|
|
{}
|
|
|