1
0
forked from 0ad/0ad
0ad/source/ps/XML/XeroXMB.h
Ykkrosh 4fed9b8242 # Added initial support for players and population counters in new simulation system, plus various infrastructure improvements.
Merge from 22b478ffed8d.
Pure scripted interface definitions.
Entity creation from scripts.
Improved messaging system.
Messages on entity deletion.
Basic player entities.
Player ownership.
Bug fixes.

This was SVN commit r7281.
2010-01-22 20:03:14 +00:00

250 lines
5.7 KiB
C++

/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Xeromyces - XMB reading library
*/
/*
Brief outline:
XMB is a binary representation of XML, with some limitations
but much more efficiency (particularly for loading simple data
classes that don't need much initialisation).
Main limitations:
* Only handles UTF16 internally. (It's meant to be a feature, but
can be detrimental if it's always being converted back to
ASCII.)
* Can't correctly handle mixed text/elements inside elements -
"<div> <b> Text </b> </div>" and "<div> Te<b/>xt </div>" are
considered identical.
* Tries to avoid using strings - you usually have to load the
numeric IDs and use them instead.
* Case-sensitive (but converts all element/attribute names in
the XML file to lowercase, so you only have to be careful in
the code)
Theoretical file structure:
XMB_File {
char Header[4]; // because everyone has one; currently "XMB0"
int ElementNameCount;
ZStrA ElementNames[];
int AttributeNameCount;
ZStrA AttributeNames[];
XMB_Node Root;
}
XMB_Node {
0) int Length; // of entire struct, so it can be skipped over
4) int ElementName;
8) int AttributeCount;
12) int ChildCount;
16) int ChildrenOffset; // == sizeof(Text)+sizeof(Attributes)
20) XMB_Text Text;
XMB_Attribute Attributes[];
XMB_Node Children[];
}
XMB_Attribute {
int Name;
ZStrW Value;
}
ZStrA {
int Length; // in bytes
char* Text; // null-terminated ASCII
}
ZStrW {
int Length; // in bytes
char16* Text; // null-terminated UTF16
}
XMB_Text {
20) int Length; // 0 if there's no text, else 4+sizeof(Text) in bytes including terminator
// If Length != 0:
24) int LineNumber; // for e.g. debugging scripts
28) char16* Text; // null-terminated UTF16
}
*/
#ifndef INCLUDED_XEROXMB
#define INCLUDED_XEROXMB
// Define to use a std::map for name lookups rather than a linear search.
// (The map is usually slower.)
//#define XERO_USEMAP
#include <string>
#include "ps/utf16string.h"
#ifdef XERO_USEMAP
# include <map>
#endif
// File headers, to make sure it doesn't try loading anything other than an XMB
extern const char* HeaderMagicStr;
extern const char* UnfinishedHeaderMagicStr;
class XMBElement;
class XMBElementList;
class XMBAttributeList;
class XMBFile
{
public:
XMBFile() : m_Pointer(NULL) {}
// Initialise from the contents of an XMB file.
// FileData must remain allocated and unchanged while
// the XMBFile is being used.
// @return indication of success; main cause for failure is attempting to
// load a partially valid XMB file (e.g. if the game was interrupted
// while writing it), which we detect by checking the magic string.
bool Initialise(const char* FileData);
// Returns the root element
XMBElement GetRoot() const;
// Returns internal ID for a given ASCII element/attribute string.
int GetElementID(const char* Name) const;
int GetAttributeID(const char* Name) const;
// For lazy people (e.g. me) when speed isn't vital:
// Returns element/attribute string for a given internal ID
std::string GetElementString(const int ID) const;
std::string GetAttributeString(const int ID) const;
private:
const char* m_Pointer;
#ifdef XERO_USEMAP
std::map<std::string, int> m_ElementNames;
std::map<std::string, int> m_AttributeNames;
#else
int m_ElementNameCount;
int m_AttributeNameCount;
const char* m_ElementPointer;
const char* m_AttributePointer;
#endif
std::string ReadZStrA();
};
class XMBElement
{
public:
XMBElement()
: m_Pointer(0) {}
XMBElement(const char* offset)
: m_Pointer(offset) {}
int GetNodeName() const;
XMBElementList GetChildNodes() const;
XMBAttributeList GetAttributes() const;
utf16string GetText() const;
// Returns the line number of the text within this element,
// or -1 if there is no text
int GetLineNumber() const;
private:
// Pointer to the start of the node
const char* m_Pointer;
};
class XMBElementList
{
public:
XMBElementList()
: Count(0), m_Pointer(0), m_LastItemID(-2) {}
XMBElementList(const char* offset, int count)
: Count(count),
m_Pointer(offset),
m_LastItemID(-2) {} // use -2 because it isn't x-1 where x is a non-negative integer
// Get first element in list with the given name.
// Performance is linear in the number of elements in the list.
XMBElement GetFirstNamedItem(const int ElementName) const;
XMBElement Item(const int id); // returns Children[id]
int Count;
private:
const char* m_Pointer;
// For optimised sequential access:
int m_LastItemID;
const char* m_LastPointer;
};
struct XMBAttribute
{
XMBAttribute() {}
XMBAttribute(int name, utf16string value)
: Name(name), Value(value) {};
int Name;
utf16string Value;
};
class XMBAttributeList
{
public:
XMBAttributeList(const char* offset, int count)
: Count(count), m_Pointer(offset), m_LastItemID(-2) {};
// Get the attribute value directly
utf16string GetNamedItem(const int AttributeName) const;
// Returns an attribute by position in the list
XMBAttribute Item(const int id);
int Count;
private:
// Pointer to start of attribute list
const char* m_Pointer;
// For optimised sequential access:
int m_LastItemID;
const char* m_LastPointer;
};
#endif // INCLUDED_XEROXMB