LLViewerRegion WIP: Added all headers that are dragged in.
Most in particular llevents.h, which comes along with the demand that the old events in llevent.h are put in a namespace LLOldEvents. Made all changes necessary to compile the rest of the code again (without changing the actual code: it's still using the old events). This patch also removes LLStopWhenHandled and LLStandardSignal from indra/llui/llnotifications.h because those are moved to llevents.h. That seems to be the only change to indra/llui/llnotifications.h that isn't floater related, so I left the rest of that file alone.
This commit is contained in:
672
indra/llcommon/lleventdispatcher.cpp
Normal file
672
indra/llcommon/lleventdispatcher.cpp
Normal file
@@ -0,0 +1,672 @@
|
||||
/**
|
||||
* @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 (LLSD::array_const_iterator li(list.beginArray()), lend(list.endArray());
|
||||
li != lend; ++li)
|
||||
{
|
||||
out << delim << li->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(boost::bind(&LLSDArgsSource::next, boost::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 (LLSD::array_const_iterator pi(params.beginArray()), pend(params.endArray());
|
||||
pi != pend; ++pi)
|
||||
{
|
||||
mRequired[pi->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)
|
||||
{}
|
||||
|
||||
Reference in New Issue
Block a user