summaryrefslogtreecommitdiff
path: root/indra/llxuixml
diff options
context:
space:
mode:
authorTofu Linden <tofu.linden@lindenlab.com>2010-09-24 10:22:20 +0100
committerTofu Linden <tofu.linden@lindenlab.com>2010-09-24 10:22:20 +0100
commit8de8669f340179324f47668dbd9102ba4f8526bd (patch)
tree663f02ab3761092aec66682c139617f64a2407bc /indra/llxuixml
parent528964429633b5f878216ba0ffa80c69abc70205 (diff)
parentb25d969b61eb1e4f114ee0e632d1de9777780e9f (diff)
merge from viewer-development
Diffstat (limited to 'indra/llxuixml')
-rw-r--r--indra/llxuixml/llinitparam.cpp51
-rw-r--r--indra/llxuixml/llinitparam.h168
-rw-r--r--indra/llxuixml/llregistry.h5
-rw-r--r--indra/llxuixml/lltrans.cpp14
-rw-r--r--indra/llxuixml/llxuiparser.cpp656
-rw-r--r--indra/llxuixml/llxuiparser.h138
6 files changed, 789 insertions, 243 deletions
diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp
index 0b324a10c9..2c92539387 100644
--- a/indra/llxuixml/llinitparam.cpp
+++ b/indra/llxuixml/llinitparam.cpp
@@ -68,7 +68,6 @@ namespace LLInitParam
void BlockDescriptor::aggregateBlockData(BlockDescriptor& src_block_data)
{
mNamedParams.insert(src_block_data.mNamedParams.begin(), src_block_data.mNamedParams.end());
- mSynonyms.insert(src_block_data.mSynonyms.begin(), src_block_data.mSynonyms.end());
std::copy(src_block_data.mUnnamedParams.begin(), src_block_data.mUnnamedParams.end(), std::back_inserter(mUnnamedParams));
std::copy(src_block_data.mValidationList.begin(), src_block_data.mValidationList.end(), std::back_inserter(mValidationList));
std::copy(src_block_data.mAllParams.begin(), src_block_data.mAllParams.end(), std::back_inserter(mAllParams));
@@ -78,8 +77,7 @@ namespace LLInitParam
// BaseBlock
//
BaseBlock::BaseBlock()
- : mChangeVersion(0),
- mBlockDescriptor(NULL)
+ : mChangeVersion(0)
{}
BaseBlock::~BaseBlock()
@@ -88,8 +86,6 @@ namespace LLInitParam
// called by each derived class in least to most derived order
void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size)
{
- mBlockDescriptor = &descriptor;
-
descriptor.mCurrentBlockPtr = this;
descriptor.mMaxParamOffset = block_size;
@@ -182,7 +178,7 @@ namespace LLInitParam
param_handle_t param_handle = it->second->mParamHandle;
const Param* param = getParamFromHandle(param_handle);
ParamDescriptor::serialize_func_t serialize_func = it->second->mSerializeFunc;
- if (serialize_func)
+ if (serialize_func && param->anyProvided())
{
// Ensure this param has not already been serialized
// Prevents <rect> from being serialized as its own tag.
@@ -274,22 +270,6 @@ namespace LLInitParam
}
}
- for(BlockDescriptor::param_map_t::const_iterator it = block_data.mSynonyms.begin();
- it != block_data.mSynonyms.end();
- ++it)
- {
- param_handle_t param_handle = it->second->mParamHandle;
- const Param* param = getParamFromHandle(param_handle);
- ParamDescriptor::inspect_func_t inspect_func = it->second->mInspectFunc;
- if (inspect_func)
- {
- // use existing serial number for param
- name_stack.push_back(std::make_pair(it->first, it->second->mGeneration));
- inspect_func(*param, parser, name_stack, it->second->mMinCount, it->second->mMaxCount);
- name_stack.pop_back();
- }
- }
-
return true;
}
@@ -311,22 +291,9 @@ namespace LLInitParam
// find pointer to member parameter from offset table
paramp = getParamFromHandle(found_it->second->mParamHandle);
deserialize_func = found_it->second->mDeserializeFunc;
- }
- else
- {
- BlockDescriptor::param_map_t::iterator found_it = block_data.mSynonyms.find(top_name);
- if (found_it != block_data.mSynonyms.end())
- {
- // find pointer to member parameter from offset table
- paramp = getParamFromHandle(found_it->second->mParamHandle);
- deserialize_func = found_it->second->mDeserializeFunc;
- }
- }
- Parser::name_stack_range_t new_name_stack(name_stack.first, name_stack.second);
- ++new_name_stack.first;
- if (deserialize_func)
- {
+ Parser::name_stack_range_t new_name_stack(name_stack.first, name_stack.second);
+ ++new_name_stack.first;
return deserialize_func(*paramp, p, new_name_stack, name_stack.first == name_stack.second ? -1 : name_stack.first->second);
}
}
@@ -401,7 +368,7 @@ namespace LLInitParam
}
else
{
- block_data.mSynonyms[synonym] = param_descriptor;
+ block_data.mNamedParams[synonym] = param_descriptor;
}
}
}
@@ -426,14 +393,6 @@ namespace LLInitParam
}
}
- for (BlockDescriptor::param_map_t::const_iterator it = block_data.mSynonyms.begin(); it != block_data.mSynonyms.end(); ++it)
- {
- if (it->second->mParamHandle == handle)
- {
- return it->first;
- }
- }
-
return LLStringUtil::null;
}
diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h
index 869b0c2cd6..8cb5bd80fc 100644
--- a/indra/llxuixml/llinitparam.h
+++ b/indra/llxuixml/llinitparam.h
@@ -34,6 +34,7 @@ f * @file llinitparam.h
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/type_traits/is_convertible.hpp>
+#include <boost/unordered_map.hpp>
#include "llregistry.h"
#include "llmemory.h"
@@ -196,36 +197,39 @@ namespace LLInitParam
typedef std::pair<name_stack_t::const_iterator, name_stack_t::const_iterator> name_stack_range_t;
typedef std::vector<std::string> possible_values_t;
- typedef boost::function<bool (void*)> parser_read_func_t;
- typedef boost::function<bool (const void*, const name_stack_t&)> parser_write_func_t;
+ typedef bool (*parser_read_func_t)(Parser& parser, void* output);
+ typedef bool (*parser_write_func_t)(Parser& parser, const void*, const name_stack_t&);
typedef boost::function<void (const name_stack_t&, S32, S32, const possible_values_t*)> parser_inspect_func_t;
typedef std::map<const std::type_info*, parser_read_func_t, CompareTypeID> parser_read_func_map_t;
typedef std::map<const std::type_info*, parser_write_func_t, CompareTypeID> parser_write_func_map_t;
typedef std::map<const std::type_info*, parser_inspect_func_t, CompareTypeID> parser_inspect_func_map_t;
- Parser()
+ Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map)
: mParseSilently(false),
- mParseGeneration(0)
+ mParseGeneration(0),
+ mParserReadFuncs(&read_map),
+ mParserWriteFuncs(&write_map),
+ mParserInspectFuncs(&inspect_map)
{}
virtual ~Parser();
template <typename T> bool readValue(T& param)
{
- parser_read_func_map_t::iterator found_it = mParserReadFuncs.find(&typeid(T));
- if (found_it != mParserReadFuncs.end())
+ parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T));
+ if (found_it != mParserReadFuncs->end())
{
- return found_it->second((void*)&param);
+ return found_it->second(*this, (void*)&param);
}
return false;
}
template <typename T> bool writeValue(const T& param, const name_stack_t& name_stack)
{
- parser_write_func_map_t::iterator found_it = mParserWriteFuncs.find(&typeid(T));
- if (found_it != mParserWriteFuncs.end())
+ parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T));
+ if (found_it != mParserWriteFuncs->end())
{
- return found_it->second((const void*)&param, name_stack);
+ return found_it->second(*this, (const void*)&param, name_stack);
}
return false;
}
@@ -233,8 +237,8 @@ namespace LLInitParam
// dispatch inspection to registered inspection functions, for each parameter in a param block
template <typename T> bool inspectValue(const name_stack_t& name_stack, S32 min_count, S32 max_count, const possible_values_t* possible_values)
{
- parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs.find(&typeid(T));
- if (found_it != mParserInspectFuncs.end())
+ parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs->find(&typeid(T));
+ if (found_it != mParserInspectFuncs->end())
{
found_it->second(name_stack, min_count, max_count, possible_values);
return true;
@@ -246,7 +250,6 @@ namespace LLInitParam
virtual void parserWarning(const std::string& message);
virtual void parserError(const std::string& message);
void setParseSilently(bool silent) { mParseSilently = silent; }
- bool getParseSilently() { return mParseSilently; }
S32 getParseGeneration() { return mParseGeneration; }
S32 newParseGeneration() { return ++mParseGeneration; }
@@ -254,24 +257,24 @@ namespace LLInitParam
protected:
template <typename T>
- void registerParserFuncs(parser_read_func_t read_func, parser_write_func_t write_func)
+ void registerParserFuncs(parser_read_func_t read_func, parser_write_func_t write_func = NULL)
{
- mParserReadFuncs.insert(std::make_pair(&typeid(T), read_func));
- mParserWriteFuncs.insert(std::make_pair(&typeid(T), write_func));
+ mParserReadFuncs->insert(std::make_pair(&typeid(T), read_func));
+ mParserWriteFuncs->insert(std::make_pair(&typeid(T), write_func));
}
template <typename T>
void registerInspectFunc(parser_inspect_func_t inspect_func)
{
- mParserInspectFuncs.insert(std::make_pair(&typeid(T), inspect_func));
+ mParserInspectFuncs->insert(std::make_pair(&typeid(T), inspect_func));
}
bool mParseSilently;
private:
- parser_read_func_map_t mParserReadFuncs;
- parser_write_func_map_t mParserWriteFuncs;
- parser_inspect_func_map_t mParserInspectFuncs;
+ parser_read_func_map_t* mParserReadFuncs;
+ parser_write_func_map_t* mParserWriteFuncs;
+ parser_inspect_func_map_t* mParserInspectFuncs;
S32 mParseGeneration;
};
@@ -284,7 +287,7 @@ namespace LLInitParam
void setProvided(bool is_provided) { mIsProvided = is_provided; }
protected:
- bool getProvided() const { return mIsProvided; }
+ bool anyProvided() const { return mIsProvided; }
Param(class BaseBlock* enclosing_block);
@@ -380,14 +383,13 @@ namespace LLInitParam
void aggregateBlockData(BlockDescriptor& src_block_data);
public:
- typedef std::map<const std::string, ParamDescriptor*> param_map_t; // references param descriptors stored in mAllParams
+ typedef boost::unordered_map<const std::string, ParamDescriptor*> param_map_t; // references param descriptors stored in mAllParams
typedef std::vector<ParamDescriptor*> param_list_t;
typedef std::list<ParamDescriptor> all_params_list_t;// references param descriptors stored in mAllParams
typedef std::vector<std::pair<param_handle_t, ParamDescriptor::validation_func_t> > param_validation_list_t;
param_map_t mNamedParams; // parameters with associated names
- param_map_t mSynonyms; // parameters with alternate names
param_list_t mUnnamedParams; // parameters with_out_ associated names
param_validation_list_t mValidationList; // parameters that must be validated
all_params_list_t mAllParams; // all parameters, owns descriptors
@@ -473,8 +475,8 @@ namespace LLInitParam
bool serializeBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), const BaseBlock* diff_block = NULL) const;
bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t()) const;
- const BlockDescriptor& mostDerivedBlockDescriptor() const { return *mBlockDescriptor; }
- BlockDescriptor& mostDerivedBlockDescriptor() { return *mBlockDescriptor; }
+ virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); }
+ virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); }
// take all provided params from other and apply to self
bool overwriteFrom(const BaseBlock& other)
@@ -499,8 +501,6 @@ namespace LLInitParam
// can be updated in getters
mutable S32 mChangeVersion;
- BlockDescriptor* mBlockDescriptor; // most derived block descriptor
-
static BlockDescriptor& selfBlockDescriptor()
{
static BlockDescriptor sBlockDescriptor;
@@ -568,7 +568,7 @@ namespace LLInitParam
mData.mValue = value;
}
- bool isProvided() const { return Param::getProvided(); }
+ bool isProvided() const { return Param::anyProvided(); }
static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation)
{
@@ -576,7 +576,7 @@ namespace LLInitParam
// no further names in stack, attempt to parse value now
if (name_stack.first == name_stack.second)
{
- if (parser.readValue<T>(typed_param.mData.mValue))
+ if (parser.readValue(typed_param.mData.mValue))
{
typed_param.mData.clearKey();
typed_param.setProvided(true);
@@ -589,7 +589,7 @@ namespace LLInitParam
{
// try to parse a known named value
std::string name;
- if (parser.readValue<std::string>(name))
+ if (parser.readValue(name))
{
// try to parse a per type named value
if (NAME_VALUE_LOOKUP::get(name, typed_param.mData.mValue))
@@ -624,7 +624,7 @@ namespace LLInitParam
{
if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->mData.getKey(), key))
{
- if (!parser.writeValue<std::string>(key, name_stack))
+ if (!parser.writeValue(key, name_stack))
{
return;
}
@@ -632,7 +632,7 @@ namespace LLInitParam
}
// then try to serialize value directly
else if (!diff_param || !ParamCompare<T>::equals(typed_param.get(), static_cast<const self_t*>(diff_param)->get())) {
- if (!parser.writeValue<T>(typed_param.mData.mValue, name_stack))
+ if (!parser.writeValue(typed_param.mData.mValue, name_stack))
{
return;
}
@@ -745,7 +745,7 @@ namespace LLInitParam
{
// try to parse a known named value
std::string name;
- if (parser.readValue<std::string>(name))
+ if (parser.readValue(name))
{
// try to parse a per type named value
if (NAME_VALUE_LOOKUP::get(name, typed_param))
@@ -772,7 +772,7 @@ namespace LLInitParam
std::string key = typed_param.mData.getKey();
if (!key.empty() && typed_param.mData.mKeyVersion == typed_param.getLastChangeVersion())
{
- if (!parser.writeValue<std::string>(key, name_stack))
+ if (!parser.writeValue(key, name_stack))
{
return;
}
@@ -795,13 +795,13 @@ namespace LLInitParam
bool isProvided() const
{
// only validate block when it hasn't already passed validation and user has supplied *some* value
- if (Param::getProvided() && mData.mValidatedVersion < T::getLastChangeVersion())
+ if (Param::anyProvided() && mData.mValidatedVersion < T::getLastChangeVersion())
{
// a sub-block is "provided" when it has been filled in enough to be valid
mData.mValidated = T::validateBlock(false);
mData.mValidatedVersion = T::getLastChangeVersion();
}
- return Param::getProvided() && mData.mValidated;
+ return Param::anyProvided() && mData.mValidated;
}
// assign block contents to this param-that-is-a-block
@@ -852,7 +852,7 @@ namespace LLInitParam
{
const self_t& src_typed_param = static_cast<const self_t&>(src);
self_t& dst_typed_param = static_cast<self_t&>(dst);
- if (dst_typed_param.T::merge(T::selfBlockDescriptor(), src_typed_param, overwrite || !dst_typed_param.isProvided()))
+ if (dst_typed_param.T::merge(T::selfBlockDescriptor(), src_typed_param, overwrite))
{
dst_typed_param.mData.clearKey();
return true;
@@ -909,7 +909,7 @@ namespace LLInitParam
}
}
- bool isProvided() const { return Param::getProvided(); }
+ bool isProvided() const { return Param::anyProvided(); }
static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation)
{
@@ -919,7 +919,7 @@ namespace LLInitParam
if (name_stack.first == name_stack.second)
{
// attempt to read value directly
- if (parser.readValue<value_t>(value))
+ if (parser.readValue(value))
{
typed_param.mValues.push_back(value);
// save an empty name/value key as a placeholder
@@ -934,7 +934,7 @@ namespace LLInitParam
{
// try to parse a known named value
std::string name;
- if (parser.readValue<std::string>(name))
+ if (parser.readValue(name))
{
// try to parse a per type named value
if (NAME_VALUE_LOOKUP::get(name, typed_param.mValues))
@@ -958,7 +958,7 @@ namespace LLInitParam
const self_t& typed_param = static_cast<const self_t&>(param);
if (!typed_param.isProvided() || name_stack.empty()) return;
- typename container_t::const_iterator it = typed_param.mValues.begin();
+ const_iterator it = typed_param.mValues.begin();
for (typename std::vector<key_cache_t>::const_iterator key_it = typed_param.mCachedKeys.begin();
it != typed_param.mValues.end();
++key_it, ++it)
@@ -968,13 +968,13 @@ namespace LLInitParam
if(!key.empty())
{
- if(!parser.writeValue<std::string>(key, name_stack))
+ if(!parser.writeValue(key, name_stack))
{
return;
}
}
// not parse via name values, write out value directly
- else if (!parser.writeValue<VALUE_TYPE>(*it, name_stack))
+ else if (!parser.writeValue(*it, name_stack))
{
return;
}
@@ -1025,8 +1025,15 @@ namespace LLInitParam
// implicit conversion
operator value_assignment_t() const { return self_t::get(); }
- // explicit conversion
- value_assignment_t operator()() const { return get(); }
+
+ typedef typename container_t::iterator iterator;
+ typedef typename container_t::const_iterator const_iterator;
+ iterator begin() { return mValues.begin(); }
+ iterator end() { return mValues.end(); }
+ const_iterator begin() const { return mValues.begin(); }
+ const_iterator end() const { return mValues.end(); }
+ bool empty() const { return mValues.empty(); }
+ size_t size() const { return mValues.size(); }
U32 numValidElements() const
{
@@ -1092,7 +1099,7 @@ namespace LLInitParam
}
}
- bool isProvided() const { return Param::getProvided(); }
+ bool isProvided() const { return Param::anyProvided(); }
value_ref_t operator[](S32 index) { return mValues[index]; }
value_const_ref_t operator[](S32 index) const { return mValues[index]; }
@@ -1100,32 +1107,41 @@ namespace LLInitParam
static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation)
{
self_t& typed_param = static_cast<self_t&>(param);
+ bool new_value = false;
if (generation != typed_param.mLastParamGeneration || typed_param.mValues.empty())
{
+ new_value = true;
typed_param.mValues.push_back(value_t());
typed_param.mCachedKeys.push_back(Data());
- typed_param.enclosingBlock().setLastChangedParam(param, true);
- typed_param.mLastParamGeneration = generation;
}
- value_t& value = typed_param.mValues.back();
+ value_ref_t value = typed_param.mValues.back();
// attempt to parse block...
if(value.deserializeBlock(parser, name_stack))
{
+ if (new_value)
+ { // successfully parsed new value, let's keep it
+ typed_param.mLastParamGeneration = generation;
+ }
+ typed_param.enclosingBlock().setLastChangedParam(param, true);
typed_param.setProvided(true);
return true;
}
-
- if(!NAME_VALUE_LOOKUP::empty())
+ else if(!NAME_VALUE_LOOKUP::empty())
{
// try to parse a known named value
std::string name;
- if (parser.readValue<std::string>(name))
+ if (parser.readValue(name))
{
// try to parse a per type named value
if (NAME_VALUE_LOOKUP::get(name, value))
{
+ if (new_value)
+ { // successfully parsed new value, let's keep it
+ typed_param.mLastParamGeneration = generation;
+ }
+
typed_param.mCachedKeys.back().setKey(name);
typed_param.mCachedKeys.back().mKeyVersion = value.getLastChangeVersion();
typed_param.enclosingBlock().setLastChangedParam(param, true);
@@ -1136,6 +1152,12 @@ namespace LLInitParam
}
}
+ if (new_value)
+ { // failed to parse new value, pop it off
+ typed_param.mValues.pop_back();
+ typed_param.mCachedKeys.pop_back();
+ }
+
return false;
}
@@ -1144,7 +1166,7 @@ namespace LLInitParam
const self_t& typed_param = static_cast<const self_t&>(param);
if (!typed_param.isProvided() || name_stack.empty()) return;
- typename container_t::const_iterator it = typed_param.mValues.begin();
+ const_iterator it = typed_param.mValues.begin();
for (typename std::vector<Data>::const_iterator key_it = typed_param.mCachedKeys.begin();
it != typed_param.mValues.end();
++key_it, ++it)
@@ -1154,7 +1176,7 @@ namespace LLInitParam
std::string key = key_it->getKey();
if (!key.empty() && key_it->mKeyVersion == it->getLastChangeVersion())
{
- if(!parser.writeValue<std::string>(key, name_stack))
+ if(!parser.writeValue(key, name_stack))
{
return;
}
@@ -1208,13 +1230,20 @@ namespace LLInitParam
// implicit conversion
operator value_assignment_t() const { return self_t::get(); }
- // explicit conversion
- value_assignment_t operator()() const { return get(); }
+
+ typedef typename container_t::iterator iterator;
+ typedef typename container_t::const_iterator const_iterator;
+ iterator begin() { return mValues.begin(); }
+ iterator end() { return mValues.end(); }
+ const_iterator begin() const { return mValues.begin(); }
+ const_iterator end() const { return mValues.end(); }
+ bool empty() const { return mValues.empty(); }
+ size_t size() const { return mValues.size(); }
U32 numValidElements() const
{
U32 count = 0;
- for (typename container_t::const_iterator it = mValues.begin();
+ for (const_iterator it = mValues.begin();
it != mValues.end();
++it)
{
@@ -1306,6 +1335,9 @@ namespace LLInitParam
BaseBlock::setLastChangedParam(last_param, user_provided);
}
+ virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); }
+ virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); }
+
protected:
Choice()
: mCurChoice(0)
@@ -1415,6 +1447,10 @@ namespace LLInitParam
{
return BaseBlock::merge(selfBlockDescriptor(), other, false);
}
+
+ virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); }
+ virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); }
+
protected:
Block()
{
@@ -1494,15 +1530,13 @@ namespace LLInitParam
typedef Multiple<T, RANGE, NAME_VALUE_LOOKUP> self_t;
typedef typename super_t::container_t container_t;
typedef typename super_t::value_assignment_t value_assignment_t;
- typedef typename container_t::iterator iterator;
- typedef typename container_t::const_iterator const_iterator;
+ typedef typename super_t::iterator iterator;
+ typedef typename super_t::const_iterator const_iterator;
explicit Multiple(const char* name = "", value_assignment_t val = DefaultInitializer<container_t>::get())
: super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, &validate, RANGE::minCount(), RANGE::maxCount())
{}
- using super_t::operator();
-
Multiple& operator=(value_assignment_t val)
{
set(val);
@@ -1612,7 +1646,7 @@ namespace LLInitParam
// type to apply parse direct value T
if (name_stack.first == name_stack.second)
{
- if(parser.readValue<T>(typed_param.mData.mValue))
+ if(parser.readValue(typed_param.mData.mValue))
{
typed_param.enclosingBlock().setLastChangedParam(param, true);
typed_param.setProvided(true);
@@ -1627,7 +1661,7 @@ namespace LLInitParam
{
// try to parse a known named value
std::string name;
- if (parser.readValue<std::string>(name))
+ if (parser.readValue(name))
{
// try to parse a per type named value
if (TypeValues<T>::get(name, typed_param.mData.mValue))
@@ -1669,7 +1703,7 @@ namespace LLInitParam
{
if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->mData.getKey(), key))
{
- if (!parser.writeValue<std::string>(key, name_stack))
+ if (!parser.writeValue(key, name_stack))
{
return;
}
@@ -1679,7 +1713,7 @@ namespace LLInitParam
else if (!diff_param || !ParamCompare<T>::equals(typed_param.get(), (static_cast<const self_t*>(diff_param))->get()))
{
- if (parser.writeValue<T>(typed_param.mData.mValue, name_stack))
+ if (parser.writeValue(typed_param.mData.mValue, name_stack))
{
return;
}
@@ -1712,7 +1746,7 @@ namespace LLInitParam
bool isProvided() const
{
- if (!Param::getProvided()) return false;
+ if (!Param::anyProvided()) return false;
// block has an updated parameter
// if cached value is stale, regenerate from params
@@ -1779,7 +1813,7 @@ namespace LLInitParam
value_assignment_t get() const
{
// if some parameters were provided, issue warnings on invalid blocks
- if (Param::getProvided() && (mData.mValueAge == OLDER_THAN_BLOCK))
+ if (Param::anyProvided() && (mData.mValueAge == OLDER_THAN_BLOCK))
{
// go ahead and issue warnings at this point if any param is invalid
if(block_t::validateBlock(true))
diff --git a/indra/llxuixml/llregistry.h b/indra/llxuixml/llregistry.h
index ee119b9ebc..eee9933739 100644
--- a/indra/llxuixml/llregistry.h
+++ b/indra/llxuixml/llregistry.h
@@ -70,6 +70,11 @@ public:
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();
diff --git a/indra/llxuixml/lltrans.cpp b/indra/llxuixml/lltrans.cpp
index 01e13864b6..11127a53f5 100644
--- a/indra/llxuixml/lltrans.cpp
+++ b/indra/llxuixml/lltrans.cpp
@@ -66,7 +66,8 @@ bool LLTrans::parseStrings(LLXMLNodePtr &root, const std::set<std::string>& defa
}
StringTable string_table;
- LLXUIParser::instance().readXUI(root, string_table, xml_filename);
+ LLXUIParser parser;
+ parser.readXUI(root, string_table, xml_filename);
if (!string_table.validateBlock())
{
@@ -77,8 +78,8 @@ bool LLTrans::parseStrings(LLXMLNodePtr &root, const std::set<std::string>& defa
sStringTemplates.clear();
sDefaultArgs.clear();
- for(LLInitParam::ParamIterator<StringDef>::const_iterator it = string_table.strings().begin();
- it != string_table.strings().end();
+ for(LLInitParam::ParamIterator<StringDef>::const_iterator it = string_table.strings.begin();
+ it != string_table.strings.end();
++it)
{
LLTransTemplate xml_template(it->name, it->value);
@@ -109,7 +110,8 @@ bool LLTrans::parseLanguageStrings(LLXMLNodePtr &root)
}
StringTable string_table;
- LLXUIParser::instance().readXUI(root, string_table, xml_filename);
+ LLXUIParser parser;
+ parser.readXUI(root, string_table, xml_filename);
if (!string_table.validateBlock())
{
@@ -117,8 +119,8 @@ bool LLTrans::parseLanguageStrings(LLXMLNodePtr &root)
return false;
}
- for(LLInitParam::ParamIterator<StringDef>::const_iterator it = string_table.strings().begin();
- it != string_table.strings().end();
+ for(LLInitParam::ParamIterator<StringDef>::const_iterator it = string_table.strings.begin();
+ it != string_table.strings.end();
++it)
{
// share the same map with parseStrings() so we can search the strings using the same getString() function.- angela
diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp
index 8469debd3e..e1ad9a5c71 100644
--- a/indra/llxuixml/llxuiparser.cpp
+++ b/indra/llxuixml/llxuiparser.cpp
@@ -29,17 +29,28 @@
#include "llxuiparser.h"
#include "llxmlnode.h"
+#include "expat/expat.h"
#include <fstream>
#include <boost/tokenizer.hpp>
+//#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/classic_core.hpp>
#include "lluicolor.h"
+using namespace BOOST_SPIRIT_CLASSIC_NS;
+
const S32 MAX_STRING_ATTRIBUTE_SIZE = 40;
+static LLInitParam::Parser::parser_read_func_map_t sXSDReadFuncs;
+static LLInitParam::Parser::parser_write_func_map_t sXSDWriteFuncs;
+static LLInitParam::Parser::parser_inspect_func_map_t sXSDInspectFuncs;
+
+
//
// LLXSDWriter
//
LLXSDWriter::LLXSDWriter()
+: Parser(sXSDReadFuncs, sXSDWriteFuncs, sXSDInspectFuncs)
{
registerInspectFunc<bool>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:boolean", _1, _2, _3, _4));
registerInspectFunc<std::string>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4));
@@ -357,41 +368,35 @@ void LLXUIXSDWriter::writeXSD(const std::string& type_name, const std::string& p
fclose(xsd_file);
}
+static LLInitParam::Parser::parser_read_func_map_t sXUIReadFuncs;
+static LLInitParam::Parser::parser_write_func_map_t sXUIWriteFuncs;
+static LLInitParam::Parser::parser_inspect_func_map_t sXUIInspectFuncs;
+
//
// LLXUIParser
//
LLXUIParser::LLXUIParser()
-: mLastWriteGeneration(-1),
+: Parser(sXUIReadFuncs, sXUIWriteFuncs, sXUIInspectFuncs),
+ mLastWriteGeneration(-1),
mCurReadDepth(0)
{
- registerParserFuncs<bool>(boost::bind(&LLXUIParser::readBoolValue, this, _1),
- boost::bind(&LLXUIParser::writeBoolValue, this, _1, _2));
- registerParserFuncs<std::string>(boost::bind(&LLXUIParser::readStringValue, this, _1),
- boost::bind(&LLXUIParser::writeStringValue, this, _1, _2));
- registerParserFuncs<U8>(boost::bind(&LLXUIParser::readU8Value, this, _1),
- boost::bind(&LLXUIParser::writeU8Value, this, _1, _2));
- registerParserFuncs<S8>(boost::bind(&LLXUIParser::readS8Value, this, _1),
- boost::bind(&LLXUIParser::writeS8Value, this, _1, _2));
- registerParserFuncs<U16>(boost::bind(&LLXUIParser::readU16Value, this, _1),
- boost::bind(&LLXUIParser::writeU16Value, this, _1, _2));
- registerParserFuncs<S16>(boost::bind(&LLXUIParser::readS16Value, this, _1),
- boost::bind(&LLXUIParser::writeS16Value, this, _1, _2));
- registerParserFuncs<U32>(boost::bind(&LLXUIParser::readU32Value, this, _1),
- boost::bind(&LLXUIParser::writeU32Value, this, _1, _2));
- registerParserFuncs<S32>(boost::bind(&LLXUIParser::readS32Value, this, _1),
- boost::bind(&LLXUIParser::writeS32Value, this, _1, _2));
- registerParserFuncs<F32>(boost::bind(&LLXUIParser::readF32Value, this, _1),
- boost::bind(&LLXUIParser::writeF32Value, this, _1, _2));
- registerParserFuncs<F64>(boost::bind(&LLXUIParser::readF64Value, this, _1),
- boost::bind(&LLXUIParser::writeF64Value, this, _1, _2));
- registerParserFuncs<LLColor4>(boost::bind(&LLXUIParser::readColor4Value, this, _1),
- boost::bind(&LLXUIParser::writeColor4Value, this, _1, _2));
- registerParserFuncs<LLUIColor>(boost::bind(&LLXUIParser::readUIColorValue, this, _1),
- boost::bind(&LLXUIParser::writeUIColorValue, this, _1, _2));
- registerParserFuncs<LLUUID>(boost::bind(&LLXUIParser::readUUIDValue, this, _1),
- boost::bind(&LLXUIParser::writeUUIDValue, this, _1, _2));
- registerParserFuncs<LLSD>(boost::bind(&LLXUIParser::readSDValue, this, _1),
- boost::bind(&LLXUIParser::writeSDValue, this, _1, _2));
+ if (sXUIReadFuncs.empty())
+ {
+ registerParserFuncs<bool>(readBoolValue, writeBoolValue);
+ registerParserFuncs<std::string>(readStringValue, writeStringValue);
+ registerParserFuncs<U8>(readU8Value, writeU8Value);
+ registerParserFuncs<S8>(readS8Value, writeS8Value);
+ registerParserFuncs<U16>(readU16Value, writeU16Value);
+ registerParserFuncs<S16>(readS16Value, writeS16Value);
+ registerParserFuncs<U32>(readU32Value, writeU32Value);
+ registerParserFuncs<S32>(readS32Value, writeS32Value);
+ registerParserFuncs<F32>(readF32Value, writeF32Value);
+ registerParserFuncs<F64>(readF64Value, writeF64Value);
+ registerParserFuncs<LLColor4>(readColor4Value, writeColor4Value);
+ registerParserFuncs<LLUIColor>(readUIColorValue, writeUIColorValue);
+ registerParserFuncs<LLUUID>(readUUIDValue, writeUUIDValue);
+ registerParserFuncs<LLSD>(readSDValue, writeSDValue);
+ }
}
static LLFastTimer::DeclareTimer FTM_PARSE_XUI("XUI Parsing");
@@ -400,6 +405,7 @@ void LLXUIParser::readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, cons
{
LLFastTimer timer(FTM_PARSE_XUI);
mNameStack.clear();
+ mRootNodeName = node->getName()->mString;
mCurFileName = filename;
mCurReadDepth = 0;
setParseSilently(silent);
@@ -410,11 +416,11 @@ void LLXUIParser::readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, cons
}
else
{
- readXUIImpl(node, std::string(node->getName()->mString), block);
+ readXUIImpl(node, block);
}
}
-bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, const std::string& scope, LLInitParam::BaseBlock& block)
+bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block)
{
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
boost::char_separator<char> sep(".");
@@ -481,7 +487,15 @@ bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, const std::string& scope, LLIn
}
// check for proper nesting
- if(!scope.empty() && *name_token_it != scope)
+ if (mNameStack.empty())
+ {
+ if (*name_token_it != mRootNodeName)
+ {
+ childp = childp->getNextSibling();
+ continue;
+ }
+ }
+ else if(mNameStack.back().first != *name_token_it)
{
childp = childp->getNextSibling();
continue;
@@ -499,7 +513,7 @@ bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, const std::string& scope, LLIn
}
// recurse and visit children XML nodes
- if(readXUIImpl(childp, mNameStack.empty() ? scope : mNameStack.back().first, block))
+ if(readXUIImpl(childp, block))
{
// child node successfully parsed, remove from DOM
@@ -615,17 +629,19 @@ LLXMLNodePtr LLXUIParser::getNode(const name_stack_t& stack)
}
-bool LLXUIParser::readBoolValue(void* val_ptr)
+bool LLXUIParser::readBoolValue(Parser& parser, void* val_ptr)
{
S32 value;
- bool success = mCurReadNode->getBoolValue(1, &value);
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ bool success = self.mCurReadNode->getBoolValue(1, &value);
*((bool*)val_ptr) = (value != FALSE);
return success;
}
-bool LLXUIParser::writeBoolValue(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeBoolValue(Parser& parser, const void* val_ptr, const name_stack_t& stack)
{
- LLXMLNodePtr node = getNode(stack);
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ LLXMLNodePtr node = self.getNode(stack);
if (node.notNull())
{
node->setBoolValue(*((bool*)val_ptr));
@@ -634,15 +650,17 @@ bool LLXUIParser::writeBoolValue(const void* val_ptr, const name_stack_t& stack)
return false;
}
-bool LLXUIParser::readStringValue(void* val_ptr)
+bool LLXUIParser::readStringValue(Parser& parser, void* val_ptr)
{
- *((std::string*)val_ptr) = mCurReadNode->getSanitizedValue();
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ *((std::string*)val_ptr) = self.mCurReadNode->getSanitizedValue();
return true;
}
-bool LLXUIParser::writeStringValue(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeStringValue(Parser& parser, const void* val_ptr, const name_stack_t& stack)
{
- LLXMLNodePtr node = getNode(stack);
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ LLXMLNodePtr node = self.getNode(stack);
if (node.notNull())
{
const std::string* string_val = reinterpret_cast<const std::string*>(val_ptr);
@@ -671,14 +689,16 @@ bool LLXUIParser::writeStringValue(const void* val_ptr, const name_stack_t& stac
return false;
}
-bool LLXUIParser::readU8Value(void* val_ptr)
+bool LLXUIParser::readU8Value(Parser& parser, void* val_ptr)
{
- return mCurReadNode->getByteValue(1, (U8*)val_ptr);
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ return self.mCurReadNode->getByteValue(1, (U8*)val_ptr);
}
-bool LLXUIParser::writeU8Value(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeU8Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
{
- LLXMLNodePtr node = getNode(stack);
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ LLXMLNodePtr node = self.getNode(stack);
if (node.notNull())
{
node->setUnsignedValue(*((U8*)val_ptr));
@@ -687,10 +707,11 @@ bool LLXUIParser::writeU8Value(const void* val_ptr, const name_stack_t& stack)
return false;
}
-bool LLXUIParser::readS8Value(void* val_ptr)
+bool LLXUIParser::readS8Value(Parser& parser, void* val_ptr)
{
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
S32 value;
- if(mCurReadNode->getIntValue(1, &value))
+ if(self.mCurReadNode->getIntValue(1, &value))
{
*((S8*)val_ptr) = value;
return true;
@@ -698,9 +719,10 @@ bool LLXUIParser::readS8Value(void* val_ptr)
return false;
}
-bool LLXUIParser::writeS8Value(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeS8Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
{
- LLXMLNodePtr node = getNode(stack);
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ LLXMLNodePtr node = self.getNode(stack);
if (node.notNull())
{
node->setIntValue(*((S8*)val_ptr));
@@ -709,10 +731,11 @@ bool LLXUIParser::writeS8Value(const void* val_ptr, const name_stack_t& stack)
return false;
}
-bool LLXUIParser::readU16Value(void* val_ptr)
+bool LLXUIParser::readU16Value(Parser& parser, void* val_ptr)
{
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
U32 value;
- if(mCurReadNode->getUnsignedValue(1, &value))
+ if(self.mCurReadNode->getUnsignedValue(1, &value))
{
*((U16*)val_ptr) = value;
return true;
@@ -720,9 +743,10 @@ bool LLXUIParser::readU16Value(void* val_ptr)
return false;
}
-bool LLXUIParser::writeU16Value(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeU16Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
{
- LLXMLNodePtr node = getNode(stack);
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ LLXMLNodePtr node = self.getNode(stack);
if (node.notNull())
{
node->setUnsignedValue(*((U16*)val_ptr));
@@ -731,10 +755,11 @@ bool LLXUIParser::writeU16Value(const void* val_ptr, const name_stack_t& stack)
return false;
}
-bool LLXUIParser::readS16Value(void* val_ptr)
+bool LLXUIParser::readS16Value(Parser& parser, void* val_ptr)
{
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
S32 value;
- if(mCurReadNode->getIntValue(1, &value))
+ if(self.mCurReadNode->getIntValue(1, &value))
{
*((S16*)val_ptr) = value;
return true;
@@ -742,9 +767,10 @@ bool LLXUIParser::readS16Value(void* val_ptr)
return false;
}
-bool LLXUIParser::writeS16Value(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeS16Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
{
- LLXMLNodePtr node = getNode(stack);
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ LLXMLNodePtr node = self.getNode(stack);
if (node.notNull())
{
node->setIntValue(*((S16*)val_ptr));
@@ -753,14 +779,16 @@ bool LLXUIParser::writeS16Value(const void* val_ptr, const name_stack_t& stack)
return false;
}
-bool LLXUIParser::readU32Value(void* val_ptr)
+bool LLXUIParser::readU32Value(Parser& parser, void* val_ptr)
{
- return mCurReadNode->getUnsignedValue(1, (U32*)val_ptr);
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ return self.mCurReadNode->getUnsignedValue(1, (U32*)val_ptr);
}
-bool LLXUIParser::writeU32Value(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeU32Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
{
- LLXMLNodePtr node = getNode(stack);
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ LLXMLNodePtr node = self.getNode(stack);
if (node.notNull())
{
node->setUnsignedValue(*((U32*)val_ptr));
@@ -769,14 +797,16 @@ bool LLXUIParser::writeU32Value(const void* val_ptr, const name_stack_t& stack)
return false;
}
-bool LLXUIParser::readS32Value(void* val_ptr)
+bool LLXUIParser::readS32Value(Parser& parser, void* val_ptr)
{
- return mCurReadNode->getIntValue(1, (S32*)val_ptr);
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ return self.mCurReadNode->getIntValue(1, (S32*)val_ptr);
}
-bool LLXUIParser::writeS32Value(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeS32Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
{
- LLXMLNodePtr node = getNode(stack);
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ LLXMLNodePtr node = self.getNode(stack);
if (node.notNull())
{
node->setIntValue(*((S32*)val_ptr));
@@ -785,14 +815,16 @@ bool LLXUIParser::writeS32Value(const void* val_ptr, const name_stack_t& stack)
return false;
}
-bool LLXUIParser::readF32Value(void* val_ptr)
+bool LLXUIParser::readF32Value(Parser& parser, void* val_ptr)
{
- return mCurReadNode->getFloatValue(1, (F32*)val_ptr);
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ return self.mCurReadNode->getFloatValue(1, (F32*)val_ptr);
}
-bool LLXUIParser::writeF32Value(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeF32Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
{
- LLXMLNodePtr node = getNode(stack);
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ LLXMLNodePtr node = self.getNode(stack);
if (node.notNull())
{
node->setFloatValue(*((F32*)val_ptr));
@@ -801,14 +833,16 @@ bool LLXUIParser::writeF32Value(const void* val_ptr, const name_stack_t& stack)
return false;
}
-bool LLXUIParser::readF64Value(void* val_ptr)
+bool LLXUIParser::readF64Value(Parser& parser, void* val_ptr)
{
- return mCurReadNode->getDoubleValue(1, (F64*)val_ptr);
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ return self.mCurReadNode->getDoubleValue(1, (F64*)val_ptr);
}
-bool LLXUIParser::writeF64Value(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeF64Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
{
- LLXMLNodePtr node = getNode(stack);
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ LLXMLNodePtr node = self.getNode(stack);
if (node.notNull())
{
node->setDoubleValue(*((F64*)val_ptr));
@@ -817,10 +851,11 @@ bool LLXUIParser::writeF64Value(const void* val_ptr, const name_stack_t& stack)
return false;
}
-bool LLXUIParser::readColor4Value(void* val_ptr)
+bool LLXUIParser::readColor4Value(Parser& parser, void* val_ptr)
{
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
LLColor4* colorp = (LLColor4*)val_ptr;
- if(mCurReadNode->getFloatValue(4, colorp->mV) >= 3)
+ if(self.mCurReadNode->getFloatValue(4, colorp->mV) >= 3)
{
return true;
}
@@ -828,9 +863,10 @@ bool LLXUIParser::readColor4Value(void* val_ptr)
return false;
}
-bool LLXUIParser::writeColor4Value(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeColor4Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
{
- LLXMLNodePtr node = getNode(stack);
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ LLXMLNodePtr node = self.getNode(stack);
if (node.notNull())
{
LLColor4 color = *((LLColor4*)val_ptr);
@@ -840,11 +876,12 @@ bool LLXUIParser::writeColor4Value(const void* val_ptr, const name_stack_t& stac
return false;
}
-bool LLXUIParser::readUIColorValue(void* val_ptr)
+bool LLXUIParser::readUIColorValue(Parser& parser, void* val_ptr)
{
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
LLUIColor* param = (LLUIColor*)val_ptr;
LLColor4 color;
- bool success = mCurReadNode->getFloatValue(4, color.mV) >= 3;
+ bool success = self.mCurReadNode->getFloatValue(4, color.mV) >= 3;
if (success)
{
param->set(color);
@@ -853,9 +890,10 @@ bool LLXUIParser::readUIColorValue(void* val_ptr)
return false;
}
-bool LLXUIParser::writeUIColorValue(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeUIColorValue(Parser& parser, const void* val_ptr, const name_stack_t& stack)
{
- LLXMLNodePtr node = getNode(stack);
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ LLXMLNodePtr node = self.getNode(stack);
if (node.notNull())
{
LLUIColor color = *((LLUIColor*)val_ptr);
@@ -868,11 +906,12 @@ bool LLXUIParser::writeUIColorValue(const void* val_ptr, const name_stack_t& sta
return false;
}
-bool LLXUIParser::readUUIDValue(void* val_ptr)
+bool LLXUIParser::readUUIDValue(Parser& parser, void* val_ptr)
{
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
LLUUID temp_id;
// LLUUID::set is destructive, so use temporary value
- if (temp_id.set(mCurReadNode->getSanitizedValue()))
+ if (temp_id.set(self.mCurReadNode->getSanitizedValue()))
{
*(LLUUID*)(val_ptr) = temp_id;
return true;
@@ -880,9 +919,10 @@ bool LLXUIParser::readUUIDValue(void* val_ptr)
return false;
}
-bool LLXUIParser::writeUUIDValue(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeUUIDValue(Parser& parser, const void* val_ptr, const name_stack_t& stack)
{
- LLXMLNodePtr node = getNode(stack);
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ LLXMLNodePtr node = self.getNode(stack);
if (node.notNull())
{
node->setStringValue(((LLUUID*)val_ptr)->asString());
@@ -891,15 +931,18 @@ bool LLXUIParser::writeUUIDValue(const void* val_ptr, const name_stack_t& stack)
return false;
}
-bool LLXUIParser::readSDValue(void* val_ptr)
+bool LLXUIParser::readSDValue(Parser& parser, void* val_ptr)
{
- *((LLSD*)val_ptr) = LLSD(mCurReadNode->getSanitizedValue());
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+ *((LLSD*)val_ptr) = LLSD(self.mCurReadNode->getSanitizedValue());
return true;
}
-bool LLXUIParser::writeSDValue(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeSDValue(Parser& parser, const void* val_ptr, const name_stack_t& stack)
{
- LLXMLNodePtr node = getNode(stack);
+ LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+
+ LLXMLNodePtr node = self.getNode(stack);
if (node.notNull())
{
std::string string_val = ((LLSD*)val_ptr)->asString();
@@ -962,3 +1005,438 @@ void LLXUIParser::parserError(const std::string& message)
Parser::parserError(message);
#endif
}
+
+
+//
+// LLSimpleXUIParser
+//
+
+struct ScopedFile
+{
+ ScopedFile( const std::string& filename, const char* accessmode )
+ {
+ mFile = LLFile::fopen(filename, accessmode);
+ }
+
+ ~ScopedFile()
+ {
+ fclose(mFile);
+ mFile = NULL;
+ }
+
+ S32 getRemainingBytes()
+ {
+ if (!isOpen()) return 0;
+
+ S32 cur_pos = ftell(mFile);
+ fseek(mFile, 0L, SEEK_END);
+ S32 file_size = ftell(mFile);
+ fseek(mFile, cur_pos, SEEK_SET);
+ return file_size - cur_pos;
+ }
+
+ bool isOpen() { return mFile != NULL; }
+
+ LLFILE* mFile;
+};
+static LLInitParam::Parser::parser_read_func_map_t sSimpleXUIReadFuncs;
+static LLInitParam::Parser::parser_write_func_map_t sSimpleXUIWriteFuncs;
+static LLInitParam::Parser::parser_inspect_func_map_t sSimpleXUIInspectFuncs;
+
+LLSimpleXUIParser::LLSimpleXUIParser(LLSimpleXUIParser::element_start_callback_t element_cb)
+: Parser(sSimpleXUIReadFuncs, sSimpleXUIWriteFuncs, sSimpleXUIInspectFuncs),
+ mLastWriteGeneration(-1),
+ mCurReadDepth(0),
+ mElementCB(element_cb)
+{
+ if (sSimpleXUIReadFuncs.empty())
+ {
+ registerParserFuncs<bool>(readBoolValue);
+ registerParserFuncs<std::string>(readStringValue);
+ registerParserFuncs<U8>(readU8Value);
+ registerParserFuncs<S8>(readS8Value);
+ registerParserFuncs<U16>(readU16Value);
+ registerParserFuncs<S16>(readS16Value);
+ registerParserFuncs<U32>(readU32Value);
+ registerParserFuncs<S32>(readS32Value);
+ registerParserFuncs<F32>(readF32Value);
+ registerParserFuncs<F64>(readF64Value);
+ registerParserFuncs<LLColor4>(readColor4Value);
+ registerParserFuncs<LLUIColor>(readUIColorValue);
+ registerParserFuncs<LLUUID>(readUUIDValue);
+ registerParserFuncs<LLSD>(readSDValue);
+ }
+}
+
+LLSimpleXUIParser::~LLSimpleXUIParser()
+{
+}
+
+
+bool LLSimpleXUIParser::readXUI(const std::string& filename, LLInitParam::BaseBlock& block, bool silent)
+{
+ LLFastTimer timer(FTM_PARSE_XUI);
+
+ mParser = XML_ParserCreate(NULL);
+ XML_SetUserData(mParser, this);
+ XML_SetElementHandler( mParser, startElementHandler, endElementHandler);
+ XML_SetCharacterDataHandler( mParser, characterDataHandler);
+
+ mOutputStack.push_back(std::make_pair(&block, 0));
+ mNameStack.clear();
+ mCurFileName = filename;
+ mCurReadDepth = 0;
+ setParseSilently(silent);
+
+ ScopedFile file(filename, "rb");
+ if( !file.isOpen() )
+ {
+ LL_WARNS("ReadXUI") << "Unable to open file " << filename << LL_ENDL;
+ return false;
+ }
+
+ S32 bytes_read = 0;
+
+ S32 buffer_size = file.getRemainingBytes();
+ void* buffer = XML_GetBuffer(mParser, buffer_size);
+ if( !buffer )
+ {
+ LL_WARNS("ReadXUI") << "Unable to allocate XML buffer while reading file " << filename << LL_ENDL;
+ XML_ParserFree( mParser );
+ return false;
+ }
+
+ bytes_read = (S32)fread(buffer, 1, buffer_size, file.mFile);
+ if( bytes_read <= 0 )
+ {
+ LL_WARNS("ReadXUI") << "Error while reading file " << filename << LL_ENDL;
+ XML_ParserFree( mParser );
+ return false;
+ }
+
+ if( !XML_ParseBuffer(mParser, bytes_read, TRUE ) )
+ {
+ LL_WARNS("ReadXUI") << "Error while parsing file " << filename << LL_ENDL;
+ XML_ParserFree( mParser );
+ return false;
+ }
+
+ XML_ParserFree( mParser );
+ return true;
+}
+
+void LLSimpleXUIParser::startElementHandler(void *userData, const char *name, const char **atts)
+{
+ LLSimpleXUIParser* self = reinterpret_cast<LLSimpleXUIParser*>(userData);
+ self->startElement(name, atts);
+}
+
+void LLSimpleXUIParser::endElementHandler(void *userData, const char *name)
+{
+ LLSimpleXUIParser* self = reinterpret_cast<LLSimpleXUIParser*>(userData);
+ self->endElement(name);
+}
+
+void LLSimpleXUIParser::characterDataHandler(void *userData, const char *s, int len)
+{
+ LLSimpleXUIParser* self = reinterpret_cast<LLSimpleXUIParser*>(userData);
+ self->characterData(s, len);
+}
+
+void LLSimpleXUIParser::startElement(const char *name, const char **atts)
+{
+ processText();
+
+ typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+ boost::char_separator<char> sep(".");
+
+ if (mElementCB)
+ {
+ LLInitParam::BaseBlock* blockp = mElementCB(*this, name);
+ if (blockp)
+ {
+ mOutputStack.push_back(std::make_pair(blockp, 0));
+ }
+ }
+
+ mOutputStack.back().second++;
+ S32 num_tokens_pushed = 0;
+ std::string child_name(name);
+
+ if (mOutputStack.back().second == 1)
+ { // root node for this block
+ mScope.push_back(child_name);
+ }
+ else
+ { // compound attribute
+ if (child_name.find(".") == std::string::npos)
+ {
+ mNameStack.push_back(std::make_pair(child_name, newParseGeneration()));
+ num_tokens_pushed++;
+ mScope.push_back(child_name);
+ }
+ else
+ {
+ // parse out "dotted" name into individual tokens
+ tokenizer name_tokens(child_name, sep);
+
+ tokenizer::iterator name_token_it = name_tokens.begin();
+ if(name_token_it == name_tokens.end())
+ {
+ return;
+ }
+
+ // check for proper nesting
+ if(!mScope.empty() && *name_token_it != mScope.back())
+ {
+ return;
+ }
+
+ // now ignore first token
+ ++name_token_it;
+
+ // copy remaining tokens on to our running token list
+ for(tokenizer::iterator token_to_push = name_token_it; token_to_push != name_tokens.end(); ++token_to_push)
+ {
+ mNameStack.push_back(std::make_pair(*token_to_push, newParseGeneration()));
+ num_tokens_pushed++;
+ }
+ mScope.push_back(mNameStack.back().first);
+ }
+ }
+
+ mTokenSizeStack.push_back(num_tokens_pushed);
+ readAttributes(atts);
+}
+
+bool LLSimpleXUIParser::readAttributes(const char **atts)
+{
+ typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+ boost::char_separator<char> sep(".");
+
+ bool any_parsed = false;
+ for(S32 i = 0; atts[i] && atts[i+1]; i += 2 )
+ {
+ std::string attribute_name(atts[i]);
+ mCurAttributeValueBegin = atts[i+1];
+
+ S32 num_tokens_pushed = 0;
+ tokenizer name_tokens(attribute_name, sep);
+ // copy remaining tokens on to our running token list
+ for(tokenizer::iterator token_to_push = name_tokens.begin(); token_to_push != name_tokens.end(); ++token_to_push)
+ {
+ mNameStack.push_back(std::make_pair(*token_to_push, newParseGeneration()));
+ num_tokens_pushed++;
+ }
+
+ // child nodes are not necessarily valid attributes, so don't complain once we've recursed
+ any_parsed |= mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently);
+
+ while(num_tokens_pushed-- > 0)
+ {
+ mNameStack.pop_back();
+ }
+ }
+ return any_parsed;
+}
+
+void LLSimpleXUIParser::processText()
+{
+ if (!mTextContents.empty())
+ {
+ LLStringUtil::trim(mTextContents);
+ if (!mTextContents.empty())
+ {
+ mNameStack.push_back(std::make_pair(std::string("value"), newParseGeneration()));
+ mCurAttributeValueBegin = mTextContents.c_str();
+ mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently);
+ mNameStack.pop_back();
+ }
+ mTextContents.clear();
+ }
+}
+
+void LLSimpleXUIParser::endElement(const char *name)
+{
+ processText();
+
+ if (--mOutputStack.back().second == 0)
+ {
+ if (mOutputStack.empty())
+ {
+ LL_ERRS("ReadXUI") << "Parameter block output stack popped while empty." << LL_ENDL;
+ }
+ mOutputStack.pop_back();
+ }
+
+ S32 num_tokens_to_pop = mTokenSizeStack.back();
+ mTokenSizeStack.pop_back();
+ while(num_tokens_to_pop-- > 0)
+ {
+ mNameStack.pop_back();
+ }
+ mScope.pop_back();
+}
+
+void LLSimpleXUIParser::characterData(const char *s, int len)
+{
+ mTextContents += std::string(s, len);
+}
+
+
+/*virtual*/ std::string LLSimpleXUIParser::getCurrentElementName()
+{
+ std::string full_name;
+ for (name_stack_t::iterator it = mNameStack.begin();
+ it != mNameStack.end();
+ ++it)
+ {
+ full_name += it->first + "."; // build up dotted names: "button.param.nestedparam."
+ }
+
+ return full_name;
+}
+
+const S32 LINE_NUMBER_HERE = 0;
+
+void LLSimpleXUIParser::parserWarning(const std::string& message)
+{
+#ifdef LL_WINDOWS
+ // use Visual Studo friendly formatting of output message for easy access to originating xml
+ llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), LINE_NUMBER_HERE, message.c_str()).c_str());
+ utf16str += '\n';
+ OutputDebugString(utf16str.c_str());
+#else
+ Parser::parserWarning(message);
+#endif
+}
+
+void LLSimpleXUIParser::parserError(const std::string& message)
+{
+#ifdef LL_WINDOWS
+ llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), LINE_NUMBER_HERE, message.c_str()).c_str());
+ utf16str += '\n';
+ OutputDebugString(utf16str.c_str());
+#else
+ Parser::parserError(message);
+#endif
+}
+
+bool LLSimpleXUIParser::readBoolValue(Parser& parser, void* val_ptr)
+{
+ LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+ if (!strcmp(self.mCurAttributeValueBegin, "true"))
+ {
+ *((bool*)val_ptr) = true;
+ return true;
+ }
+ else if (!strcmp(self.mCurAttributeValueBegin, "false"))
+ {
+ *((bool*)val_ptr) = false;
+ return true;
+ }
+
+ return false;
+}
+
+bool LLSimpleXUIParser::readStringValue(Parser& parser, void* val_ptr)
+{
+ LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+ *((std::string*)val_ptr) = self.mCurAttributeValueBegin;
+ return true;
+}
+
+bool LLSimpleXUIParser::readU8Value(Parser& parser, void* val_ptr)
+{
+ LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+ return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U8*)val_ptr)]).full;
+}
+
+bool LLSimpleXUIParser::readS8Value(Parser& parser, void* val_ptr)
+{
+ LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+ return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S8*)val_ptr)]).full;
+}
+
+bool LLSimpleXUIParser::readU16Value(Parser& parser, void* val_ptr)
+{
+ LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+ return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U16*)val_ptr)]).full;
+}
+
+bool LLSimpleXUIParser::readS16Value(Parser& parser, void* val_ptr)
+{
+ LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+ return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S16*)val_ptr)]).full;
+}
+
+bool LLSimpleXUIParser::readU32Value(Parser& parser, void* val_ptr)
+{
+ LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+ return parse(self.mCurAttributeValueBegin, uint_p[assign_a(*(U32*)val_ptr)]).full;
+}
+
+bool LLSimpleXUIParser::readS32Value(Parser& parser, void* val_ptr)
+{
+ LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+ return parse(self.mCurAttributeValueBegin, int_p[assign_a(*(S32*)val_ptr)]).full;
+}
+
+bool LLSimpleXUIParser::readF32Value(Parser& parser, void* val_ptr)
+{
+ LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+ return parse(self.mCurAttributeValueBegin, real_p[assign_a(*(F32*)val_ptr)]).full;
+}
+
+bool LLSimpleXUIParser::readF64Value(Parser& parser, void* val_ptr)
+{
+ LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+ return parse(self.mCurAttributeValueBegin, real_p[assign_a(*(F64*)val_ptr)]).full;
+}
+
+bool LLSimpleXUIParser::readColor4Value(Parser& parser, void* val_ptr)
+{
+ LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+ LLColor4 value;
+
+ if (parse(self.mCurAttributeValueBegin, real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full)
+ {
+ *(LLColor4*)(val_ptr) = value;
+ return true;
+ }
+ return false;
+}
+
+bool LLSimpleXUIParser::readUIColorValue(Parser& parser, void* val_ptr)
+{
+ LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+ LLColor4 value;
+ LLUIColor* colorp = (LLUIColor*)val_ptr;
+
+ if (parse(self.mCurAttributeValueBegin, real_p[assign_a(value.mV[0])] >> real_p[assign_a(value.mV[1])] >> real_p[assign_a(value.mV[2])] >> real_p[assign_a(value.mV[3])], space_p).full)
+ {
+ colorp->set(value);
+ return true;
+ }
+ return false;
+}
+
+bool LLSimpleXUIParser::readUUIDValue(Parser& parser, void* val_ptr)
+{
+ LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+ LLUUID temp_id;
+ // LLUUID::set is destructive, so use temporary value
+ if (temp_id.set(std::string(self.mCurAttributeValueBegin)))
+ {
+ *(LLUUID*)(val_ptr) = temp_id;
+ return true;
+ }
+ return false;
+}
+
+bool LLSimpleXUIParser::readSDValue(Parser& parser, void* val_ptr)
+{
+ LLSimpleXUIParser& self = static_cast<LLSimpleXUIParser&>(parser);
+ *((LLSD*)val_ptr) = LLSD(self.mCurAttributeValueBegin);
+ return true;
+}
diff --git a/indra/llxuixml/llxuiparser.h b/indra/llxuixml/llxuiparser.h
index 30b7e8c356..5c613b0c69 100644
--- a/indra/llxuixml/llxuiparser.h
+++ b/indra/llxuixml/llxuiparser.h
@@ -96,14 +96,12 @@ public:
-class LLXUIParser : public LLInitParam::Parser, public LLSingleton<LLXUIParser>
+class LLXUIParser : public LLInitParam::Parser
{
LOG_CLASS(LLXUIParser);
-protected:
- LLXUIParser();
- friend class LLSingleton<LLXUIParser>;
public:
+ LLXUIParser();
typedef LLInitParam::Parser::name_stack_t name_stack_t;
/*virtual*/ std::string getCurrentElementName();
@@ -114,42 +112,40 @@ public:
void writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const LLInitParam::BaseBlock* diff_block = NULL);
private:
- typedef std::list<std::pair<std::string, bool> > token_list_t;
-
- bool readXUIImpl(LLXMLNodePtr node, const std::string& scope, LLInitParam::BaseBlock& block);
+ bool readXUIImpl(LLXMLNodePtr node, LLInitParam::BaseBlock& block);
bool readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block);
//reader helper functions
- bool readBoolValue(void* val_ptr);
- bool readStringValue(void* val_ptr);
- bool readU8Value(void* val_ptr);
- bool readS8Value(void* val_ptr);
- bool readU16Value(void* val_ptr);
- bool readS16Value(void* val_ptr);
- bool readU32Value(void* val_ptr);
- bool readS32Value(void* val_ptr);
- bool readF32Value(void* val_ptr);
- bool readF64Value(void* val_ptr);
- bool readColor4Value(void* val_ptr);
- bool readUIColorValue(void* val_ptr);
- bool readUUIDValue(void* val_ptr);
- bool readSDValue(void* val_ptr);
+ static bool readBoolValue(Parser& parser, void* val_ptr);
+ static bool readStringValue(Parser& parser, void* val_ptr);
+ static bool readU8Value(Parser& parser, void* val_ptr);
+ static bool readS8Value(Parser& parser, void* val_ptr);
+ static bool readU16Value(Parser& parser, void* val_ptr);
+ static bool readS16Value(Parser& parser, void* val_ptr);
+ static bool readU32Value(Parser& parser, void* val_ptr);
+ static bool readS32Value(Parser& parser, void* val_ptr);
+ static bool readF32Value(Parser& parser, void* val_ptr);
+ static bool readF64Value(Parser& parser, void* val_ptr);
+ static bool readColor4Value(Parser& parser, void* val_ptr);
+ static bool readUIColorValue(Parser& parser, void* val_ptr);
+ static bool readUUIDValue(Parser& parser, void* val_ptr);
+ static bool readSDValue(Parser& parser, void* val_ptr);
//writer helper functions
- bool writeBoolValue(const void* val_ptr, const name_stack_t&);
- bool writeStringValue(const void* val_ptr, const name_stack_t&);
- bool writeU8Value(const void* val_ptr, const name_stack_t&);
- bool writeS8Value(const void* val_ptr, const name_stack_t&);
- bool writeU16Value(const void* val_ptr, const name_stack_t&);
- bool writeS16Value(const void* val_ptr, const name_stack_t&);
- bool writeU32Value(const void* val_ptr, const name_stack_t&);
- bool writeS32Value(const void* val_ptr, const name_stack_t&);
- bool writeF32Value(const void* val_ptr, const name_stack_t&);
- bool writeF64Value(const void* val_ptr, const name_stack_t&);
- bool writeColor4Value(const void* val_ptr, const name_stack_t&);
- bool writeUIColorValue(const void* val_ptr, const name_stack_t&);
- bool writeUUIDValue(const void* val_ptr, const name_stack_t&);
- bool writeSDValue(const void* val_ptr, const name_stack_t&);
+ static bool writeBoolValue(Parser& parser, const void* val_ptr, const name_stack_t&);
+ static bool writeStringValue(Parser& parser, const void* val_ptr, const name_stack_t&);
+ static bool writeU8Value(Parser& parser, const void* val_ptr, const name_stack_t&);
+ static bool writeS8Value(Parser& parser, const void* val_ptr, const name_stack_t&);
+ static bool writeU16Value(Parser& parser, const void* val_ptr, const name_stack_t&);
+ static bool writeS16Value(Parser& parser, const void* val_ptr, const name_stack_t&);
+ static bool writeU32Value(Parser& parser, const void* val_ptr, const name_stack_t&);
+ static bool writeS32Value(Parser& parser, const void* val_ptr, const name_stack_t&);
+ static bool writeF32Value(Parser& parser, const void* val_ptr, const name_stack_t&);
+ static bool writeF64Value(Parser& parser, const void* val_ptr, const name_stack_t&);
+ static bool writeColor4Value(Parser& parser, const void* val_ptr, const name_stack_t&);
+ static bool writeUIColorValue(Parser& parser, const void* val_ptr, const name_stack_t&);
+ static bool writeUUIDValue(Parser& parser, const void* val_ptr, const name_stack_t&);
+ static bool writeSDValue(Parser& parser, const void* val_ptr, const name_stack_t&);
LLXMLNodePtr getNode(const name_stack_t& stack);
@@ -165,6 +161,78 @@ private:
LLXMLNodePtr mLastWrittenChild;
S32 mCurReadDepth;
std::string mCurFileName;
+ std::string mRootNodeName;
+};
+
+// LLSimpleXUIParser is a streamlined SAX-based XUI parser that does not support localization
+// or parsing of a tree of independent param blocks, such as child widgets.
+// Use this for reading non-localized files that only need a single param block as a result.
+//
+// NOTE: In order to support nested block parsing, we need callbacks for start element that
+// push new blocks contexts on the mScope stack.
+// NOTE: To support localization without building a DOM, we need to enforce consistent
+// ordering of child elements from base file to localized diff file. Then we can use a pair
+// of coroutines to perform matching of xml nodes during parsing. Not sure if the overhead
+// of coroutines would offset the gain from SAX parsing
+
+class LLSimpleXUIParser : public LLInitParam::Parser
+{
+LOG_CLASS(LLSimpleXUIParser);
+public:
+ typedef LLInitParam::Parser::name_stack_t name_stack_t;
+ typedef LLInitParam::BaseBlock* (*element_start_callback_t)(LLSimpleXUIParser&, const char* block_name);
+
+ LLSimpleXUIParser(element_start_callback_t element_cb = NULL);
+ virtual ~LLSimpleXUIParser();
+
+ /*virtual*/ std::string getCurrentElementName();
+ /*virtual*/ void parserWarning(const std::string& message);
+ /*virtual*/ void parserError(const std::string& message);
+
+ bool readXUI(const std::string& filename, LLInitParam::BaseBlock& block, bool silent=false);
+
+
+private:
+ //reader helper functions
+ static bool readBoolValue(Parser&, void* val_ptr);
+ static bool readStringValue(Parser&, void* val_ptr);
+ static bool readU8Value(Parser&, void* val_ptr);
+ static bool readS8Value(Parser&, void* val_ptr);
+ static bool readU16Value(Parser&, void* val_ptr);
+ static bool readS16Value(Parser&, void* val_ptr);
+ static bool readU32Value(Parser&, void* val_ptr);
+ static bool readS32Value(Parser&, void* val_ptr);
+ static bool readF32Value(Parser&, void* val_ptr);
+ static bool readF64Value(Parser&, void* val_ptr);
+ static bool readColor4Value(Parser&, void* val_ptr);
+ static bool readUIColorValue(Parser&, void* val_ptr);
+ static bool readUUIDValue(Parser&, void* val_ptr);
+ static bool readSDValue(Parser&, void* val_ptr);
+
+private:
+ static void startElementHandler(void *userData, const char *name, const char **atts);
+ static void endElementHandler(void *userData, const char *name);
+ static void characterDataHandler(void *userData, const char *s, int len);
+
+ void startElement(const char *name, const char **atts);
+ void endElement(const char *name);
+ void characterData(const char *s, int len);
+ bool readAttributes(const char **atts);
+ void processText();
+
+ Parser::name_stack_t mNameStack;
+ struct XML_ParserStruct* mParser;
+ S32 mLastWriteGeneration;
+ LLXMLNodePtr mLastWrittenChild;
+ S32 mCurReadDepth;
+ std::string mCurFileName;
+ std::string mTextContents;
+ const char* mCurAttributeValueBegin;
+ std::vector<S32> mTokenSizeStack;
+ std::vector<std::string> mScope;
+ element_start_callback_t mElementCB;
+
+ std::vector<std::pair<LLInitParam::BaseBlock*, S32> > mOutputStack;
};