phoenix-firestorm/indra/llxml/llxmlnode.h

336 lines
13 KiB
C++

/**
* @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;
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
// Unit Testing
void createUnitTest(S32 max_num_children);
bool performUnitTest(std::string &error_buffer);
protected:
bool removeChild(LLXMLNode* child);
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);
bool isFullyDefault();
};
#endif // LL_LLXMLNODE