Apertura del repositorio

This commit is contained in:
2025-05-24 18:09:39 -03:00
parent 76e6359dad
commit d883ddd0d0
35253 changed files with 2891973 additions and 2 deletions
+58
View File
@@ -0,0 +1,58 @@
# -*- cmake -*-
project(llxml)
include(00-Common)
include(LLCommon)
set(llxml_SOURCE_FILES
llcontrol.cpp
llxmlnode.cpp
llxmlparser.cpp
llxmltree.cpp
)
set(llxml_HEADER_FILES
CMakeLists.txt
llcontrol.h
llxmlnode.h
llxmlparser.h
llxmltree.h
)
list(APPEND llxml_SOURCE_FILES ${llxml_HEADER_FILES})
add_library (llxml ${llxml_SOURCE_FILES})
# Libraries on which this library depends, needed for Linux builds
# Sort by high-level to low-level
target_link_libraries( llxml
llfilesystem
llmath
llcommon
ll::expat
)
target_include_directories( llxml INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
# tests
if (LL_TESTS)
# unit tests
SET(llxml_TEST_SOURCE_FILES
# none yet!
)
LL_ADD_PROJECT_UNIT_TESTS(llxml "${llxml_TEST_SOURCE_FILES}")
# integration tests
# set(TEST_DEBUG on)
set(test_libs
llxml
llmath
llcommon
)
LL_ADD_INTEGRATION_TEST(llcontrol "" "${test_libs}")
endif (LL_TESTS)
File diff suppressed because it is too large Load Diff
+497
View File
@@ -0,0 +1,497 @@
/**
* @file llcontrol.h
* @brief A mechanism for storing "control state" for a program
*
* $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_LLCONTROL_H
#define LL_LLCONTROL_H
#include "llboost.h"
#include "llevent.h"
#include "llstring.h"
#include "llrect.h"
#include "llrefcount.h"
#include "llinstancetracker.h"
#include <vector>
#include <boost/bind.hpp>
#include <boost/signals2.hpp>
class LLVector3;
class LLVector3d;
class LLQuaternion;
class LLColor4;
class LLColor3;
// if this is changed, also modify mTypeString in llcontrol.h
typedef enum e_control_type
{
TYPE_U32 = 0,
TYPE_S32,
TYPE_F32,
TYPE_BOOLEAN,
TYPE_STRING,
TYPE_VEC3,
TYPE_VEC3D,
TYPE_QUAT,
TYPE_RECT,
TYPE_COL4,
TYPE_COL3,
TYPE_LLSD,
TYPE_COUNT
} eControlType;
typedef enum e_sanity_type
{
SANITY_TYPE_NONE = 0,
SANITY_TYPE_EQUALS,
SANITY_TYPE_NOT_EQUALS,
SANITY_TYPE_LESS_THAN,
SANITY_TYPE_GREATER_THAN,
SANITY_TYPE_LESS_THAN_EQUALS,
SANITY_TYPE_GREATER_THAN_EQUALS,
SANITY_TYPE_BETWEEN,
SANITY_TYPE_NOT_BETWEEN,
SANITY_TYPE_COUNT
} eSanityType;
class LLControlVariable : public LLRefCount
{
LOG_CLASS(LLControlVariable);
friend class LLControlGroup;
public:
typedef boost::signals2::signal<bool(LLControlVariable* control, const LLSD&), boost_boolean_combiner> validate_signal_t;
typedef boost::signals2::signal<void(LLControlVariable* control, const LLSD&, const LLSD&)> commit_signal_t;
typedef boost::signals2::signal<void(LLControlVariable* control, const LLSD&)> sanity_signal_t;
enum ePersist
{
PERSIST_NO, // don't save this var
PERSIST_NONDFT, // save this var if differs from default
PERSIST_ALWAYS // save this var even if has default value
};
private:
std::string mName;
std::string mComment;
eControlType mType;
eSanityType mSanityType;
std::string mSanityComment;
ePersist mPersist;
bool mCanBackup; // <FS:Zi> Backup Settings
bool mHideFromSettingsEditor;
std::vector<LLSD> mValues;
std::vector<LLSD> mSanityValues;
commit_signal_t mCommitSignal;
validate_signal_t mValidateSignal;
sanity_signal_t mSanitySignal;
public:
LLControlVariable(const std::string& name, eControlType type,
LLSD initial, const std::string& comment,
eSanityType sanityType,
LLSD sanityValues,
const std::string& sanityComment,
// <FS:Zi> Backup Settings
// ePersist persist = PERSIST_NONDFT, bool hidefromsettingseditor = false
ePersist persist = PERSIST_NONDFT, bool can_backup = true, bool hidefromsettingseditor = false
// </FS:Zi>
);
virtual ~LLControlVariable();
const std::string& getName() const { return mName; }
const std::string& getComment() const { return mComment; }
eSanityType getSanityType() { return mSanityType; }
const std::string& getSanityComment() const { return mSanityComment; }
const std::vector<LLSD>& getSanityValues() { return mSanityValues; };
eControlType type() { return mType; }
bool isType(eControlType tp) { return tp == mType; }
void resetToDefault(bool fire_signal = false);
commit_signal_t* getSignal() { return &mCommitSignal; } // shorthand for commit signal
commit_signal_t* getCommitSignal() { return &mCommitSignal; }
validate_signal_t* getValidateSignal() { return &mValidateSignal; }
sanity_signal_t* getSanitySignal() { return &mSanitySignal; }
// [RLVa:KB] - Patch: RLVa-2.1.0
bool hasUnsavedValue() { return mValues.size() > 2; }
// [/RLVa:KB]
bool isDefault() { return (mValues.size() == 1); }
bool isSane();
bool shouldSave(bool nondefault_only);
bool isPersisted() { return mPersist != PERSIST_NO; }
bool isBackupable() { return mCanBackup; } // <FS:Zi> Backup Settings
bool isHiddenFromSettingsEditor() { return mHideFromSettingsEditor; }
LLSD get() const { return getValue(); }
LLSD getValue() const { return mValues.back(); }
LLSD getDefault() const { return mValues.front(); }
LLSD getSaveValue() const;
void set(const LLSD& val) { setValue(val); }
void setValue(const LLSD& value, bool saved_value = true);
void setDefaultValue(const LLSD& value);
void setPersist(ePersist);
void setBackupable(bool state); // <FS:Zi> Backup Settings
void setHiddenFromSettingsEditor(bool hide);
void setComment(const std::string& comment);
private:
void firePropertyChanged(const LLSD &pPreviousValue)
{
mCommitSignal(this, mValues.back(), pPreviousValue);
}
LLSD getComparableValue(const LLSD& value);
bool llsd_compare(const LLSD& a, const LLSD & b);
};
typedef LLPointer<LLControlVariable> LLControlVariablePtr;
//! Helper functions for converting between static types and LLControl values
template <class T>
eControlType get_control_type()
{
LL_WARNS() << "Usupported control type: " << typeid(T).name() << "." << LL_ENDL;
return TYPE_COUNT;
}
template <class T>
LLSD convert_to_llsd(const T& in)
{
// default implementation
return LLSD(in);
}
template <class T>
T convert_from_llsd(const LLSD& sd, eControlType type, std::string_view control_name)
{
// needs specialization
return T(sd);
}
//const U32 STRING_CACHE_SIZE = 10000;
class LLControlGroup : public LLInstanceTracker<LLControlGroup, std::string>
{
LOG_CLASS(LLControlGroup);
protected:
typedef std::map<std::string, LLControlVariablePtr, std::less<> > ctrl_name_table_t;
ctrl_name_table_t mNameTable;
static const std::string mTypeString[TYPE_COUNT];
static const std::string mSanityTypeString[SANITY_TYPE_COUNT];
public:
static eControlType typeStringToEnum(const std::string& typestr);
static eSanityType sanityTypeStringToEnum(const std::string& sanitystr);
static std::string typeEnumToString(eControlType typeenum);
static std::string sanityTypeEnumToString(eSanityType sanitytypeenum);
LLControlGroup(const std::string& name);
~LLControlGroup();
void cleanup();
LLControlVariablePtr getControl(std::string_view name);
struct ApplyFunctor
{
virtual ~ApplyFunctor() {};
virtual void apply(const std::string& name, LLControlVariable* control) = 0;
};
void applyToAll(ApplyFunctor* func);
// <FS:Zi> Backup Settings
//LLControlVariable* declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, LLControlVariable::ePersist persist, bool hidefromsettingseditor = false);
LLControlVariable* declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, eSanityType sanity_type, LLSD sanity_value, const std::string& sanity_comment, LLControlVariable::ePersist persist, bool can_backup = true, bool hidefromsettingseditor = false);
// </FS:Zi>
LLControlVariable* declareU32(const std::string& name, U32 initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
LLControlVariable* declareS32(const std::string& name, S32 initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
LLControlVariable* declareF32(const std::string& name, F32 initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
LLControlVariable* declareBOOL(const std::string& name, bool initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
LLControlVariable* declareString(const std::string& name, const std::string &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
LLControlVariable* declareVec3(const std::string& name, const LLVector3 &initial_val,const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
LLControlVariable* declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
LLControlVariable* declareQuat(const std::string& name, const LLQuaternion &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
LLControlVariable* declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
LLControlVariable* declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
LLControlVariable* declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
LLControlVariable* declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT);
std::string getString(std::string_view name);
std::string getText(std::string_view name);
bool getBOOL(std::string_view name);
S32 getS32(std::string_view name);
F32 getF32(std::string_view name);
U32 getU32(std::string_view name);
LLWString getWString(std::string_view name);
LLVector3 getVector3(std::string_view name);
LLVector3d getVector3d(std::string_view name);
LLRect getRect(std::string_view name);
LLSD getLLSD(std::string_view name);
LLQuaternion getQuaternion(std::string_view name);
LLColor4 getColor(std::string_view name);
LLColor4 getColor4(std::string_view name);
LLColor3 getColor3(std::string_view name);
LLSD asLLSD(bool diffs_only);
// generic getter
template<typename T> T get(std::string_view name)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD;
LLControlVariable* control = getControl(name);
LLSD value;
eControlType type = TYPE_COUNT;
if (control)
{
value = control->get();
type = control->type();
}
else
{
LL_WARNS() << "Control " << name << " not found." << LL_ENDL;
return T();
}
return convert_from_llsd<T>(value, type, name);
}
void setBOOL(std::string_view name, bool val);
void setS32(std::string_view name, S32 val);
void setF32(std::string_view name, F32 val);
void setU32(std::string_view name, U32 val);
void setString(std::string_view name, const std::string& val);
void setVector3(std::string_view name, const LLVector3 &val);
void setVector3d(std::string_view name, const LLVector3d &val);
void setQuaternion(std::string_view name, const LLQuaternion &val);
void setRect(std::string_view name, const LLRect &val);
void setColor4(std::string_view name, const LLColor4 &val);
void setLLSD(std::string_view name, const LLSD& val);
// type agnostic setter that takes LLSD
void setUntypedValue(std::string_view name, const LLSD& val);
// generic setter
template<typename T> void set(std::string_view name, const T& val)
{
LLControlVariable* control = getControl(name);
if (control && control->isType(get_control_type<T>()))
{
control->set(convert_to_llsd(val));
}
else
{
LL_WARNS() << "Invalid control " << name << LL_ENDL;
}
}
bool controlExists(std::string_view name);
// Returns number of controls loaded, 0 if failed
// If require_declaration is false, will auto-declare controls it finds
// as the given type.
U32 loadFromFileLegacy(const std::string& filename, bool require_declaration = true, eControlType declare_as = TYPE_STRING);
U32 saveToFile(const std::string& filename, bool nondefault_only);
U32 loadFromFile(const std::string& filename, bool default_values = false, bool save_values = true);
void resetToDefaults();
void incrCount(std::string_view name);
bool mSettingsProfile;
};
//! Publish/Subscribe object to interact with LLControlGroups.
//! Use an LLCachedControl instance to connect to a LLControlVariable
//! without have to manually create and bind a listener to a local
//! object.
template <class T>
class LLControlCache : public LLRefCount, public LLInstanceTracker<LLControlCache<T>, std::string>
{
public:
// This constructor will declare a control if it doesn't exist in the contol group
LLControlCache(LLControlGroup& group,
const std::string& name,
const T& default_value,
const std::string& comment)
: LLInstanceTracker<LLControlCache<T>, std::string >(name)
{
if(!group.controlExists(name))
{
if(!declareTypedControl(group, name, default_value, comment))
{
LL_ERRS() << "The control could not be created!!!" << LL_ENDL;
}
}
bindToControl(group, name);
}
LLControlCache(LLControlGroup& group,
const std::string& name)
: LLInstanceTracker<LLControlCache<T>, std::string >(name)
{
if(!group.controlExists(name))
{
LL_ERRS() << "Control named \"" << name << "\" not found." << LL_ENDL;
}
bindToControl(group, name);
}
~LLControlCache()
{
}
const T& getValue() const { return mCachedValue; }
private:
void bindToControl(LLControlGroup& group, const std::string& name)
{
LLControlVariablePtr controlp = group.getControl(name);
mType = controlp->type();
mCachedValue = convert_from_llsd<T>(controlp->get(), mType, name);
// Add a listener to the controls signal...
// NOTE: All listeners connected to 0 group, for guaranty that variable handlers (gSavedSettings) call last
mConnection = controlp->getSignal()->connect(0,
boost::bind(&LLControlCache<T>::handleValueChange, this, _2)
);
mType = controlp->type();
}
bool declareTypedControl(LLControlGroup& group,
const std::string& name,
const T& default_value,
const std::string& comment)
{
LLSD init_value;
eControlType type = get_control_type<T>();
init_value = convert_to_llsd(default_value);
if(type < TYPE_COUNT)
{
// <FS:Zi> Backup Settings
// group.declareControl(name, type, init_value, comment, SANITY_TYPE_NONE, LLSD(), std::string(""), LLControlVariable::PERSIST_NO);
group.declareControl(name, type, init_value, comment, SANITY_TYPE_NONE, LLSD(), std::string(""), LLControlVariable::PERSIST_NO);
// </FS_Zi>
return true;
}
return false;
}
bool handleValueChange(const LLSD& newvalue)
{
mCachedValue = convert_from_llsd<T>(newvalue, mType, "");
return true;
}
private:
T mCachedValue;
eControlType mType;
boost::signals2::scoped_connection mConnection;
};
template <typename T>
class LLCachedControl
{
public:
LLCachedControl(LLControlGroup& group,
const std::string& name,
const T& default_value,
const std::string& comment = "Declared In Code")
{
mCachedControlPtr = LLControlCache<T>::getInstance(name).get();
if (! mCachedControlPtr)
{
mCachedControlPtr = new LLControlCache<T>(group, name, default_value, comment);
}
}
LLCachedControl(LLControlGroup& group,
const std::string& name)
{
mCachedControlPtr = LLControlCache<T>::getInstance(name).get();
if (! mCachedControlPtr)
{
mCachedControlPtr = new LLControlCache<T>(group, name);
}
}
operator const T&() const { return mCachedControlPtr->getValue(); }
operator boost::function<const T&()> () const { return boost::function<const T&()>(*this); }
const T& operator()() { return mCachedControlPtr->getValue(); }
private:
LLPointer<LLControlCache<T> > mCachedControlPtr;
};
template <> eControlType get_control_type<U32>();
template <> eControlType get_control_type<S32>();
template <> eControlType get_control_type<F32>();
template <> eControlType get_control_type<bool>();
template <> eControlType get_control_type<std::string>();
template <> eControlType get_control_type<LLVector3>();
template <> eControlType get_control_type<LLVector3d>();
template <> eControlType get_control_type<LLQuaternion>();
template <> eControlType get_control_type<LLRect>();
template <> eControlType get_control_type<LLColor4>();
template <> eControlType get_control_type<LLColor3>();
template <> eControlType get_control_type<LLSD>();
template <> LLSD convert_to_llsd<U32>(const U32& in);
template <> LLSD convert_to_llsd<LLVector3>(const LLVector3& in);
template <> LLSD convert_to_llsd<LLVector3d>(const LLVector3d& in);
template <> LLSD convert_to_llsd<LLQuaternion>(const LLQuaternion& in);
template <> LLSD convert_to_llsd<LLRect>(const LLRect& in);
template <> LLSD convert_to_llsd<LLColor4>(const LLColor4& in);
template <> LLSD convert_to_llsd<LLColor3>(const LLColor3& in);
template<> std::string convert_from_llsd<std::string>(const LLSD& sd, eControlType type, std::string_view control_name);
template<> LLWString convert_from_llsd<LLWString>(const LLSD& sd, eControlType type, std::string_view control_name);
template<> LLVector3 convert_from_llsd<LLVector3>(const LLSD& sd, eControlType type, std::string_view control_name);
template<> LLVector3d convert_from_llsd<LLVector3d>(const LLSD& sd, eControlType type, std::string_view control_name);
template<> LLQuaternion convert_from_llsd<LLQuaternion>(const LLSD& sd, eControlType type, std::string_view control_name);
template<> LLRect convert_from_llsd<LLRect>(const LLSD& sd, eControlType type, std::string_view control_name);
template<> bool convert_from_llsd<bool>(const LLSD& sd, eControlType type, std::string_view control_name);
template<> S32 convert_from_llsd<S32>(const LLSD& sd, eControlType type, std::string_view control_name);
template<> F32 convert_from_llsd<F32>(const LLSD& sd, eControlType type, std::string_view control_name);
template<> U32 convert_from_llsd<U32>(const LLSD& sd, eControlType type, std::string_view control_name);
template<> LLColor3 convert_from_llsd<LLColor3>(const LLSD& sd, eControlType type, std::string_view control_name);
template<> LLColor4 convert_from_llsd<LLColor4>(const LLSD& sd, eControlType type, std::string_view control_name);
template<> LLSD convert_from_llsd<LLSD>(const LLSD& sd, eControlType type, std::string_view control_name);
//#define TEST_CACHED_CONTROL 1
#ifdef TEST_CACHED_CONTROL
void test_cached_control();
#endif // TEST_CACHED_CONTROL
#endif
File diff suppressed because it is too large Load Diff
+341
View File
@@ -0,0 +1,341 @@
/**
* @file llxmlnode.h
* @brief LLXMLNode definition
*
* $LicenseInfo:firstyear=2000&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_LLXMLNODE_H
#define LL_LLXMLNODE_H
#ifndef XML_STATIC
#define XML_STATIC
#endif
#ifdef LL_USESYSTEMLIBS
#include <expat.h>
#else
#include "expat/expat.h"
#endif
#include <map>
#include "indra_constants.h"
#include "llrefcount.h"
#include "llpointer.h"
#include "llstring.h"
#include "llstringtable.h"
#include "llfile.h"
#include "lluuid.h"
class LLVector3;
class LLVector3d;
class LLQuaternion;
class LLColor4;
class LLColor4U;
class LLSD;
struct CompareAttributes
{
bool operator()(const LLStringTableEntry* const lhs, const LLStringTableEntry* const rhs) const
{
if (lhs == NULL)
return true;
if (rhs == NULL)
return true;
return strcmp(lhs->mString, rhs->mString) < 0;
}
};
// Defines a simple node hierarchy for reading and writing task objects
class LLXMLNode;
typedef LLPointer<LLXMLNode> LLXMLNodePtr;
typedef std::multimap<std::string, LLXMLNodePtr > LLXMLNodeList;
typedef std::multimap<const LLStringTableEntry *, LLXMLNodePtr > LLXMLChildList;
typedef std::map<const LLStringTableEntry *, LLXMLNodePtr, CompareAttributes> LLXMLAttribList;
class LLColor4;
class LLColor4U;
class LLQuaternion;
class LLVector3;
class LLVector3d;
class LLVector4;
class LLVector4U;
struct LLXMLChildren : public LLThreadSafeRefCount
{
LLXMLChildList map; // Map of children names->pointers
LLXMLNodePtr head; // Head of the double-linked list
LLXMLNodePtr tail; // Tail of the double-linked list
};
typedef LLPointer<LLXMLChildren> LLXMLChildrenPtr;
class LLXMLNode : public LLThreadSafeRefCount
{
public:
enum ValueType
{
TYPE_CONTAINER, // A node which contains nodes
TYPE_UNKNOWN, // A node loaded from file without a specified type
TYPE_BOOLEAN, // "true" or "false"
TYPE_INTEGER, // any integer type: U8, U32, S32, U64, etc.
TYPE_FLOAT, // any floating point type: F32, F64
TYPE_STRING, // a string
TYPE_UUID, // a UUID
TYPE_NODEREF, // the ID of another node in the hierarchy to reference
};
enum Encoding
{
ENCODING_DEFAULT = 0,
ENCODING_DECIMAL,
ENCODING_HEX,
// ENCODING_BASE32, // Not implemented yet
};
protected:
~LLXMLNode();
public:
LLXMLNode();
LLXMLNode(const char* name, bool is_attribute);
LLXMLNode(LLStringTableEntry* name, bool is_attribute);
LLXMLNode(const LLXMLNode& rhs);
LLXMLNodePtr deepCopy();
bool isNull();
bool deleteChild(LLXMLNode* child);
void addChild(LLXMLNodePtr& new_child);
void setParent(LLXMLNodePtr& new_parent); // reparent if necessary
// Deserialization
static bool parseFile(
const std::string& filename,
LLXMLNodePtr& node,
LLXMLNode* defaults = nullptr);
static bool parseBuffer(
const char* buffer,
U64 length,
LLXMLNodePtr& node,
LLXMLNode* defaults = nullptr);
static bool parseStream(
std::istream& str,
LLXMLNodePtr& node,
LLXMLNode* defaults = nullptr);
static bool updateNode(
LLXMLNodePtr& node,
LLXMLNodePtr& update_node);
static bool getLayeredXMLNode(LLXMLNodePtr& root, const std::vector<std::string>& paths);
// Write standard XML file header:
// <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
static void writeHeaderToFile(LLFILE *out_file);
// Write XML to file with one attribute per line.
// XML escapes values as they are written.
void writeToFile(LLFILE *out_file, const std::string& indent = std::string(), bool use_type_decorations=true);
void writeToOstream(std::ostream& output_stream, const std::string& indent = std::string(), bool use_type_decorations=true);
// Utility
void findName(const std::string& name, LLXMLNodeList &results);
void findName(LLStringTableEntry* name, LLXMLNodeList &results);
void findID(const std::string& id, LLXMLNodeList &results);
virtual LLXMLNodePtr createChild(const char* name, bool is_attribute);
virtual LLXMLNodePtr createChild(LLStringTableEntry* name, bool is_attribute);
// Getters
U32 getBoolValue(U32 expected_length, bool *array);
U32 getByteValue(U32 expected_length, U8 *array, Encoding encoding = ENCODING_DEFAULT);
U32 getIntValue(U32 expected_length, S32 *array, Encoding encoding = ENCODING_DEFAULT);
U32 getUnsignedValue(U32 expected_length, U32 *array, Encoding encoding = ENCODING_DEFAULT);
U32 getLongValue(U32 expected_length, U64 *array, Encoding encoding = ENCODING_DEFAULT);
U32 getFloatValue(U32 expected_length, F32 *array, Encoding encoding = ENCODING_DEFAULT);
U32 getDoubleValue(U32 expected_length, F64 *array, Encoding encoding = ENCODING_DEFAULT);
U32 getStringValue(U32 expected_length, std::string *array);
U32 getUUIDValue(U32 expected_length, LLUUID *array);
U32 getNodeRefValue(U32 expected_length, LLXMLNode **array);
bool hasAttribute(const char* name );
bool getAttributeBOOL(const char* name, bool& value );
bool getAttributeU8(const char* name, U8& value );
bool getAttributeS8(const char* name, S8& value );
bool getAttributeU16(const char* name, U16& value );
bool getAttributeS16(const char* name, S16& value );
bool getAttributeU32(const char* name, U32& value );
bool getAttributeS32(const char* name, S32& value );
bool getAttributeF32(const char* name, F32& value );
bool getAttributeF64(const char* name, F64& value );
bool getAttributeColor(const char* name, LLColor4& value );
bool getAttributeColor4(const char* name, LLColor4& value );
bool getAttributeColor4U(const char* name, LLColor4U& value );
bool getAttributeVector3(const char* name, LLVector3& value );
bool getAttributeVector3d(const char* name, LLVector3d& value );
bool getAttributeQuat(const char* name, LLQuaternion& value );
bool getAttributeUUID(const char* name, LLUUID& value );
bool getAttributeString(const char* name, std::string& value );
const ValueType& getType() const { return mType; }
U32 getLength() const { return mLength; }
U32 getPrecision() const { return mPrecision; }
const std::string& getValue() const { return mValue; }
std::string getSanitizedValue() const;
std::string getTextContents() const;
const LLStringTableEntry* getName() const { return mName; }
bool hasName(const char* name) const { return mName == gStringTable.checkStringEntry(name); }
bool hasName(const std::string& name) const { return mName == gStringTable.checkStringEntry(name.c_str()); }
const std::string& getID() const { return mID; }
U32 getChildCount() const;
// getChild returns a Null LLXMLNode (not a NULL pointer) if there is no such child.
// This child has no value so any getTYPEValue() calls on it will return 0.
bool getChild(const char* name, LLXMLNodePtr& node, bool use_default_if_missing = true);
bool getChild(const LLStringTableEntry* name, LLXMLNodePtr& node, bool use_default_if_missing = true);
void getChildren(const char* name, LLXMLNodeList &children, bool use_default_if_missing = true) const;
void getChildren(const LLStringTableEntry* name, LLXMLNodeList &children, bool use_default_if_missing = true) const;
// recursively finds all children at any level matching name
void getDescendants(const LLStringTableEntry* name, LLXMLNodeList &children) const;
bool getAttribute(const char* name, LLXMLNodePtr& node, bool use_default_if_missing = true);
bool getAttribute(const LLStringTableEntry* name, LLXMLNodePtr& node, bool use_default_if_missing = true);
S32 getLineNumber();
// The following skip over attributes
LLXMLNodePtr getFirstChild() const;
LLXMLNodePtr getNextSibling() const;
LLXMLNodePtr getRoot();
// Setters
bool setAttributeString(const char* attr, const std::string& value);
void setBoolValue(const bool value) { setBoolValue(1, &value); }
void setByteValue(const U8 value, Encoding encoding = ENCODING_DEFAULT) { setByteValue(1, &value, encoding); }
void setIntValue(const S32 value, Encoding encoding = ENCODING_DEFAULT) { setIntValue(1, &value, encoding); }
void setUnsignedValue(const U32 value, Encoding encoding = ENCODING_DEFAULT) { setUnsignedValue(1, &value, encoding); }
void setLongValue(const U64 value, Encoding encoding = ENCODING_DEFAULT) { setLongValue(1, &value, encoding); }
void setFloatValue(const F32 value, Encoding encoding = ENCODING_DEFAULT, U32 precision = 0) { setFloatValue(1, &value, encoding); }
void setDoubleValue(const F64 value, Encoding encoding = ENCODING_DEFAULT, U32 precision = 0) { setDoubleValue(1, &value, encoding); }
void setStringValue(const std::string& value) { setStringValue(1, &value); }
void setUUIDValue(const LLUUID value) { setUUIDValue(1, &value); }
void setNodeRefValue(const LLXMLNode *value) { setNodeRefValue(1, &value); }
void setBoolValue(U32 length, const bool *array);
void setByteValue(U32 length, const U8 *array, Encoding encoding = ENCODING_DEFAULT);
void setIntValue(U32 length, const S32 *array, Encoding encoding = ENCODING_DEFAULT);
void setUnsignedValue(U32 length, const U32* array, Encoding encoding = ENCODING_DEFAULT);
void setLongValue(U32 length, const U64 *array, Encoding encoding = ENCODING_DEFAULT);
void setFloatValue(U32 length, const F32 *array, Encoding encoding = ENCODING_DEFAULT, U32 precision = 0);
void setDoubleValue(U32 length, const F64 *array, Encoding encoding = ENCODING_DEFAULT, U32 precision = 0);
void setStringValue(U32 length, const std::string *array);
void setUUIDValue(U32 length, const LLUUID *array);
void setNodeRefValue(U32 length, const LLXMLNode **array);
void setValue(const std::string& value);
void setName(const std::string& name);
void setName(LLStringTableEntry* name);
void setLineNumber(S32 line_number);
// Escapes " (quot) ' (apos) & (amp) < (lt) > (gt)
static std::string escapeXML(const std::string& xml);
// Set the default node corresponding to this default node
void setDefault(LLXMLNode *default_node);
// Find the node within defaults_list which corresponds to this node
void findDefault(LLXMLNode *defaults_list);
void updateDefault();
// Delete any child nodes that aren't among the tree's children, recursive
void scrubToTree(LLXMLNode *tree);
bool deleteChildren(const std::string& name);
bool deleteChildren(LLStringTableEntry* name);
void setAttributes(ValueType type, U32 precision, Encoding encoding, U32 length);
// void appendValue(const std::string& value); // Unused
bool fromXMLRPCValue(LLSD& target);
// Unit Testing
void createUnitTest(S32 max_num_children);
bool performUnitTest(std::string &error_buffer);
protected:
bool removeChild(LLXMLNode* child);
bool isFullyDefault();
std::string getXMLRPCTextContents() const;
bool parseXmlRpcArrayValue(LLSD& target);
bool parseXmlRpcStructValue(LLSD& target);
public:
std::string mID; // The ID attribute of this node
XML_Parser *mParser; // Temporary pointer while loading
bool mIsAttribute; // Flag is only used for output formatting
U32 mVersionMajor; // Version of this tag to use
U32 mVersionMinor;
U32 mLength; // If the length is nonzero, then only return arrays of this length
U32 mPrecision; // The number of BITS per array item
ValueType mType; // The value type
Encoding mEncoding; // The value encoding
S32 mLineNumber; // line number in source file, if applicable
LLXMLNode* mParent; // The parent node
LLXMLChildrenPtr mChildren; // The child nodes
LLXMLAttribList mAttributes; // The attribute nodes
LLXMLNodePtr mPrev; // Double-linked list previous node
LLXMLNodePtr mNext; // Double-linked list next node
static bool sStripEscapedStrings;
static bool sStripWhitespaceValues;
protected:
LLStringTableEntry *mName; // The name of this node
// The value of this node (use getters/setters only)
// Values are not XML-escaped in memory
// They may contain " (quot) ' (apos) & (amp) < (lt) > (gt)
std::string mValue;
LLXMLNodePtr mDefault; // Mirror node in the default tree
static const char *skipWhitespace(const char *str);
static const char *skipNonWhitespace(const char *str);
static const char *parseInteger(const char *str, U64 *dest, bool *is_negative, U32 precision, Encoding encoding);
static const char *parseFloat(const char *str, F64 *dest, U32 precision, Encoding encoding);
};
#endif // LL_LLXMLNODE
+416
View File
@@ -0,0 +1,416 @@
/**
* @file llxmlparser.cpp
* @brief LLXmlParser implementation
*
* $LicenseInfo:firstyear=2002&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$
*/
// llxmlparser.cpp
//
// copyright 2002, linden research inc
#include "linden_common.h"
#include "llxmlparser.h"
#include "llerror.h"
LLXmlParser::LLXmlParser()
:
mParser( NULL ),
mDepth( 0 )
{
mAuxErrorString = "no error";
// Override the document's declared encoding.
mParser = XML_ParserCreate(NULL);
XML_SetUserData(mParser, this);
XML_SetElementHandler( mParser, startElementHandler, endElementHandler);
XML_SetCharacterDataHandler( mParser, characterDataHandler);
XML_SetProcessingInstructionHandler( mParser, processingInstructionHandler);
XML_SetCommentHandler( mParser, commentHandler);
XML_SetCdataSectionHandler( mParser, startCdataSectionHandler, endCdataSectionHandler);
// This sets the default handler but does not inhibit expansion of internal entities.
// The entity reference will not be passed to the default handler.
XML_SetDefaultHandlerExpand( mParser, defaultDataHandler);
XML_SetUnparsedEntityDeclHandler( mParser, unparsedEntityDeclHandler);
}
LLXmlParser::~LLXmlParser()
{
XML_ParserFree( mParser );
}
bool LLXmlParser::parseFile(const std::string &path)
{
llassert( !mDepth );
bool success = true;
LLFILE* file = LLFile::fopen(path, "rb"); /* Flawfinder: ignore */
if( !file )
{
mAuxErrorString = llformat( "Couldn't open file %s", path.c_str());
success = false;
}
else
{
S32 bytes_read = 0;
fseek(file, 0L, SEEK_END);
S32 buffer_size = ftell(file);
fseek(file, 0L, SEEK_SET);
void* buffer = XML_GetBuffer(mParser, buffer_size);
if( !buffer )
{
mAuxErrorString = llformat( "Unable to allocate XML buffer while reading file %s", path.c_str() );
success = false;
goto exit_label;
}
bytes_read = (S32)fread(buffer, 1, buffer_size, file);
if( bytes_read <= 0 )
{
mAuxErrorString = llformat( "Error while reading file %s", path.c_str() );
success = false;
goto exit_label;
}
if( !XML_ParseBuffer(mParser, bytes_read, true ) )
{
mAuxErrorString = llformat( "Error while parsing file %s", path.c_str() );
success = false;
}
exit_label:
fclose( file );
}
if( success )
{
llassert( !mDepth );
}
mDepth = 0;
if( !success )
{
LL_WARNS() << mAuxErrorString << LL_ENDL;
}
return success;
}
// Parses some input. Returns 0 if a fatal error is detected.
// The last call must have isFinal true;
// len may be zero for this call (or any other).
S32 LLXmlParser::parse( const char* buf, int len, int isFinal )
{
return XML_Parse(mParser, buf, len, isFinal);
}
const char* LLXmlParser::getErrorString()
{
const char* error_string = XML_ErrorString(XML_GetErrorCode( mParser ));
if( !error_string )
{
error_string = mAuxErrorString.c_str();
}
return error_string;
}
S32 LLXmlParser::getCurrentLineNumber()
{
return XML_GetCurrentLineNumber( mParser );
}
S32 LLXmlParser::getCurrentColumnNumber()
{
return XML_GetCurrentColumnNumber(mParser);
}
///////////////////////////////////////////////////////////////////////////////
// Pseudo-private methods. These are only used by internal callbacks.
// static
void LLXmlParser::startElementHandler(
void *userData,
const XML_Char *name,
const XML_Char **atts)
{
LLXmlParser* self = (LLXmlParser*) userData;
self->startElement( name, atts );
self->mDepth++;
}
// static
void LLXmlParser::endElementHandler(
void *userData,
const XML_Char *name)
{
LLXmlParser* self = (LLXmlParser*) userData;
self->mDepth--;
self->endElement( name );
}
// s is not 0 terminated.
// static
void LLXmlParser::characterDataHandler(
void *userData,
const XML_Char *s,
int len)
{
LLXmlParser* self = (LLXmlParser*) userData;
self->characterData( s, len );
}
// target and data are 0 terminated
// static
void LLXmlParser::processingInstructionHandler(
void *userData,
const XML_Char *target,
const XML_Char *data)
{
LLXmlParser* self = (LLXmlParser*) userData;
self->processingInstruction( target, data );
}
// data is 0 terminated
// static
void LLXmlParser::commentHandler(void *userData, const XML_Char *data)
{
LLXmlParser* self = (LLXmlParser*) userData;
self->comment( data );
}
// static
void LLXmlParser::startCdataSectionHandler(void *userData)
{
LLXmlParser* self = (LLXmlParser*) userData;
self->mDepth++;
self->startCdataSection();
}
// static
void LLXmlParser::endCdataSectionHandler(void *userData)
{
LLXmlParser* self = (LLXmlParser*) userData;
self->endCdataSection();
self->mDepth++;
}
// This is called for any characters in the XML document for
// which there is no applicable handler. This includes both
// characters that are part of markup which is of a kind that is
// not reported (comments, markup declarations), or characters
// that are part of a construct which could be reported but
// for which no handler has been supplied. The characters are passed
// exactly as they were in the XML document except that
// they will be encoded in UTF-8. Line boundaries are not normalized.
// Note that a byte order mark character is not passed to the default handler.
// There are no guarantees about how characters are divided between calls
// to the default handler: for example, a comment might be split between
// multiple calls.
// static
void LLXmlParser::defaultDataHandler(
void *userData,
const XML_Char *s,
int len)
{
LLXmlParser* self = (LLXmlParser*) userData;
self->defaultData( s, len );
}
// This is called for a declaration of an unparsed (NDATA)
// entity. The base argument is whatever was set by XML_SetBase.
// The entityName, systemId and notationName arguments will never be null.
// The other arguments may be.
// static
void LLXmlParser::unparsedEntityDeclHandler(
void *userData,
const XML_Char *entityName,
const XML_Char *base,
const XML_Char *systemId,
const XML_Char *publicId,
const XML_Char *notationName)
{
LLXmlParser* self = (LLXmlParser*) userData;
self->unparsedEntityDecl( entityName, base, systemId, publicId, notationName );
}
////////////////////////////////////////////////////////////////////
// Test code.
/*
class LLXmlDOMParser : public LLXmlParser
{
public:
LLXmlDOMParser() {}
virtual ~LLXmlDOMParser() {}
void tabs()
{
for ( int i = 0; i < getDepth(); i++)
{
putchar(' ');
}
}
virtual void startElement(const char *name, const char **atts)
{
tabs();
printf("startElement %s\n", name);
S32 i = 0;
while( atts[i] && atts[i+1] )
{
tabs();
printf( "\t%s=%s\n", atts[i], atts[i+1] );
i += 2;
}
if( atts[i] )
{
tabs();
printf( "\ttrailing attribute: %s\n", atts[i] );
}
}
virtual void endElement(const char *name)
{
tabs();
printf("endElement %s\n", name);
}
virtual void characterData(const char *s, int len)
{
tabs();
char* str = new char[len+1];
strncpy( str, s, len );
str[len] = '\0';
printf("CharacterData %s\n", str);
delete str;
}
virtual void processingInstruction(const char *target, const char *data)
{
tabs();
printf("processingInstruction %s\n", data);
}
virtual void comment(const char *data)
{
tabs();
printf("comment %s\n", data);
}
virtual void startCdataSection()
{
tabs();
printf("startCdataSection\n");
}
virtual void endCdataSection()
{
tabs();
printf("endCdataSection\n");
}
virtual void defaultData(const char *s, int len)
{
tabs();
char* str = new char[len+1];
strncpy( str, s, len );
str[len] = '\0';
printf("defaultData %s\n", str);
delete str;
}
virtual void unparsedEntityDecl(
const char *entityName,
const char *base,
const char *systemId,
const char *publicId,
const char *notationName)
{
tabs();
printf(
"unparsed entity:\n"
"\tentityName %s\n"
"\tbase %s\n"
"\tsystemId %s\n"
"\tpublicId %s\n"
"\tnotationName %s\n",
entityName,
base,
systemId,
publicId,
notationName );
}
};
int main()
{
char buf[1024];
LLFILE* file = LLFile::fopen("test.xml", "rb");
if( !file )
{
return 1;
}
LLXmlDOMParser parser;
int done;
do {
size_t len = fread(buf, 1, sizeof(buf), file);
done = len < sizeof(buf);
if( 0 == parser.parse( buf, len, done) )
{
fprintf(stderr,
"%s at line %d\n",
parser.getErrorString(),
parser.getCurrentLineNumber() );
return 1;
}
} while (!done);
fclose( file );
return 0;
}
*/
+133
View File
@@ -0,0 +1,133 @@
/**
* @file llxmlparser.h
* @brief LLXmlParser class definition
*
* $LicenseInfo:firstyear=2002&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_LLXMLPARSER_H
#define LL_LLXMLPARSER_H
#ifndef XML_STATIC
#define XML_STATIC
#endif
#ifdef LL_USESYSTEMLIBS
#include <expat.h>
#else
#include "expat/expat.h"
#endif
class LLXmlParser
{
public:
LLXmlParser();
virtual ~LLXmlParser();
// Parses entire file
bool parseFile(const std::string &path);
// Parses some input. Returns 0 if a fatal error is detected.
// The last call must have isFinal true;
// len may be zero for this call (or any other).
S32 parse( const char* buf, int len, int isFinal );
const char* getErrorString();
S32 getCurrentLineNumber();
S32 getCurrentColumnNumber();
S32 getDepth() { return mDepth; }
protected:
// atts is array of name/value pairs, terminated by 0;
// names and values are 0 terminated.
virtual void startElement(const char *name, const char **atts) {}
virtual void endElement(const char *name) {}
// s is not 0 terminated.
virtual void characterData(const char *s, int len) {}
// target and data are 0 terminated
virtual void processingInstruction(const char *target, const char *data) {}
// data is 0 terminated
virtual void comment(const char *data) {}
virtual void startCdataSection() {}
virtual void endCdataSection() {}
// This is called for any characters in the XML document for
// which there is no applicable handler. This includes both
// characters that are part of markup which is of a kind that is
// not reported (comments, markup declarations), or characters
// that are part of a construct which could be reported but
// for which no handler has been supplied. The characters are passed
// exactly as they were in the XML document except that
// they will be encoded in UTF-8. Line boundaries are not normalized.
// Note that a byte order mark character is not passed to the default handler.
// There are no guarantees about how characters are divided between calls
// to the default handler: for example, a comment might be split between
// multiple calls.
virtual void defaultData(const char *s, int len) {}
// This is called for a declaration of an unparsed (NDATA)
// entity. The base argument is whatever was set by XML_SetBase.
// The entityName, systemId and notationName arguments will never be null.
// The other arguments may be.
virtual void unparsedEntityDecl(
const char *entityName,
const char *base,
const char *systemId,
const char *publicId,
const char *notationName) {}
public:
///////////////////////////////////////////////////////////////////////////////
// Pseudo-private methods. These are only used by internal callbacks.
static void startElementHandler(void *userData, const XML_Char *name, const XML_Char **atts);
static void endElementHandler(void *userData, const XML_Char *name);
static void characterDataHandler(void *userData, const XML_Char *s, int len);
static void processingInstructionHandler(void *userData, const XML_Char *target, const XML_Char *data);
static void commentHandler(void *userData, const XML_Char *data);
static void startCdataSectionHandler(void *userData);
static void endCdataSectionHandler(void *userData);
static void defaultDataHandler( void *userData, const XML_Char *s, int len);
static void unparsedEntityDeclHandler(
void *userData,
const XML_Char *entityName,
const XML_Char *base,
const XML_Char *systemId,
const XML_Char *publicId,
const XML_Char *notationName);
protected:
XML_Parser mParser;
int mDepth;
std::string mAuxErrorString;
};
#endif // LL_LLXMLPARSER_H
+735
View File
@@ -0,0 +1,735 @@
/**
* @file llxmltree.cpp
* @brief LLXmlTree implementation
*
* $LicenseInfo:firstyear=2002&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"
#include "llxmltree.h"
#include "v3color.h"
#include "v4color.h"
#include "v4coloru.h"
#include "v3math.h"
#include "v3dmath.h"
#include "v4math.h"
#include "llquaternion.h"
#include "lluuid.h"
//////////////////////////////////////////////////////////////
// LLXmlTree
// static
LLStdStringTable LLXmlTree::sAttributeKeys(1024);
LLXmlTree::LLXmlTree()
: mRoot( NULL ),
mNodeNames(512)
{
}
LLXmlTree::~LLXmlTree()
{
cleanup();
}
void LLXmlTree::cleanup()
{
delete mRoot;
mRoot = NULL;
mNodeNames.cleanup();
}
bool LLXmlTree::parseFile(const std::string &path, bool keep_contents)
{
delete mRoot;
mRoot = NULL;
LLXmlTreeParser parser(this);
bool success = parser.parseFile( path, &mRoot, keep_contents );
if( !success )
{
S32 line_number = parser.getCurrentLineNumber();
const char* error = parser.getErrorString();
LL_WARNS() << "LLXmlTree parse failed. Line " << line_number << ": " << error << LL_ENDL;
}
return success;
}
bool LLXmlTree::parseString(const std::string &string, bool keep_contents)
{
delete mRoot;
mRoot = NULL;
LLXmlTreeParser parser(this);
bool success = parser.parseString( string, &mRoot, keep_contents );
if( !success )
{
S32 line_number = parser.getCurrentLineNumber();
const char* error = parser.getErrorString();
LL_WARNS() << "LLXmlTree parse failed. Line " << line_number << ": " << error << LL_ENDL;
}
return success;
}
void LLXmlTree::dump()
{
if( mRoot )
{
dumpNode( mRoot, " " );
}
}
void LLXmlTree::dumpNode( LLXmlTreeNode* node, const std::string& prefix )
{
node->dump( prefix );
std::string new_prefix = prefix + " ";
for( LLXmlTreeNode* child = node->getFirstChild(); child; child = node->getNextChild() )
{
dumpNode( child, new_prefix );
}
}
//////////////////////////////////////////////////////////////
// LLXmlTreeNode
LLXmlTreeNode::LLXmlTreeNode( const std::string& name, LLXmlTreeNode* parent, LLXmlTree* tree )
: mName(name),
mParent(parent),
mTree(tree)
{
}
LLXmlTreeNode::~LLXmlTreeNode()
{
for (auto& attr : mAttributes)
{
delete attr.second;
}
mAttributes.clear();
for (auto& child : mChildren)
{
delete child;
}
mChildren.clear();
}
void LLXmlTreeNode::dump( const std::string& prefix )
{
LL_INFOS() << prefix << mName ;
if( !mContents.empty() )
{
LL_CONT << " contents = \"" << mContents << "\"";
}
attribute_map_t::iterator iter;
for (iter=mAttributes.begin(); iter != mAttributes.end(); iter++)
{
LLStdStringHandle key = iter->first;
const std::string* value = iter->second;
LL_CONT << prefix << " " << key << "=" << (value->empty() ? "NULL" : *value);
}
LL_CONT << LL_ENDL;
}
bool LLXmlTreeNode::hasAttribute(const std::string& name)
{
LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString(name);
attribute_map_t::iterator iter = mAttributes.find(canonical_name);
return iter != mAttributes.end();
}
void LLXmlTreeNode::addAttribute(const std::string& name, const std::string& value)
{
LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString(name);
const std::string *newstr = new std::string(value);
mAttributes[canonical_name] = newstr; // insert + copy
}
LLXmlTreeNode* LLXmlTreeNode::getFirstChild()
{
mChildrenIter = mChildren.begin();
return getNextChild();
}
LLXmlTreeNode* LLXmlTreeNode::getNextChild()
{
if (mChildrenIter == mChildren.end())
return 0;
else
return *mChildrenIter++;
}
LLXmlTreeNode* LLXmlTreeNode::getChildByName(const std::string& name)
{
LLStdStringHandle tableptr = mTree->mNodeNames.checkString(name);
mChildMapIter = mChildMap.lower_bound(tableptr);
mChildMapEndIter = mChildMap.upper_bound(tableptr);
return getNextNamedChild();
}
LLXmlTreeNode* LLXmlTreeNode::getNextNamedChild()
{
if (mChildMapIter == mChildMapEndIter)
return NULL;
else
return (mChildMapIter++)->second;
}
void LLXmlTreeNode::appendContents(const std::string& str)
{
mContents.append( str );
}
void LLXmlTreeNode::addChild(LLXmlTreeNode* child)
{
llassert( child );
mChildren.push_back( child );
// Add a name mapping to this node
LLStdStringHandle tableptr = mTree->mNodeNames.insert(child->mName);
mChildMap.insert( child_map_t::value_type(tableptr, child));
child->mParent = this;
}
//////////////////////////////////////////////////////////////
// These functions assume that name is already in mAttritrubteKeys
bool LLXmlTreeNode::getFastAttributeBOOL(LLStdStringHandle canonical_name, bool& value)
{
const std::string *s = getAttribute( canonical_name );
return s && LLStringUtil::convertToBOOL( *s, value );
}
bool LLXmlTreeNode::getFastAttributeU8(LLStdStringHandle canonical_name, U8& value)
{
const std::string *s = getAttribute( canonical_name );
return s && LLStringUtil::convertToU8( *s, value );
}
bool LLXmlTreeNode::getFastAttributeS8(LLStdStringHandle canonical_name, S8& value)
{
const std::string *s = getAttribute( canonical_name );
return s && LLStringUtil::convertToS8( *s, value );
}
bool LLXmlTreeNode::getFastAttributeS16(LLStdStringHandle canonical_name, S16& value)
{
const std::string *s = getAttribute( canonical_name );
return s && LLStringUtil::convertToS16( *s, value );
}
bool LLXmlTreeNode::getFastAttributeU16(LLStdStringHandle canonical_name, U16& value)
{
const std::string *s = getAttribute( canonical_name );
return s && LLStringUtil::convertToU16( *s, value );
}
bool LLXmlTreeNode::getFastAttributeU32(LLStdStringHandle canonical_name, U32& value)
{
const std::string *s = getAttribute( canonical_name );
return s && LLStringUtil::convertToU32( *s, value );
}
bool LLXmlTreeNode::getFastAttributeS32(LLStdStringHandle canonical_name, S32& value)
{
const std::string *s = getAttribute( canonical_name );
return s && LLStringUtil::convertToS32( *s, value );
}
bool LLXmlTreeNode::getFastAttributeF32(LLStdStringHandle canonical_name, F32& value)
{
const std::string *s = getAttribute( canonical_name );
return s && LLStringUtil::convertToF32( *s, value );
}
bool LLXmlTreeNode::getFastAttributeF64(LLStdStringHandle canonical_name, F64& value)
{
const std::string *s = getAttribute( canonical_name );
return s && LLStringUtil::convertToF64( *s, value );
}
bool LLXmlTreeNode::getFastAttributeColor(LLStdStringHandle canonical_name, LLColor4& value)
{
const std::string *s = getAttribute( canonical_name );
return s ? LLColor4::parseColor(*s, &value) : false;
}
bool LLXmlTreeNode::getFastAttributeColor4(LLStdStringHandle canonical_name, LLColor4& value)
{
const std::string *s = getAttribute( canonical_name );
return s ? LLColor4::parseColor4(*s, &value) : false;
}
bool LLXmlTreeNode::getFastAttributeColor4U(LLStdStringHandle canonical_name, LLColor4U& value)
{
const std::string *s = getAttribute( canonical_name );
return s ? LLColor4U::parseColor4U(*s, &value ) : false;
}
bool LLXmlTreeNode::getFastAttributeVector3(LLStdStringHandle canonical_name, LLVector3& value)
{
const std::string *s = getAttribute( canonical_name );
return s ? LLVector3::parseVector3(*s, &value ) : false;
}
bool LLXmlTreeNode::getFastAttributeVector3d(LLStdStringHandle canonical_name, LLVector3d& value)
{
const std::string *s = getAttribute( canonical_name );
return s ? LLVector3d::parseVector3d(*s, &value ) : false;
}
bool LLXmlTreeNode::getFastAttributeQuat(LLStdStringHandle canonical_name, LLQuaternion& value)
{
const std::string *s = getAttribute( canonical_name );
return s ? LLQuaternion::parseQuat(*s, &value ) : false;
}
bool LLXmlTreeNode::getFastAttributeUUID(LLStdStringHandle canonical_name, LLUUID& value)
{
const std::string *s = getAttribute( canonical_name );
return s ? LLUUID::parseUUID(*s, &value ) : false;
}
bool LLXmlTreeNode::getFastAttributeString(LLStdStringHandle canonical_name, std::string& value)
{
const std::string *s = getAttribute( canonical_name );
if( !s )
{
return false;
}
value = *s;
return true;
}
//////////////////////////////////////////////////////////////
bool LLXmlTreeNode::getAttributeBOOL(const std::string& name, bool& value)
{
LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
return getFastAttributeBOOL(canonical_name, value);
}
bool LLXmlTreeNode::getAttributeU8(const std::string& name, U8& value)
{
LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
return getFastAttributeU8(canonical_name, value);
}
bool LLXmlTreeNode::getAttributeS8(const std::string& name, S8& value)
{
LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
return getFastAttributeS8(canonical_name, value);
}
bool LLXmlTreeNode::getAttributeS16(const std::string& name, S16& value)
{
LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
return getFastAttributeS16(canonical_name, value);
}
bool LLXmlTreeNode::getAttributeU16(const std::string& name, U16& value)
{
LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
return getFastAttributeU16(canonical_name, value);
}
bool LLXmlTreeNode::getAttributeU32(const std::string& name, U32& value)
{
LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
return getFastAttributeU32(canonical_name, value);
}
bool LLXmlTreeNode::getAttributeS32(const std::string& name, S32& value)
{
LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
return getFastAttributeS32(canonical_name, value);
}
bool LLXmlTreeNode::getAttributeF32(const std::string& name, F32& value)
{
LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
return getFastAttributeF32(canonical_name, value);
}
bool LLXmlTreeNode::getAttributeF64(const std::string& name, F64& value)
{
LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
return getFastAttributeF64(canonical_name, value);
}
bool LLXmlTreeNode::getAttributeColor(const std::string& name, LLColor4& value)
{
LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
return getFastAttributeColor(canonical_name, value);
}
bool LLXmlTreeNode::getAttributeColor4(const std::string& name, LLColor4& value)
{
LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
return getFastAttributeColor4(canonical_name, value);
}
bool LLXmlTreeNode::getAttributeColor4U(const std::string& name, LLColor4U& value)
{
LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
return getFastAttributeColor4U(canonical_name, value);
}
bool LLXmlTreeNode::getAttributeVector3(const std::string& name, LLVector3& value)
{
LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
return getFastAttributeVector3(canonical_name, value);
}
bool LLXmlTreeNode::getAttributeVector3d(const std::string& name, LLVector3d& value)
{
LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
return getFastAttributeVector3d(canonical_name, value);
}
bool LLXmlTreeNode::getAttributeQuat(const std::string& name, LLQuaternion& value)
{
LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
return getFastAttributeQuat(canonical_name, value);
}
bool LLXmlTreeNode::getAttributeUUID(const std::string& name, LLUUID& value)
{
LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
return getFastAttributeUUID(canonical_name, value);
}
bool LLXmlTreeNode::getAttributeString(const std::string& name, std::string& value)
{
LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
return getFastAttributeString(canonical_name, value);
}
/*
The following xml <message> nodes will all return the string from getTextContents():
"The quick brown fox\n Jumps over the lazy dog"
1. HTML paragraph format:
<message>
<p>The quick brown fox</p>
<p> Jumps over the lazy dog</p>
</message>
2. Each quoted section -> paragraph:
<message>
"The quick brown fox"
" Jumps over the lazy dog"
</message>
3. Literal text with beginning and trailing whitespace removed:
<message>
The quick brown fox
Jumps over the lazy dog
</message>
*/
std::string LLXmlTreeNode::getTextContents()
{
std::string msg;
LLXmlTreeNode* p = getChildByName("p");
if (p)
{
// Case 1: node has <p>text</p> tags
while (p)
{
msg += p->getContents() + "\n";
p = getNextNamedChild();
}
}
else
{
std::string::size_type n = mContents.find_first_not_of(" \t\n");
if (n != std::string::npos && mContents[n] == '\"')
{
// Case 2: node has quoted text
S32 num_lines = 0;
while(1)
{
// mContents[n] == '"'
++n;
std::string::size_type t = n;
std::string::size_type m = 0;
// fix-up escaped characters
while(1)
{
m = mContents.find_first_of("\\\"", t); // find first \ or "
if ((m == std::string::npos) || (mContents[m] == '\"'))
{
break;
}
mContents.erase(m,1);
t = m+1;
}
if (m == std::string::npos)
{
break;
}
// mContents[m] == '"'
num_lines++;
msg += mContents.substr(n,m-n) + "\n";
n = mContents.find_first_of("\"", m+1);
if (n == std::string::npos)
{
if (num_lines == 1)
{
msg.erase(msg.size()-1); // remove "\n" if only one line
}
break;
}
}
}
else
{
// Case 3: node has embedded text (beginning and trailing whitespace trimmed)
msg = mContents;
}
}
return msg;
}
//////////////////////////////////////////////////////////////
// LLXmlTreeParser
LLXmlTreeParser::LLXmlTreeParser(LLXmlTree* tree)
: mTree(tree),
mRoot( NULL ),
mCurrent( NULL ),
mDump( false ),
mKeepContents(false)
{
}
LLXmlTreeParser::~LLXmlTreeParser()
{
}
bool LLXmlTreeParser::parseFile(const std::string &path, LLXmlTreeNode** root, bool keep_contents)
{
llassert( !mRoot );
llassert( !mCurrent );
mKeepContents = keep_contents;
bool success = LLXmlParser::parseFile(path);
*root = mRoot;
mRoot = NULL;
if( success )
{
llassert( !mCurrent );
}
mCurrent = NULL;
return success;
}
bool LLXmlTreeParser::parseString(const std::string &string, LLXmlTreeNode** root, bool keep_contents)
{
llassert( !mRoot );
llassert( !mCurrent );
mKeepContents = keep_contents;
bool success = LLXmlParser::parse(string.c_str(), static_cast<S32>(string.length()), 1);
*root = mRoot;
mRoot = NULL;
if( success )
{
llassert( !mCurrent );
}
mCurrent = NULL;
return success;
}
const std::string& LLXmlTreeParser::tabs()
{
static std::string s;
s = "";
S32 num_tabs = getDepth() - 1;
for( S32 i = 0; i < num_tabs; i++)
{
s += " ";
}
return s;
}
void LLXmlTreeParser::startElement(const char* name, const char **atts)
{
if( mDump )
{
LL_INFOS() << tabs() << "startElement " << name << LL_ENDL;
S32 i = 0;
while( atts[i] && atts[i+1] )
{
LL_INFOS() << tabs() << "attribute: " << atts[i] << "=" << atts[i+1] << LL_ENDL;
i += 2;
}
}
LLXmlTreeNode* child = CreateXmlTreeNode( std::string(name), mCurrent );
S32 i = 0;
while( atts[i] && atts[i+1] )
{
child->addAttribute( atts[i], atts[i+1] );
i += 2;
}
if( mCurrent )
{
mCurrent->addChild( child );
}
else
{
llassert( !mRoot );
mRoot = child;
}
mCurrent = child;
}
LLXmlTreeNode* LLXmlTreeParser::CreateXmlTreeNode(const std::string& name, LLXmlTreeNode* parent)
{
return new LLXmlTreeNode(name, parent, mTree);
}
void LLXmlTreeParser::endElement(const char* name)
{
if( mDump )
{
LL_INFOS() << tabs() << "endElement " << name << LL_ENDL;
}
if( !mCurrent->mContents.empty() )
{
LLStringUtil::trim(mCurrent->mContents);
LLStringUtil::removeCRLF(mCurrent->mContents);
}
mCurrent = mCurrent->getParent();
}
void LLXmlTreeParser::characterData(const char *s, int len)
{
std::string str;
if (s) str = std::string(s, len);
if( mDump )
{
LL_INFOS() << tabs() << "CharacterData " << str << LL_ENDL;
}
if (mKeepContents)
{
mCurrent->appendContents( str );
}
}
void LLXmlTreeParser::processingInstruction(const char *target, const char *data)
{
if( mDump )
{
LL_INFOS() << tabs() << "processingInstruction " << data << LL_ENDL;
}
}
void LLXmlTreeParser::comment(const char *data)
{
if( mDump )
{
LL_INFOS() << tabs() << "comment " << data << LL_ENDL;
}
}
void LLXmlTreeParser::startCdataSection()
{
if( mDump )
{
LL_INFOS() << tabs() << "startCdataSection" << LL_ENDL;
}
}
void LLXmlTreeParser::endCdataSection()
{
if( mDump )
{
LL_INFOS() << tabs() << "endCdataSection" << LL_ENDL;
}
}
void LLXmlTreeParser::defaultData(const char *s, int len)
{
if( mDump )
{
std::string str;
if (s) str = std::string(s, len);
LL_INFOS() << tabs() << "defaultData " << str << LL_ENDL;
}
}
void LLXmlTreeParser::unparsedEntityDecl(
const char* entity_name,
const char* base,
const char* system_id,
const char* public_id,
const char* notation_name)
{
if( mDump )
{
LL_INFOS() << tabs() << "unparsed entity:" << LL_ENDL;
LL_INFOS() << tabs() << " entityName " << entity_name << LL_ENDL;
LL_INFOS() << tabs() << " base " << base << LL_ENDL;
LL_INFOS() << tabs() << " systemId " << system_id << LL_ENDL;
LL_INFOS() << tabs() << " publicId " << public_id << LL_ENDL;
LL_INFOS() << tabs() << " notationName " << notation_name<< LL_ENDL;
}
}
void test_llxmltree()
{
LLXmlTree tree;
bool success = tree.parseFile( "test.xml" );
if( success )
{
tree.dump();
}
}
+236
View File
@@ -0,0 +1,236 @@
/**
* @file llxmltree.h
* @author Aaron Yonas, Richard Nelson
* @brief LLXmlTree class definition
*
* $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_LLXMLTREE_H
#define LL_LLXMLTREE_H
#include <map>
#include <list>
#include "llstring.h"
#include "llxmlparser.h"
#include "llstringtable.h"
class LLColor4;
class LLColor4U;
class LLQuaternion;
class LLUUID;
class LLVector3;
class LLVector3d;
class LLXmlTreeNode;
class LLXmlTreeParser;
//////////////////////////////////////////////////////////////
// LLXmlTree
class LLXmlTree
{
friend class LLXmlTreeNode;
public:
LLXmlTree();
virtual ~LLXmlTree();
void cleanup();
virtual bool parseFile(const std::string &path, bool keep_contents = true);
virtual bool parseString(const std::string &string, bool keep_contents = true);
LLXmlTreeNode* getRoot() { return mRoot; }
void dump();
void dumpNode( LLXmlTreeNode* node, const std::string& prefix );
static LLStdStringHandle addAttributeString( const std::string& name)
{
return sAttributeKeys.addString( name );
}
public:
// global
static LLStdStringTable sAttributeKeys;
protected:
LLXmlTreeNode* mRoot;
// local
LLStdStringTable mNodeNames;
};
//////////////////////////////////////////////////////////////
// LLXmlTreeNode
class LLXmlTreeNode
{
friend class LLXmlTree;
friend class LLXmlTreeParser;
protected:
// Protected since nodes are only created and destroyed by friend classes and other LLXmlTreeNodes
LLXmlTreeNode( const std::string& name, LLXmlTreeNode* parent, LLXmlTree* tree );
public:
virtual ~LLXmlTreeNode();
const std::string& getName()
{
return mName;
}
bool hasName( const std::string& name )
{
return mName == name;
}
bool hasAttribute( const std::string& name );
// Fast versions use cannonical_name handlee to entru in LLXmlTree::sAttributeKeys string table
bool getFastAttributeBOOL( LLStdStringHandle cannonical_name, bool& value );
bool getFastAttributeU8( LLStdStringHandle cannonical_name, U8& value );
bool getFastAttributeS8( LLStdStringHandle cannonical_name, S8& value );
bool getFastAttributeU16( LLStdStringHandle cannonical_name, U16& value );
bool getFastAttributeS16( LLStdStringHandle cannonical_name, S16& value );
bool getFastAttributeU32( LLStdStringHandle cannonical_name, U32& value );
bool getFastAttributeS32( LLStdStringHandle cannonical_name, S32& value );
bool getFastAttributeF32( LLStdStringHandle cannonical_name, F32& value );
bool getFastAttributeF64( LLStdStringHandle cannonical_name, F64& value );
bool getFastAttributeColor( LLStdStringHandle cannonical_name, LLColor4& value );
bool getFastAttributeColor4( LLStdStringHandle cannonical_name, LLColor4& value );
bool getFastAttributeColor4U( LLStdStringHandle cannonical_name, LLColor4U& value );
bool getFastAttributeVector3( LLStdStringHandle cannonical_name, LLVector3& value );
bool getFastAttributeVector3d( LLStdStringHandle cannonical_name, LLVector3d& value );
bool getFastAttributeQuat( LLStdStringHandle cannonical_name, LLQuaternion& value );
bool getFastAttributeUUID( LLStdStringHandle cannonical_name, LLUUID& value );
bool getFastAttributeString( LLStdStringHandle cannonical_name, std::string& value );
// Normal versions find 'name' in LLXmlTree::sAttributeKeys then call fast versions
virtual bool getAttributeBOOL( const std::string& name, bool& value );
virtual bool getAttributeU8( const std::string& name, U8& value );
virtual bool getAttributeS8( const std::string& name, S8& value );
virtual bool getAttributeU16( const std::string& name, U16& value );
virtual bool getAttributeS16( const std::string& name, S16& value );
virtual bool getAttributeU32( const std::string& name, U32& value );
virtual bool getAttributeS32( const std::string& name, S32& value );
virtual bool getAttributeF32( const std::string& name, F32& value );
virtual bool getAttributeF64( const std::string& name, F64& value );
virtual bool getAttributeColor( const std::string& name, LLColor4& value );
virtual bool getAttributeColor4( const std::string& name, LLColor4& value );
virtual bool getAttributeColor4U( const std::string& name, LLColor4U& value );
virtual bool getAttributeVector3( const std::string& name, LLVector3& value );
virtual bool getAttributeVector3d( const std::string& name, LLVector3d& value );
virtual bool getAttributeQuat( const std::string& name, LLQuaternion& value );
virtual bool getAttributeUUID( const std::string& name, LLUUID& value );
virtual bool getAttributeString( const std::string& name, std::string& value );
const std::string& getContents()
{
return mContents;
}
std::string getTextContents();
LLXmlTreeNode* getParent() { return mParent; }
LLXmlTreeNode* getFirstChild();
LLXmlTreeNode* getNextChild();
S32 getChildCount() { return (S32)mChildren.size(); }
LLXmlTreeNode* getChildByName( const std::string& name ); // returns first child with name, NULL if none
LLXmlTreeNode* getNextNamedChild(); // returns next child with name, NULL if none
protected:
const std::string* getAttribute( LLStdStringHandle name)
{
attribute_map_t::iterator iter = mAttributes.find(name);
return (iter == mAttributes.end()) ? 0 : iter->second;
}
private:
void addAttribute( const std::string& name, const std::string& value );
void appendContents( const std::string& str );
void addChild( LLXmlTreeNode* child );
void dump( const std::string& prefix );
protected:
typedef std::map<LLStdStringHandle, const std::string*> attribute_map_t;
attribute_map_t mAttributes;
private:
std::string mName;
std::string mContents;
typedef std::vector<class LLXmlTreeNode *> children_t;
children_t mChildren;
children_t::iterator mChildrenIter;
typedef std::multimap<LLStdStringHandle, LLXmlTreeNode *> child_map_t;
child_map_t mChildMap; // for fast name lookups
child_map_t::iterator mChildMapIter;
child_map_t::iterator mChildMapEndIter;
LLXmlTreeNode* mParent;
LLXmlTree* mTree;
};
//////////////////////////////////////////////////////////////
// LLXmlTreeParser
class LLXmlTreeParser : public LLXmlParser
{
public:
LLXmlTreeParser(LLXmlTree* tree);
virtual ~LLXmlTreeParser();
bool parseFile(const std::string &path, LLXmlTreeNode** root, bool keep_contents );
bool parseString(const std::string &string, LLXmlTreeNode** root, bool keep_contents);
protected:
const std::string& tabs();
// Overrides from LLXmlParser
virtual void startElement(const char *name, const char **attributes);
virtual void endElement(const char *name);
virtual void characterData(const char *s, int len);
virtual void processingInstruction(const char *target, const char *data);
virtual void comment(const char *data);
virtual void startCdataSection();
virtual void endCdataSection();
virtual void defaultData(const char *s, int len);
virtual void unparsedEntityDecl(
const char* entity_name,
const char* base,
const char* system_id,
const char* public_id,
const char* notation_name);
//template method pattern
virtual LLXmlTreeNode* CreateXmlTreeNode(const std::string& name, LLXmlTreeNode* parent);
protected:
LLXmlTree* mTree;
LLXmlTreeNode* mRoot;
LLXmlTreeNode* mCurrent;
bool mDump; // Dump parse tree to LL_INFOS() as it is read.
bool mKeepContents;
};
#endif // LL_LLXMLTREE_H
+154
View File
@@ -0,0 +1,154 @@
/**
* @file llcontrol_tut.cpp
* @date February 2008
* @brief control group unit tests
*
* $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"
#include "llsdserialize.h"
#include "llfile.h"
#include "stringize.h"
#include "../llcontrol.h"
#include "../test/lltut.h"
#include <memory>
#include <vector>
namespace tut
{
struct control_group
{
std::unique_ptr<LLControlGroup> mCG;
std::string mTestConfigDir;
std::string mTestConfigFile;
std::vector<std::string> mCleanups;
static bool mListenerFired;
control_group()
{
mCG.reset(new LLControlGroup("foo"));
LLUUID random;
random.generate();
// generate temp dir
mTestConfigDir = STRINGIZE(LLFile::tmpdir() << "llcontrol-test-" << random << "/");
mTestConfigFile = mTestConfigDir + "settings.xml";
LLFile::mkdir(mTestConfigDir);
LLSD config;
config["TestSetting"]["Comment"] = "Dummy setting used for testing";
config["TestSetting"]["Persist"] = 1;
config["TestSetting"]["Type"] = "U32";
config["TestSetting"]["Value"] = 12;
writeSettingsFile(config);
}
~control_group()
{
//Remove test files
for (auto filename : mCleanups)
{
LLFile::remove(filename);
}
LLFile::remove(mTestConfigFile);
LLFile::rmdir(mTestConfigDir);
}
void writeSettingsFile(const LLSD& config)
{
llofstream file(mTestConfigFile.c_str());
if (file.is_open())
{
LLSDSerialize::toPrettyXML(config, file);
}
file.close();
}
static bool handleListenerTest()
{
control_group::mListenerFired = true;
return true;
}
};
bool control_group::mListenerFired = false;
typedef test_group<control_group> control_group_test;
typedef control_group_test::object control_group_t;
control_group_test tut_control_group("control_group");
//load settings from files - LLSD
template<> template<>
void control_group_t::test<1>()
{
int results = mCG->loadFromFile(mTestConfigFile.c_str());
ensure("number of settings", (results == 1));
ensure("value of setting", (mCG->getU32("TestSetting") == 12));
}
//save settings to files
template<> template<>
void control_group_t::test<2>()
{
int results = mCG->loadFromFile(mTestConfigFile.c_str());
mCG->setU32("TestSetting", 13);
ensure_equals("value of changed setting", mCG->getU32("TestSetting"), 13);
LLControlGroup test_cg("foo2");
std::string temp_test_file = (mTestConfigDir + "setting_llsd_temp.xml");
mCleanups.push_back(temp_test_file);
mCG->saveToFile(temp_test_file.c_str(), true);
results = test_cg.loadFromFile(temp_test_file.c_str());
ensure("number of changed settings loaded", (results == 1));
ensure("value of changed settings loaded", (test_cg.getU32("TestSetting") == 13));
}
//priorities
template<> template<>
void control_group_t::test<3>()
{
// Pass default_values = true. This tells loadFromFile() we're loading
// a default settings file that declares variables, rather than a user
// settings file. When loadFromFile() encounters an unrecognized user
// settings variable, it forcibly preserves it (CHOP-962).
int results = mCG->loadFromFile(mTestConfigFile.c_str(), true);
LLControlVariable* control = mCG->getControl("TestSetting");
LLSD new_value = 13;
control->setValue(new_value, false);
ensure_equals("value of changed setting", mCG->getU32("TestSetting"), 13);
LLControlGroup test_cg("foo3");
std::string temp_test_file = (mTestConfigDir + "setting_llsd_persist_temp.xml");
mCleanups.push_back(temp_test_file);
mCG->saveToFile(temp_test_file.c_str(), true);
results = test_cg.loadFromFile(temp_test_file.c_str());
//If we haven't changed any settings, then we shouldn't have any settings to load
ensure("number of non-persisted changed settings loaded", (results == 0));
}
//listeners
template<> template<>
void control_group_t::test<4>()
{
int results = mCG->loadFromFile(mTestConfigFile.c_str());
ensure("number of settings", (results == 1));
mCG->getControl("TestSetting")->getSignal()->connect(boost::bind(&this->handleListenerTest));
mCG->setU32("TestSetting", 13);
ensure("listener fired on changed setting", mListenerFired);
}
}