Initial moap commit. /VERY/ WIP. Primarily committed to clean up unstaged changes. Do not run this, even if it may compile, as it will NOT work (for a myriad of reasons)!
This commit is contained in:
@@ -76,6 +76,7 @@ set(llcommon_SOURCE_FILES
|
||||
llrun.cpp
|
||||
llscopedvolatileaprpool.h
|
||||
llsd.cpp
|
||||
llsdparam.cpp
|
||||
llsdserialize.cpp
|
||||
llsdserialize_xml.cpp
|
||||
llsdutil.cpp
|
||||
@@ -204,10 +205,11 @@ set(llcommon_HEADER_FILES
|
||||
llqueuedthread.h
|
||||
llrand.h
|
||||
llrefcount.h
|
||||
llrefcount.h
|
||||
llregistry.h
|
||||
llrun.h
|
||||
llsafehandle.h
|
||||
llsd.h
|
||||
llsdparam.h
|
||||
llsdserialize.h
|
||||
llsdserialize_xml.h
|
||||
llsdutil.h
|
||||
|
||||
356
indra/llcommon/llregistry.h
Normal file
356
indra/llcommon/llregistry.h
Normal file
@@ -0,0 +1,356 @@
|
||||
/**
|
||||
* @file llregistry.h
|
||||
* @brief template classes for registering name, value pairs in nested scopes, statically, etc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&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$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLREGISTRY_H
|
||||
#define LL_LLREGISTRY_H
|
||||
|
||||
#include <list>
|
||||
|
||||
#include <boost/type_traits.hpp>
|
||||
#include "llsingleton.h"
|
||||
#include "llstl.h"
|
||||
|
||||
template <typename T>
|
||||
struct LLRegistryDefaultComparator
|
||||
{
|
||||
bool operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
using std::less;
|
||||
return less<T>()(lhs, rhs);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename KEY, typename VALUE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
|
||||
class LLRegistry
|
||||
{
|
||||
public:
|
||||
typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t;
|
||||
typedef typename boost::add_reference<typename boost::add_const<KEY>::type>::type ref_const_key_t;
|
||||
typedef typename boost::add_reference<typename boost::add_const<VALUE>::type>::type ref_const_value_t;
|
||||
typedef typename boost::add_reference<VALUE>::type ref_value_t;
|
||||
typedef typename boost::add_pointer<typename boost::add_const<VALUE>::type>::type ptr_const_value_t;
|
||||
typedef typename boost::add_pointer<VALUE>::type ptr_value_t;
|
||||
|
||||
class Registrar
|
||||
{
|
||||
friend class LLRegistry<KEY, VALUE, COMPARATOR>;
|
||||
public:
|
||||
typedef std::map<KEY, VALUE, COMPARATOR> registry_map_t;
|
||||
|
||||
bool add(ref_const_key_t key, ref_const_value_t value)
|
||||
{
|
||||
if (mMap.insert(std::make_pair(key, value)).second == false)
|
||||
{
|
||||
llwarns << "Tried to register " << key << " but it was already registered!" << llendl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void remove(ref_const_key_t key)
|
||||
{
|
||||
mMap.erase(key);
|
||||
}
|
||||
|
||||
void replace(ref_const_key_t key, ref_const_value_t value)
|
||||
{
|
||||
mMap[key] = value;
|
||||
}
|
||||
|
||||
typename registry_map_t::const_iterator beginItems() const
|
||||
{
|
||||
return mMap.begin();
|
||||
}
|
||||
|
||||
typename registry_map_t::const_iterator endItems() const
|
||||
{
|
||||
return mMap.end();
|
||||
}
|
||||
|
||||
protected:
|
||||
ptr_value_t getValue(ref_const_key_t key)
|
||||
{
|
||||
typename registry_map_t::iterator found_it = mMap.find(key);
|
||||
if (found_it != mMap.end())
|
||||
{
|
||||
return &(found_it->second);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr_const_value_t getValue(ref_const_key_t key) const
|
||||
{
|
||||
typename registry_map_t::const_iterator found_it = mMap.find(key);
|
||||
if (found_it != mMap.end())
|
||||
{
|
||||
return &(found_it->second);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// if the registry is used to store pointers, and null values are valid entries
|
||||
// then use this function to check the existence of an entry
|
||||
bool exists(ref_const_key_t key) const
|
||||
{
|
||||
return mMap.find(key) != mMap.end();
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return mMap.empty();
|
||||
}
|
||||
|
||||
protected:
|
||||
// use currentRegistrar() or defaultRegistrar()
|
||||
Registrar() {}
|
||||
~Registrar() {}
|
||||
|
||||
private:
|
||||
registry_map_t mMap;
|
||||
};
|
||||
|
||||
typedef typename std::list<Registrar*> scope_list_t;
|
||||
typedef typename std::list<Registrar*>::iterator scope_list_iterator_t;
|
||||
typedef typename std::list<Registrar*>::const_iterator scope_list_const_iterator_t;
|
||||
|
||||
LLRegistry()
|
||||
{}
|
||||
|
||||
~LLRegistry() {}
|
||||
|
||||
ptr_value_t getValue(ref_const_key_t key)
|
||||
{
|
||||
for(scope_list_iterator_t it = mActiveScopes.begin();
|
||||
it != mActiveScopes.end();
|
||||
++it)
|
||||
{
|
||||
ptr_value_t valuep = (*it)->getValue(key);
|
||||
if (valuep != NULL) return valuep;
|
||||
}
|
||||
return mDefaultRegistrar.getValue(key);
|
||||
}
|
||||
|
||||
ptr_const_value_t getValue(ref_const_key_t key) const
|
||||
{
|
||||
for(scope_list_const_iterator_t it = mActiveScopes.begin();
|
||||
it != mActiveScopes.end();
|
||||
++it)
|
||||
{
|
||||
ptr_value_t valuep = (*it)->getValue(key);
|
||||
if (valuep != NULL) return valuep;
|
||||
}
|
||||
return mDefaultRegistrar.getValue(key);
|
||||
}
|
||||
|
||||
bool exists(ref_const_key_t key) const
|
||||
{
|
||||
for(scope_list_const_iterator_t it = mActiveScopes.begin();
|
||||
it != mActiveScopes.end();
|
||||
++it)
|
||||
{
|
||||
if ((*it)->exists(key)) return true;
|
||||
}
|
||||
|
||||
return mDefaultRegistrar.exists(key);
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
for(scope_list_const_iterator_t it = mActiveScopes.begin();
|
||||
it != mActiveScopes.end();
|
||||
++it)
|
||||
{
|
||||
if (!(*it)->empty()) return false;
|
||||
}
|
||||
|
||||
return mDefaultRegistrar.empty();
|
||||
}
|
||||
|
||||
|
||||
Registrar& defaultRegistrar()
|
||||
{
|
||||
return mDefaultRegistrar;
|
||||
}
|
||||
|
||||
const Registrar& defaultRegistrar() const
|
||||
{
|
||||
return mDefaultRegistrar;
|
||||
}
|
||||
|
||||
|
||||
Registrar& currentRegistrar()
|
||||
{
|
||||
if (!mActiveScopes.empty())
|
||||
{
|
||||
return *mActiveScopes.front();
|
||||
}
|
||||
|
||||
return mDefaultRegistrar;
|
||||
}
|
||||
|
||||
const Registrar& currentRegistrar() const
|
||||
{
|
||||
if (!mActiveScopes.empty())
|
||||
{
|
||||
return *mActiveScopes.front();
|
||||
}
|
||||
|
||||
return mDefaultRegistrar;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
void addScope(Registrar* scope)
|
||||
{
|
||||
// newer scopes go up front
|
||||
mActiveScopes.insert(mActiveScopes.begin(), scope);
|
||||
}
|
||||
|
||||
void removeScope(Registrar* scope)
|
||||
{
|
||||
// O(N) but should be near the beggining and N should be small and this is safer than storing iterators
|
||||
scope_list_iterator_t iter = std::find(mActiveScopes.begin(), mActiveScopes.end(), scope);
|
||||
if (iter != mActiveScopes.end())
|
||||
{
|
||||
mActiveScopes.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
scope_list_t mActiveScopes;
|
||||
Registrar mDefaultRegistrar;
|
||||
};
|
||||
|
||||
template <typename KEY, typename VALUE, typename DERIVED_TYPE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
|
||||
class LLRegistrySingleton
|
||||
: public LLRegistry<KEY, VALUE, COMPARATOR>,
|
||||
public LLSingleton<DERIVED_TYPE>
|
||||
{
|
||||
friend class LLSingleton<DERIVED_TYPE>;
|
||||
public:
|
||||
typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t;
|
||||
typedef const KEY& ref_const_key_t;
|
||||
typedef const VALUE& ref_const_value_t;
|
||||
typedef VALUE* ptr_value_t;
|
||||
typedef const VALUE* ptr_const_value_t;
|
||||
typedef LLSingleton<DERIVED_TYPE> singleton_t;
|
||||
|
||||
class ScopedRegistrar : public registry_t::Registrar
|
||||
{
|
||||
public:
|
||||
ScopedRegistrar(bool push_scope = true)
|
||||
{
|
||||
if (push_scope)
|
||||
{
|
||||
pushScope();
|
||||
}
|
||||
}
|
||||
|
||||
~ScopedRegistrar()
|
||||
{
|
||||
if (!singleton_t::destroyed())
|
||||
{
|
||||
popScope();
|
||||
}
|
||||
}
|
||||
|
||||
void pushScope()
|
||||
{
|
||||
singleton_t::instance().addScope(this);
|
||||
}
|
||||
|
||||
void popScope()
|
||||
{
|
||||
singleton_t::instance().removeScope(this);
|
||||
}
|
||||
|
||||
ptr_value_t getValueFromScope(ref_const_key_t key)
|
||||
{
|
||||
return getValue(key);
|
||||
}
|
||||
|
||||
ptr_const_value_t getValueFromScope(ref_const_key_t key) const
|
||||
{
|
||||
return getValue(key);
|
||||
}
|
||||
|
||||
private:
|
||||
typename std::list<typename registry_t::Registrar*>::iterator mListIt;
|
||||
};
|
||||
|
||||
class StaticRegistrar : public registry_t::Registrar
|
||||
{
|
||||
public:
|
||||
virtual ~StaticRegistrar() {}
|
||||
StaticRegistrar(ref_const_key_t key, ref_const_value_t value)
|
||||
{
|
||||
singleton_t::instance().mStaticScope->add(key, value);
|
||||
}
|
||||
};
|
||||
|
||||
// convenience functions
|
||||
typedef typename LLRegistry<KEY, VALUE, COMPARATOR>::Registrar& ref_registrar_t;
|
||||
static ref_registrar_t currentRegistrar()
|
||||
{
|
||||
return singleton_t::instance().registry_t::currentRegistrar();
|
||||
}
|
||||
|
||||
static ref_registrar_t defaultRegistrar()
|
||||
{
|
||||
return singleton_t::instance().registry_t::defaultRegistrar();
|
||||
}
|
||||
|
||||
static ptr_value_t getValue(ref_const_key_t key)
|
||||
{
|
||||
return singleton_t::instance().registry_t::getValue(key);
|
||||
}
|
||||
|
||||
protected:
|
||||
// DERIVED_TYPE needs to derive from LLRegistrySingleton
|
||||
LLRegistrySingleton()
|
||||
: mStaticScope(NULL)
|
||||
{}
|
||||
|
||||
virtual void initSingleton()
|
||||
{
|
||||
mStaticScope = new ScopedRegistrar();
|
||||
}
|
||||
|
||||
virtual ~LLRegistrySingleton()
|
||||
{
|
||||
delete mStaticScope;
|
||||
}
|
||||
|
||||
private:
|
||||
ScopedRegistrar* mStaticScope;
|
||||
};
|
||||
|
||||
// helper macro for doing static registration
|
||||
#define GLUED_TOKEN(x, y) x ## y
|
||||
#define GLUE_TOKENS(x, y) GLUED_TOKEN(x, y)
|
||||
#define LLREGISTER_STATIC(REGISTRY, KEY, VALUE) static REGISTRY::StaticRegistrar GLUE_TOKENS(reg, __LINE__)(KEY, VALUE);
|
||||
|
||||
#endif
|
||||
342
indra/llcommon/llsdparam.cpp
Normal file
342
indra/llcommon/llsdparam.cpp
Normal file
@@ -0,0 +1,342 @@
|
||||
/**
|
||||
* @file llsdparam.cpp
|
||||
* @brief parameter block abstraction for creating complex objects and
|
||||
* parsing construction parameters from xml and LLSD
|
||||
*
|
||||
* $LicenseInfo:firstyear=2008&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$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
// Project includes
|
||||
#include "llsdparam.h"
|
||||
#include "llsdutil.h"
|
||||
|
||||
static LLInitParam::Parser::parser_read_func_map_t sReadFuncs;
|
||||
static LLInitParam::Parser::parser_write_func_map_t sWriteFuncs;
|
||||
static LLInitParam::Parser::parser_inspect_func_map_t sInspectFuncs;
|
||||
static const LLSD NO_VALUE_MARKER;
|
||||
|
||||
LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR("LLSD to LLInitParam conversion");
|
||||
|
||||
//
|
||||
// LLParamSDParser
|
||||
//
|
||||
LLParamSDParser::LLParamSDParser()
|
||||
: Parser(sReadFuncs, sWriteFuncs, sInspectFuncs)
|
||||
{
|
||||
using boost::bind;
|
||||
|
||||
if (sReadFuncs.empty())
|
||||
{
|
||||
registerParserFuncs<LLInitParam::Flag>(readFlag, &LLParamSDParser::writeFlag);
|
||||
registerParserFuncs<S32>(readS32, &LLParamSDParser::writeTypedValue<S32>);
|
||||
registerParserFuncs<U32>(readU32, &LLParamSDParser::writeU32Param);
|
||||
registerParserFuncs<F32>(readF32, &LLParamSDParser::writeTypedValue<F32>);
|
||||
registerParserFuncs<F64>(readF64, &LLParamSDParser::writeTypedValue<F64>);
|
||||
registerParserFuncs<bool>(readBool, &LLParamSDParser::writeTypedValue<bool>);
|
||||
registerParserFuncs<std::string>(readString, &LLParamSDParser::writeTypedValue<std::string>);
|
||||
registerParserFuncs<LLUUID>(readUUID, &LLParamSDParser::writeTypedValue<LLUUID>);
|
||||
registerParserFuncs<LLDate>(readDate, &LLParamSDParser::writeTypedValue<LLDate>);
|
||||
registerParserFuncs<LLURI>(readURI, &LLParamSDParser::writeTypedValue<LLURI>);
|
||||
registerParserFuncs<LLSD>(readSD, &LLParamSDParser::writeTypedValue<LLSD>);
|
||||
}
|
||||
}
|
||||
|
||||
// special case handling of U32 due to ambiguous LLSD::assign overload
|
||||
bool LLParamSDParser::writeU32Param(LLParamSDParser::parser_t& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
|
||||
{
|
||||
LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
|
||||
if (!sdparser.mWriteRootSD) return false;
|
||||
|
||||
parser_t::name_stack_range_t range(name_stack.begin(), name_stack.end());
|
||||
LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
|
||||
sd_to_write.assign((S32)*((const U32*)val_ptr));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLParamSDParser::writeFlag(LLParamSDParser::parser_t& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
|
||||
{
|
||||
LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
|
||||
if (!sdparser.mWriteRootSD) return false;
|
||||
|
||||
parser_t::name_stack_range_t range(name_stack.begin(), name_stack.end());
|
||||
LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLParamSDParser::submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack)
|
||||
{
|
||||
mCurReadSD = &sd;
|
||||
block.submitValue(name_stack, *this);
|
||||
}
|
||||
|
||||
void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent)
|
||||
{
|
||||
mCurReadSD = NULL;
|
||||
mNameStack.clear();
|
||||
setParseSilently(silent);
|
||||
|
||||
LLParamSDParserUtilities::readSDValues(boost::bind(&LLParamSDParser::submit, this, boost::ref(block), _1, _2), sd, mNameStack);
|
||||
//readSDValues(sd, block);
|
||||
}
|
||||
|
||||
void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block)
|
||||
{
|
||||
mNameStack.clear();
|
||||
mWriteRootSD = &sd;
|
||||
|
||||
name_stack_t name_stack;
|
||||
block.serializeBlock(*this, name_stack);
|
||||
}
|
||||
|
||||
/*virtual*/ std::string LLParamSDParser::getCurrentElementName()
|
||||
{
|
||||
std::string full_name = "sd";
|
||||
for (name_stack_t::iterator it = mNameStack.begin();
|
||||
it != mNameStack.end();
|
||||
++it)
|
||||
{
|
||||
full_name += llformat("[%s]", it->first.c_str());
|
||||
}
|
||||
|
||||
return full_name;
|
||||
}
|
||||
|
||||
|
||||
bool LLParamSDParser::readFlag(Parser& parser, void* val_ptr)
|
||||
{
|
||||
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
|
||||
return self.mCurReadSD == &NO_VALUE_MARKER;
|
||||
}
|
||||
|
||||
|
||||
bool LLParamSDParser::readS32(Parser& parser, void* val_ptr)
|
||||
{
|
||||
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
|
||||
|
||||
*((S32*)val_ptr) = self.mCurReadSD->asInteger();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLParamSDParser::readU32(Parser& parser, void* val_ptr)
|
||||
{
|
||||
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
|
||||
|
||||
*((U32*)val_ptr) = self.mCurReadSD->asInteger();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLParamSDParser::readF32(Parser& parser, void* val_ptr)
|
||||
{
|
||||
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
|
||||
|
||||
*((F32*)val_ptr) = self.mCurReadSD->asReal();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLParamSDParser::readF64(Parser& parser, void* val_ptr)
|
||||
{
|
||||
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
|
||||
|
||||
*((F64*)val_ptr) = self.mCurReadSD->asReal();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLParamSDParser::readBool(Parser& parser, void* val_ptr)
|
||||
{
|
||||
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
|
||||
|
||||
*((bool*)val_ptr) = self.mCurReadSD->asBoolean();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLParamSDParser::readString(Parser& parser, void* val_ptr)
|
||||
{
|
||||
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
|
||||
|
||||
*((std::string*)val_ptr) = self.mCurReadSD->asString();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLParamSDParser::readUUID(Parser& parser, void* val_ptr)
|
||||
{
|
||||
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
|
||||
|
||||
*((LLUUID*)val_ptr) = self.mCurReadSD->asUUID();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLParamSDParser::readDate(Parser& parser, void* val_ptr)
|
||||
{
|
||||
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
|
||||
|
||||
*((LLDate*)val_ptr) = self.mCurReadSD->asDate();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLParamSDParser::readURI(Parser& parser, void* val_ptr)
|
||||
{
|
||||
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
|
||||
|
||||
*((LLURI*)val_ptr) = self.mCurReadSD->asURI();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLParamSDParser::readSD(Parser& parser, void* val_ptr)
|
||||
{
|
||||
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
|
||||
|
||||
*((LLSD*)val_ptr) = *self.mCurReadSD;
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range)
|
||||
{
|
||||
LLSD* sd_to_write = &input;
|
||||
|
||||
for (LLInitParam::Parser::name_stack_t::iterator it = name_stack_range.first;
|
||||
it != name_stack_range.second;
|
||||
++it)
|
||||
{
|
||||
bool new_traversal = it->second;
|
||||
|
||||
LLSD* child_sd = it->first.empty() ? sd_to_write : &(*sd_to_write)[it->first];
|
||||
|
||||
if (child_sd->isArray())
|
||||
{
|
||||
if (new_traversal)
|
||||
{
|
||||
// write to new element at end
|
||||
sd_to_write = &(*child_sd)[child_sd->size()];
|
||||
}
|
||||
else
|
||||
{
|
||||
// write to last of existing elements, or first element if empty
|
||||
sd_to_write = &(*child_sd)[llmax(0, child_sd->size() - 1)];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (new_traversal
|
||||
&& child_sd->isDefined()
|
||||
&& !child_sd->isArray())
|
||||
{
|
||||
// copy child contents into first element of an array
|
||||
LLSD new_array = LLSD::emptyArray();
|
||||
new_array.append(*child_sd);
|
||||
// assign array to slot that previously held the single value
|
||||
*child_sd = new_array;
|
||||
// return next element in that array
|
||||
sd_to_write = &((*child_sd)[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
sd_to_write = child_sd;
|
||||
}
|
||||
}
|
||||
it->second = false;
|
||||
}
|
||||
|
||||
return *sd_to_write;
|
||||
}
|
||||
|
||||
//static
|
||||
void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack)
|
||||
{
|
||||
if (sd.isMap())
|
||||
{
|
||||
for (LLSD::map_const_iterator it = sd.beginMap();
|
||||
it != sd.endMap();
|
||||
++it)
|
||||
{
|
||||
stack.push_back(make_pair(it->first, true));
|
||||
readSDValues(cb, it->second, stack);
|
||||
stack.pop_back();
|
||||
}
|
||||
}
|
||||
else if (sd.isArray())
|
||||
{
|
||||
for (LLSD::array_const_iterator it = sd.beginArray();
|
||||
it != sd.endArray();
|
||||
++it)
|
||||
{
|
||||
stack.back().second = true;
|
||||
readSDValues(cb, *it, stack);
|
||||
}
|
||||
}
|
||||
else if (sd.isUndefined())
|
||||
{
|
||||
if (!cb.empty())
|
||||
{
|
||||
cb(NO_VALUE_MARKER, stack);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!cb.empty())
|
||||
{
|
||||
cb(sd, stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd)
|
||||
{
|
||||
LLInitParam::Parser::name_stack_t stack = LLInitParam::Parser::name_stack_t();
|
||||
readSDValues(cb, sd, stack);
|
||||
}
|
||||
namespace LLInitParam
|
||||
{
|
||||
// LLSD specialization
|
||||
// block param interface
|
||||
bool ParamValue<LLSD, TypeValues<LLSD>, false>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name)
|
||||
{
|
||||
LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack);
|
||||
|
||||
LLSD::String string;
|
||||
|
||||
if (p.readValue<LLSD::String>(string))
|
||||
{
|
||||
sd = string;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//static
|
||||
void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack)
|
||||
{
|
||||
p.writeValue<LLSD::String>(sd.asString(), name_stack);
|
||||
}
|
||||
|
||||
void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const
|
||||
{
|
||||
// read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc)
|
||||
Parser::name_stack_t stack;
|
||||
LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, stack);
|
||||
}
|
||||
}
|
||||
126
indra/llcommon/llsdparam.h
Normal file
126
indra/llcommon/llsdparam.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* @file llsdparam.h
|
||||
* @brief parameter block abstraction for creating complex objects and
|
||||
* parsing construction parameters from xml and LLSD
|
||||
*
|
||||
* $LicenseInfo:firstyear=2008&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$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLSDPARAM_H
|
||||
#define LL_LLSDPARAM_H
|
||||
|
||||
#include "llinitparam.h"
|
||||
#include "boost/function.hpp"
|
||||
|
||||
struct LL_COMMON_API LLParamSDParserUtilities
|
||||
{
|
||||
static LLSD& getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range);
|
||||
|
||||
typedef boost::function<void (const LLSD&, LLInitParam::Parser::name_stack_t&)> read_sd_cb_t;
|
||||
static void readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack);
|
||||
static void readSDValues(read_sd_cb_t cb, const LLSD& sd);
|
||||
};
|
||||
|
||||
class LL_COMMON_API LLParamSDParser
|
||||
: public LLInitParam::Parser
|
||||
{
|
||||
LOG_CLASS(LLParamSDParser);
|
||||
|
||||
typedef LLInitParam::Parser parser_t;
|
||||
|
||||
public:
|
||||
LLParamSDParser();
|
||||
void readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent = false);
|
||||
void writeSD(LLSD& sd, const LLInitParam::BaseBlock& block);
|
||||
|
||||
/*virtual*/ std::string getCurrentElementName();
|
||||
|
||||
private:
|
||||
void submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack);
|
||||
|
||||
template<typename T>
|
||||
static bool writeTypedValue(Parser& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
|
||||
{
|
||||
LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
|
||||
if (!sdparser.mWriteRootSD) return false;
|
||||
|
||||
LLInitParam::Parser::name_stack_range_t range(name_stack.begin(), name_stack.end());
|
||||
LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
|
||||
|
||||
sd_to_write.assign(*((const T*)val_ptr));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool writeU32Param(Parser& parser, const void* value_ptr, parser_t::name_stack_t& name_stack);
|
||||
static bool writeFlag(Parser& parser, const void* value_ptr, parser_t::name_stack_t& name_stack);
|
||||
|
||||
static bool readFlag(Parser& parser, void* val_ptr);
|
||||
static bool readS32(Parser& parser, void* val_ptr);
|
||||
static bool readU32(Parser& parser, void* val_ptr);
|
||||
static bool readF32(Parser& parser, void* val_ptr);
|
||||
static bool readF64(Parser& parser, void* val_ptr);
|
||||
static bool readBool(Parser& parser, void* val_ptr);
|
||||
static bool readString(Parser& parser, void* val_ptr);
|
||||
static bool readUUID(Parser& parser, void* val_ptr);
|
||||
static bool readDate(Parser& parser, void* val_ptr);
|
||||
static bool readURI(Parser& parser, void* val_ptr);
|
||||
static bool readSD(Parser& parser, void* val_ptr);
|
||||
|
||||
Parser::name_stack_t mNameStack;
|
||||
const LLSD* mCurReadSD;
|
||||
LLSD* mWriteRootSD;
|
||||
LLSD* mCurWriteSD;
|
||||
};
|
||||
|
||||
|
||||
extern LL_COMMON_API LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR;
|
||||
template<typename T>
|
||||
class LLSDParamAdapter : public T
|
||||
{
|
||||
public:
|
||||
LLSDParamAdapter() {}
|
||||
LLSDParamAdapter(const LLSD& sd)
|
||||
{
|
||||
LLFastTimer _(FTM_SD_PARAM_ADAPTOR);
|
||||
LLParamSDParser parser;
|
||||
// don't spam for implicit parsing of LLSD, as we want to allow arbitrary freeform data and ignore most of it
|
||||
bool parse_silently = true;
|
||||
parser.readSD(sd, *this, parse_silently);
|
||||
}
|
||||
|
||||
operator LLSD() const
|
||||
{
|
||||
LLParamSDParser parser;
|
||||
LLSD sd;
|
||||
parser.writeSD(sd, *this);
|
||||
return sd;
|
||||
}
|
||||
|
||||
LLSDParamAdapter(const T& val)
|
||||
: T(val)
|
||||
{
|
||||
T::operator=(val);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // LL_LLSDPARAM_H
|
||||
|
||||
@@ -45,44 +45,49 @@ const std::string AUCTION_URL (
|
||||
const std::string EVENTS_URL (
|
||||
"http://secondlife.com/events/");
|
||||
|
||||
/*
|
||||
const std::string TIER_UP_URL (
|
||||
"http://secondlife.com/app/landtier");
|
||||
|
||||
const std::string LAND_URL (
|
||||
"http://secondlife.com/app/landtier");
|
||||
|
||||
const std::string UPGRADE_TO_PREMIUM_URL (
|
||||
"http://secondlife.com/app/upgrade/");
|
||||
"http://secondlife.com/app/landtier"); // *TODO: NOT USED
|
||||
*/
|
||||
|
||||
const std::string DIRECTX_9_URL (
|
||||
"http://secondlife.com/support/");
|
||||
"http://secondlife.com/support/"); // *TODO: NOT USED
|
||||
/*
|
||||
const std::string LAND_URL (
|
||||
"http://secondlife.com/app/landtier"); // *TODO: NOT USED
|
||||
|
||||
const std::string UPGRADE_TO_PREMIUM_URL (
|
||||
"http://secondlife.com/app/upgrade/"); // *TODO: NOT USED
|
||||
|
||||
const std::string AMD_AGP_URL (
|
||||
"http://secondlife.com/support/");
|
||||
"http://secondlife.com/support/"); // *TODO: NOT USED
|
||||
|
||||
const std::string VIA_URL (
|
||||
"http://secondlife.com/support/");
|
||||
"http://secondlife.com/support/"); // *TODO: NOT USED
|
||||
|
||||
const std::string SUPPORT_URL (
|
||||
"http://secondlife.com/support/");
|
||||
|
||||
const std::string INTEL_CHIPSET_URL (
|
||||
"http://secondlife.com/support/");
|
||||
"http://secondlife.com/support/"); // *TODO: NOT USED
|
||||
|
||||
const std::string SIS_CHIPSET_URL (
|
||||
"http://secondlife.com/support/");
|
||||
"http://secondlife.com/support/"); // *TODO: NOT USED
|
||||
|
||||
const std::string BLOGS_URL (
|
||||
"http://blog.secondlife.com/");
|
||||
"http://blog.secondlife.com/"); // *TODO: NOT USED
|
||||
*/
|
||||
|
||||
const std::string BUY_CURRENCY_URL (
|
||||
"http://secondlife.com/app/currency/");
|
||||
|
||||
/*
|
||||
const std::string LSL_DOC_URL (
|
||||
"http://secondlife.com/app/lsldoc/");
|
||||
"http://secondlife.com/app/lsldoc/"); // *TODO: NOT USED
|
||||
|
||||
const std::string SL_KB_URL (
|
||||
"http://secondlife.com/knowledgebase/");
|
||||
"http://secondlife.com/knowledgebase/"); // *TODO: NOT USED
|
||||
|
||||
const std::string RELEASE_NOTES_BASE_URL (
|
||||
"http://ascent.balseraph.org/?");
|
||||
"http://secondlife.com/app/releasenotes/");
|
||||
*/
|
||||
|
||||
@@ -43,18 +43,22 @@ LL_COMMON_API extern const std::string AUCTION_URL;
|
||||
|
||||
LL_COMMON_API extern const std::string EVENTS_URL;
|
||||
|
||||
/*
|
||||
// Tier up to a new land level.
|
||||
LL_COMMON_API extern const std::string TIER_UP_URL;
|
||||
|
||||
// Tier up to a new land level.
|
||||
LL_COMMON_API extern const std::string LAND_URL;
|
||||
|
||||
// Upgrade from basic membership to premium membership
|
||||
LL_COMMON_API extern const std::string UPGRADE_TO_PREMIUM_URL;
|
||||
*/
|
||||
|
||||
// How to get DirectX 9
|
||||
LL_COMMON_API extern const std::string DIRECTX_9_URL;
|
||||
|
||||
/*
|
||||
// Upgrade from basic membership to premium membership
|
||||
LL_COMMON_API extern const std::string UPGRADE_TO_PREMIUM_URL;
|
||||
|
||||
|
||||
// Out of date VIA chipset
|
||||
LL_COMMON_API extern const std::string VIA_URL;
|
||||
|
||||
@@ -63,10 +67,12 @@ LL_COMMON_API extern const std::string SUPPORT_URL;
|
||||
|
||||
// Linden Blogs page
|
||||
LL_COMMON_API extern const std::string BLOGS_URL;
|
||||
*/
|
||||
|
||||
// Currency page
|
||||
LL_COMMON_API extern const std::string BUY_CURRENCY_URL;
|
||||
|
||||
/*
|
||||
// LSL script wiki
|
||||
LL_COMMON_API extern const std::string LSL_DOC_URL;
|
||||
|
||||
@@ -75,5 +81,5 @@ LL_COMMON_API extern const std::string SL_KB_URL;
|
||||
|
||||
// Release Notes Redirect URL for Server and Viewer
|
||||
LL_COMMON_API extern const std::string RELEASE_NOTES_BASE_URL;
|
||||
|
||||
*/
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user