IrrXml: replaced irrXml by pugixml.

pull/2966/head
Kim Kulling 2020-01-23 21:16:10 +01:00
parent d48b93cf34
commit a905303764
21 changed files with 1170 additions and 4062 deletions

View File

@ -58,8 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Header files, stdlib. // Header files, stdlib.
#include <memory> #include <memory>
namespace Assimp namespace Assimp {
{
/// \var aiImporterDesc AMFImporter::Description /// \var aiImporterDesc AMFImporter::Description
/// Conastant which hold importer description /// Conastant which hold importer description
@ -76,24 +75,26 @@ const aiImporterDesc AMFImporter::Description = {
"amf" "amf"
}; };
void AMFImporter::Clear() void AMFImporter::Clear() {
{
mNodeElement_Cur = nullptr; mNodeElement_Cur = nullptr;
mUnit.clear(); mUnit.clear();
mMaterial_Converted.clear(); mMaterial_Converted.clear();
mTexture_Converted.clear(); mTexture_Converted.clear();
// Delete all elements // Delete all elements
if(!mNodeElement_List.empty()) if(!mNodeElement_List.empty()) {
{ for(CAMFImporter_NodeElement* ne: mNodeElement_List) {
for(CAMFImporter_NodeElement* ne: mNodeElement_List) { delete ne; } delete ne;
}
mNodeElement_List.clear(); mNodeElement_List.clear();
} }
} }
AMFImporter::~AMFImporter() AMFImporter::~AMFImporter() {
{ if (mReader != nullptr) {
if(mReader != nullptr) delete mReader; delete mReader;
}
// Clear() is accounting if data already is deleted. So, just check again if all data is deleted. // Clear() is accounting if data already is deleted. So, just check again if all data is deleted.
Clear(); Clear();
} }
@ -117,15 +118,14 @@ bool AMFImporter::Find_NodeElement(const std::string& pID, const CAMFImporter_No
return false; return false;
} }
bool AMFImporter::Find_ConvertedNode(const std::string& pID, std::list<aiNode*>& pNodeList, aiNode** pNode) const bool AMFImporter::Find_ConvertedNode(const std::string& id, std::list<aiNode*>& nodeList, aiNode** pNode) const {
{ aiString node_name(id.c_str());
aiString node_name(pID.c_str());
for(aiNode* node: pNodeList) for(aiNode* node: nodeList) {
{ if(node->mName == node_name) {
if(node->mName == node_name) if (pNode != nullptr) {
{ *pNode = node;
if(pNode != nullptr) *pNode = node; }
return true; return true;
} }
@ -134,13 +134,12 @@ aiString node_name(pID.c_str());
return false; return false;
} }
bool AMFImporter::Find_ConvertedMaterial(const std::string& pID, const SPP_Material** pConvertedMaterial) const bool AMFImporter::Find_ConvertedMaterial(const std::string& id, const SPP_Material** pConvertedMaterial) const {
{ for(const SPP_Material& mat: mMaterial_Converted) {
for(const SPP_Material& mat: mMaterial_Converted) if(mat.ID == id) {
{ if (pConvertedMaterial != nullptr) {
if(mat.ID == pID) *pConvertedMaterial = &mat;
{ }
if(pConvertedMaterial != nullptr) *pConvertedMaterial = &mat;
return true; return true;
} }
@ -153,13 +152,11 @@ bool AMFImporter::Find_ConvertedMaterial(const std::string& pID, const SPP_Mater
/************************************************************ Functions: throw set ***********************************************************/ /************************************************************ Functions: throw set ***********************************************************/
/*********************************************************************************************************************************************/ /*********************************************************************************************************************************************/
void AMFImporter::Throw_CloseNotFound(const std::string& pNode) void AMFImporter::Throw_CloseNotFound(const std::string& pNode) {
{
throw DeadlyImportError("Close tag for node <" + pNode + "> not found. Seems file is corrupt."); throw DeadlyImportError("Close tag for node <" + pNode + "> not found. Seems file is corrupt.");
} }
void AMFImporter::Throw_IncorrectAttr(const std::string& pAttrName) void AMFImporter::Throw_IncorrectAttr(const std::string& pAttrName) {
{
throw DeadlyImportError("Node <" + std::string(mReader->getNodeName()) + "> has incorrect attribute \"" + pAttrName + "\"."); throw DeadlyImportError("Node <" + std::string(mReader->getNodeName()) + "> has incorrect attribute \"" + pAttrName + "\".");
} }
@ -234,11 +231,13 @@ casu_cres:
} }
} }
bool AMFImporter::XML_SearchNode(const std::string& pNodeName) bool AMFImporter::XML_SearchNode(const std::string& pNodeName) {
{ mReader->
while(mReader->read()) while(mReader->read()) {
{ //if((mReader->getNodeType() == irr::io::EXN_ELEMENT) && XML_CheckNode_NameEqual(pNodeName)) return true;
if((mReader->getNodeType() == irr::io::EXN_ELEMENT) && XML_CheckNode_NameEqual(pNodeName)) return true; if ((mReader->getNodeType() == pugi::node_element) && XML_CheckNode_NameEqual(pNodeName)) {
return true;
}
} }
return false; return false;
@ -403,16 +402,22 @@ void AMFImporter::ParseHelper_Decode_Base64(const std::string& pInputBase64, std
void AMFImporter::ParseFile(const std::string& pFile, IOSystem* pIOHandler) void AMFImporter::ParseFile(const std::string& pFile, IOSystem* pIOHandler)
{ {
irr::io::IrrXMLReader* OldReader = mReader;// store current XMLreader. // irr::io::IrrXMLReader* OldReader = mReader;// store current XMLreader.
std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb")); std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
// Check whether we can read from the file // Check whether we can read from the file
if(file.get() == NULL) throw DeadlyImportError("Failed to open AMF file " + pFile + "."); if(file.get() == NULL) throw DeadlyImportError("Failed to open AMF file " + pFile + ".");
mReader = new XmlParser;
if (!mReader->parse(file.get())) {
throw DeadlyImportError("Failed to create XML reader for file" + pFile + ".");
}
// generate a XML reader for it // generate a XML reader for it
std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(file.get())); //std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(file.get()));
mReader = irr::io::createIrrXMLReader(mIOWrapper.get()); //mReader = irr::io::createIrrXMLReader(mIOWrapper.get());
if(!mReader) throw DeadlyImportError("Failed to create XML reader for file" + pFile + "."); //if(!mReader) throw DeadlyImportError("Failed to create XML reader for file" + pFile + ".");
// //
// start reading // start reading
// search for root tag <amf> // search for root tag <amf>

View File

@ -58,7 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
#include "assimp/types.h" #include "assimp/types.h"
#include <assimp/BaseImporter.h> #include <assimp/BaseImporter.h>
#include <assimp/irrXMLWrapper.h> #include <assimp/XmlParser.h>
// Header files, stdlib. // Header files, stdlib.
#include <set> #include <set>
@ -285,7 +285,10 @@ private:
/// Check if current node name is equal to pNodeName. /// Check if current node name is equal to pNodeName.
/// \param [in] pNodeName - name for checking. /// \param [in] pNodeName - name for checking.
/// return true if current node name is equal to pNodeName, else - false. /// return true if current node name is equal to pNodeName, else - false.
bool XML_CheckNode_NameEqual(const std::string& pNodeName) { return mReader->getNodeName() == pNodeName; } bool XML_CheckNode_NameEqual(const std::string& pNodeName){
// return mReader->getNodeName() == pNodeName;
mReader->mDoc.
}
/// Skip unsupported node and report about that. Depend on node name can be skipped begin tag of node all whole node. /// Skip unsupported node and report about that. Depend on node name can be skipped begin tag of node all whole node.
/// \param [in] pParentNodeName - parent node name. Used for reporting. /// \param [in] pParentNodeName - parent node name. Used for reporting.
@ -420,7 +423,8 @@ private:
CAMFImporter_NodeElement* mNodeElement_Cur;///< Current element. CAMFImporter_NodeElement* mNodeElement_Cur;///< Current element.
std::list<CAMFImporter_NodeElement*> mNodeElement_List;///< All elements of scene graph. std::list<CAMFImporter_NodeElement*> mNodeElement_List;///< All elements of scene graph.
irr::io::IrrXMLReader* mReader;///< Pointer to XML-reader object XmlParser *mReader;
//irr::io::IrrXMLReader* mReader;///< Pointer to XML-reader object
std::string mUnit; std::string mUnit;
std::list<SPP_Material> mMaterial_Converted;///< List of converted materials for postprocessing step. std::list<SPP_Material> mMaterial_Converted;///< List of converted materials for postprocessing step.
std::list<SPP_Texture> mTexture_Converted;///< List of converted textures for postprocessing step. std::list<SPP_Texture> mTexture_Converted;///< List of converted textures for postprocessing step.

View File

@ -61,7 +61,7 @@ namespace Assimp
// Parent element - <object>. // Parent element - <object>.
void AMFImporter::ParseNode_Mesh() void AMFImporter::ParseNode_Mesh()
{ {
CAMFImporter_NodeElement* ne; CAMFImporter_NodeElement* ne;
// create new mesh object. // create new mesh object.
ne = new CAMFImporter_NodeElement_Mesh(mNodeElement_Cur); ne = new CAMFImporter_NodeElement_Mesh(mNodeElement_Cur);

View File

@ -135,7 +135,7 @@ SET( PUBLIC_HEADERS
${HEADER_PATH}/XMLTools.h ${HEADER_PATH}/XMLTools.h
${HEADER_PATH}/IOStreamBuffer.h ${HEADER_PATH}/IOStreamBuffer.h
${HEADER_PATH}/CreateAnimMesh.h ${HEADER_PATH}/CreateAnimMesh.h
${HEADER_PATH}/irrXMLWrapper.h ${HEADER_PATH}/XmlParser.h
${HEADER_PATH}/BlobIOSystem.h ${HEADER_PATH}/BlobIOSystem.h
${HEADER_PATH}/MathFunctions.h ${HEADER_PATH}/MathFunctions.h
${HEADER_PATH}/Exceptional.h ${HEADER_PATH}/Exceptional.h
@ -703,8 +703,8 @@ SET( PostProcessing_SRCS
) )
SOURCE_GROUP( PostProcessing FILES ${PostProcessing_SRCS}) SOURCE_GROUP( PostProcessing FILES ${PostProcessing_SRCS})
SET( IrrXML_SRCS ${HEADER_PATH}/irrXMLWrapper.h ) #SET( IrrXML_SRCS ${HEADER_PATH}/irrXMLWrapper.h )
SOURCE_GROUP( IrrXML FILES ${IrrXML_SRCS}) #SOURCE_GROUP( IrrXML FILES ${IrrXML_SRCS})
ADD_ASSIMP_IMPORTER( Q3D ADD_ASSIMP_IMPORTER( Q3D
Q3D/Q3DLoader.cpp Q3D/Q3DLoader.cpp
@ -1105,7 +1105,7 @@ SET( assimp_src
${ASSIMP_EXPORTER_SRCS} ${ASSIMP_EXPORTER_SRCS}
# Third-party libraries # Third-party libraries
${IrrXML_SRCS} #${IrrXML_SRCS}
${unzip_compile_SRCS} ${unzip_compile_SRCS}
${Poly2Tri_SRCS} ${Poly2Tri_SRCS}
${Clipper_SRCS} ${Clipper_SRCS}

View File

@ -47,7 +47,7 @@
#ifndef AI_COLLADAPARSER_H_INC #ifndef AI_COLLADAPARSER_H_INC
#define AI_COLLADAPARSER_H_INC #define AI_COLLADAPARSER_H_INC
#include <assimp/irrXMLWrapper.h> #include <assimp/XmlParser.h>
#include "ColladaHelper.h" #include "ColladaHelper.h"
#include <assimp/ai_assert.h> #include <assimp/ai_assert.h>
#include <assimp/TinyFormatter.h> #include <assimp/TinyFormatter.h>

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@
#ifndef INCLUDED_AI_IRRSHARED_H #ifndef INCLUDED_AI_IRRSHARED_H
#define INCLUDED_AI_IRRSHARED_H #define INCLUDED_AI_IRRSHARED_H
#include <assimp/irrXMLWrapper.h> #include <assimp/XmlParser.h>
#include <assimp/BaseImporter.h> #include <assimp/BaseImporter.h>
#include <stdint.h> #include <stdint.h>
@ -78,9 +78,8 @@ protected:
typedef Property<aiVector3D> VectorProperty; typedef Property<aiVector3D> VectorProperty;
typedef Property<int> IntProperty; typedef Property<int> IntProperty;
/** XML reader instance /// XML reader instance
*/ XmlParser mParser;
irr::io::IrrXMLReader* reader;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Parse a material description from the XML /** Parse a material description from the XML

View File

@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
#include "OgreStructs.h" #include "OgreStructs.h"
#include <assimp/irrXMLWrapper.h> #include <assimp/XmlParser.h>
namespace Assimp namespace Assimp
{ {

View File

@ -60,7 +60,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef ASSIMP_USE_HUNTER #ifdef ASSIMP_USE_HUNTER
# include <irrXML/irrXML.h> # include <irrXML/irrXML.h>
#else #else
# include <irrXML.h> # include <assimp/XmlParser.h>
#endif #endif
namespace Assimp { namespace Assimp {

View File

@ -56,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/ProgressHandler.hpp> #include <assimp/ProgressHandler.hpp>
#include <assimp/types.h> #include <assimp/types.h>
#include <assimp/BaseImporter.h> #include <assimp/BaseImporter.h>
#include <assimp/irrXMLWrapper.h> #include <assimp/XmlParser.h>
#include "FIReader.hpp" #include "FIReader.hpp"
//#include <regex> //#include <regex>

View File

@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_XGLLOADER_H_INCLUDED #define AI_XGLLOADER_H_INCLUDED
#include <assimp/BaseImporter.h> #include <assimp/BaseImporter.h>
#include <assimp/irrXMLWrapper.h> #include <assimp/XmlParser.h>
#include <assimp/LogAux.h> #include <assimp/LogAux.h>
#include <assimp/material.h> #include <assimp/material.h>
#include <assimp/Importer.hpp> #include <assimp/Importer.hpp>

View File

@ -1,6 +1,6 @@
# Compile internal irrXML only if system is not requested # Compile internal irrXML only if system is not requested
if( NOT SYSTEM_IRRXML ) #if( NOT SYSTEM_IRRXML )
add_subdirectory(irrXML) # add_subdirectory(irrXML)
endif( NOT SYSTEM_IRRXML ) #endif( NOT SYSTEM_IRRXML )
add_subdirectory( pugixml-1.9 ) add_subdirectory( pugixml-1.9 )

View File

@ -1,29 +0,0 @@
set( IrrXML_SRCS
CXMLReaderImpl.h
heapsort.h
irrArray.h
irrString.h
irrTypes.h
irrXML.cpp
irrXML.h
)
if ( MSVC )
ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
endif ( MSVC )
IF(CMAKE_SYSTEM_NAME MATCHES "(Darwin|FreeBSD)")
add_library(IrrXML ${IrrXML_SRCS})
ELSE()
add_library(IrrXML STATIC ${IrrXML_SRCS})
ENDIF()
set(IRRXML_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "IrrXML_Include" )
set(IRRXML_LIBRARY "IrrXML" CACHE INTERNAL "IrrXML" )
install(TARGETS IrrXML
LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR}
FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
COMPONENT ${LIBASSIMP_COMPONENT})

View File

@ -1,819 +0,0 @@
// Copyright (C) 2002-2005 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine" and the "irrXML" project.
// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h
#ifndef __ICXML_READER_IMPL_H_INCLUDED__
#define __ICXML_READER_IMPL_H_INCLUDED__
#include "irrXML.h"
#include "irrString.h"
#include "irrArray.h"
#include <cassert>
#include <stdlib.h>
#include <cctype>
#include <cstdint>
//using namespace Assimp;
// For locale independent number conversion
#include <sstream>
#include <locale>
#ifdef _DEBUG
#define IRR_DEBUGPRINT(x) printf((x));
#else // _DEBUG
#define IRR_DEBUGPRINT(x)
#endif // _DEBUG
namespace irr
{
namespace io
{
//! implementation of the IrrXMLReader
template<class char_type, class superclass>
class CXMLReaderImpl : public IIrrXMLReader<char_type, superclass>
{
public:
//! Constructor
CXMLReaderImpl(IFileReadCallBack* callback, bool deleteCallBack = true)
: TextData(0), P(0), TextBegin(0), TextSize(0), CurrentNodeType(EXN_NONE),
SourceFormat(ETF_ASCII), TargetFormat(ETF_ASCII)
{
if (!callback)
return;
storeTargetFormat();
// read whole xml file
readFile(callback);
// clean up
if (deleteCallBack)
delete callback;
// create list with special characters
createSpecialCharacterList();
// set pointer to text begin
P = TextBegin;
}
//! Destructor
virtual ~CXMLReaderImpl()
{
delete [] TextData;
}
//! Reads forward to the next xml node.
//! \return Returns false, if there was no further node.
virtual bool read()
{
// if not end reached, parse the node
if (P && (unsigned int)(P - TextBegin) < TextSize - 1 && *P != 0)
{
parseCurrentNode();
return true;
}
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return false;
}
//! Returns the type of the current XML node.
virtual EXML_NODE getNodeType() const
{
return CurrentNodeType;
}
//! Returns attribute count of the current XML node.
virtual int getAttributeCount() const
{
return Attributes.size();
}
//! Returns name of an attribute.
virtual const char_type* getAttributeName(int idx) const
{
if (idx < 0 || idx >= (int)Attributes.size())
return 0;
return Attributes[idx].Name.c_str();
}
//! Returns the value of an attribute.
virtual const char_type* getAttributeValue(int idx) const
{
if (idx < 0 || idx >= (int)Attributes.size())
return 0;
return Attributes[idx].Value.c_str();
}
//! Returns the value of an attribute.
virtual const char_type* getAttributeValue(const char_type* name) const
{
const SAttribute* attr = getAttributeByName(name);
if (!attr)
return 0;
return attr->Value.c_str();
}
//! Returns the value of an attribute
virtual const char_type* getAttributeValueSafe(const char_type* name) const
{
const SAttribute* attr = getAttributeByName(name);
if (!attr)
return EmptyString.c_str();
return attr->Value.c_str();
}
//! Returns the value of an attribute as integer.
int getAttributeValueAsInt(const char_type* name) const
{
return (int)getAttributeValueAsFloat(name);
}
//! Returns the value of an attribute as integer.
int getAttributeValueAsInt(int idx) const
{
return (int)getAttributeValueAsFloat(idx);
}
//! Returns the value of an attribute as float.
float getAttributeValueAsFloat(const char_type* name) const
{
const SAttribute* attr = getAttributeByName(name);
if (!attr)
return 0;
core::stringc c = attr->Value.c_str();
return static_cast<float>(atof(c.c_str()));
//return fast_atof(c.c_str());
}
//! Returns the value of an attribute as float.
float getAttributeValueAsFloat(int idx) const
{
const char_type* attrvalue = getAttributeValue(idx);
if (!attrvalue)
return 0;
core::stringc c = attrvalue;
std::istringstream sstr(c.c_str());
sstr.imbue(std::locale("C")); // Locale free number convert
float fNum;
sstr >> fNum;
return fNum;
}
//! Returns the name of the current node.
virtual const char_type* getNodeName() const
{
return NodeName.c_str();
}
//! Returns data of the current node.
virtual const char_type* getNodeData() const
{
return NodeName.c_str();
}
//! Returns if an element is an empty element, like <foo />
virtual bool isEmptyElement() const
{
return IsEmptyElement;
}
//! Returns format of the source xml file.
virtual ETEXT_FORMAT getSourceFormat() const
{
return SourceFormat;
}
//! Returns format of the strings returned by the parser.
virtual ETEXT_FORMAT getParserFormat() const
{
return TargetFormat;
}
private:
// Reads the current xml node
void parseCurrentNode()
{
char_type* start = P;
// move forward until '<' found
while(*P != L'<' && *P)
++P;
if (!*P)
return;
if (P - start > 0)
{
// we found some text, store it
if (setText(start, P))
return;
}
++P;
// based on current token, parse and report next element
switch(*P)
{
case L'/':
parseClosingXMLElement();
break;
case L'?':
ignoreDefinition();
break;
case L'!':
if (!parseCDATA())
parseComment();
break;
default:
parseOpeningXMLElement();
break;
}
}
//! sets the state that text was found. Returns true if set should be set
bool setText(char_type* start, char_type* end)
{
// check if text is more than 2 characters, and if not, check if there is
// only white space, so that this text won't be reported
if (end - start < 3)
{
char_type* p = start;
for(; p != end; ++p)
if (!isWhiteSpace(*p))
break;
if (p == end)
return false;
}
// set current text to the parsed text, and replace xml special characters
core::string<char_type> s(start, (int)(end - start));
NodeName = replaceSpecialCharacters(s);
// current XML node type is text
CurrentNodeType = EXN_TEXT;
return true;
}
//! ignores an xml definition like <?xml something />
void ignoreDefinition()
{
CurrentNodeType = EXN_UNKNOWN;
// move until end marked with '>' reached
while(*P != L'>')
++P;
++P;
}
//! parses a comment
void parseComment()
{
CurrentNodeType = EXN_COMMENT;
P += 1;
char_type *pCommentBegin = P;
int count = 1;
// move until end of comment reached
while(count)
{
if (*P == L'>')
--count;
else
if (*P == L'<')
++count;
++P;
}
P -= 3;
NodeName = core::string<char_type>(pCommentBegin+2, (int)(P - pCommentBegin-2));
P += 3;
}
//! parses an opening xml element and reads attributes
void parseOpeningXMLElement()
{
CurrentNodeType = EXN_ELEMENT;
IsEmptyElement = false;
Attributes.clear();
// find name
const char_type* startName = P;
// find end of element
while(*P != L'>' && !isWhiteSpace(*P))
++P;
const char_type* endName = P;
// find Attributes
while(*P != L'>')
{
if (isWhiteSpace(*P))
++P;
else
{
if (*P != L'/')
{
// we've got an attribute
// read the attribute names
const char_type* attributeNameBegin = P;
while(!isWhiteSpace(*P) && *P != L'=')
++P;
const char_type* attributeNameEnd = P;
++P;
// read the attribute value
// check for quotes and single quotes, thx to murphy
while( (*P != L'\"') && (*P != L'\'') && *P)
++P;
if (!*P) // malformatted xml file
return;
const char_type attributeQuoteChar = *P;
++P;
const char_type* attributeValueBegin = P;
while(*P != attributeQuoteChar && *P)
++P;
if (!*P) // malformatted xml file
return;
const char_type* attributeValueEnd = P;
++P;
SAttribute attr;
attr.Name = core::string<char_type>(attributeNameBegin,
(int)(attributeNameEnd - attributeNameBegin));
core::string<char_type> s(attributeValueBegin,
(int)(attributeValueEnd - attributeValueBegin));
attr.Value = replaceSpecialCharacters(s);
Attributes.push_back(attr);
}
else
{
// tag is closed directly
++P;
IsEmptyElement = true;
break;
}
}
}
// check if this tag is closing directly
if (endName > startName && *(endName-1) == L'/')
{
// directly closing tag
IsEmptyElement = true;
endName--;
}
NodeName = core::string<char_type>(startName, (int)(endName - startName));
++P;
}
//! parses an closing xml tag
void parseClosingXMLElement()
{
CurrentNodeType = EXN_ELEMENT_END;
IsEmptyElement = false;
Attributes.clear();
++P;
const char_type* pBeginClose = P;
while(*P != L'>')
++P;
// remove trailing whitespace, if any
while( std::isspace( P[-1]))
--P;
NodeName = core::string<char_type>(pBeginClose, (int)(P - pBeginClose));
++P;
}
//! parses a possible CDATA section, returns false if begin was not a CDATA section
bool parseCDATA()
{
if (*(P+1) != L'[')
return false;
CurrentNodeType = EXN_CDATA;
// skip '<![CDATA['
int count=0;
while( *P && count<8 )
{
++P;
++count;
}
if (!*P)
return true;
char_type *cDataBegin = P;
char_type *cDataEnd = 0;
// find end of CDATA
while(*P && !cDataEnd)
{
if (*P == L'>' &&
(*(P-1) == L']') &&
(*(P-2) == L']'))
{
cDataEnd = P - 2;
}
++P;
}
if ( cDataEnd )
NodeName = core::string<char_type>(cDataBegin, (int)(cDataEnd - cDataBegin));
else
NodeName = "";
return true;
}
// structure for storing attribute-name pairs
struct SAttribute
{
core::string<char_type> Name;
core::string<char_type> Value;
};
// finds a current attribute by name, returns 0 if not found
const SAttribute* getAttributeByName(const char_type* name) const
{
if (!name)
return 0;
core::string<char_type> n = name;
for (int i=0; i<(int)Attributes.size(); ++i)
if (Attributes[i].Name == n)
return &Attributes[i];
return 0;
}
// replaces xml special characters in a string and creates a new one
core::string<char_type> replaceSpecialCharacters(
core::string<char_type>& origstr)
{
int pos = origstr.findFirst(L'&');
int oldPos = 0;
if (pos == -1)
return origstr;
core::string<char_type> newstr;
while(pos != -1 && pos < origstr.size()-2)
{
// check if it is one of the special characters
int specialChar = -1;
for (int i=0; i<(int)SpecialCharacters.size(); ++i)
{
const char_type* p = &origstr.c_str()[pos]+1;
if (equalsn(&SpecialCharacters[i][1], p, SpecialCharacters[i].size()-1))
{
specialChar = i;
break;
}
}
if (specialChar != -1)
{
newstr.append(origstr.subString(oldPos, pos - oldPos));
newstr.append(SpecialCharacters[specialChar][0]);
pos += SpecialCharacters[specialChar].size();
}
else
{
newstr.append(origstr.subString(oldPos, pos - oldPos + 1));
pos += 1;
}
// find next &
oldPos = pos;
pos = origstr.findNext(L'&', pos);
}
if (oldPos < origstr.size()-1)
newstr.append(origstr.subString(oldPos, origstr.size()-oldPos));
return newstr;
}
//! reads the xml file and converts it into the wanted character format.
bool readFile(IFileReadCallBack* callback)
{
int size = callback->getSize();
size += 4; // We need two terminating 0's at the end.
// For ASCII we need 1 0's, for UTF-16 2, for UTF-32 4.
char* data8 = new char[size];
if (!callback->read(data8, size-4))
{
delete [] data8;
return false;
}
// add zeros at end
data8[size-1] = 0;
data8[size-2] = 0;
data8[size-3] = 0;
data8[size-4] = 0;
char16* data16 = reinterpret_cast<char16*>(data8);
char32* data32 = reinterpret_cast<char32*>(data8);
// now we need to convert the data to the desired target format
// based on the byte order mark.
const unsigned char UTF8[] = {0xEF, 0xBB, 0xBF}; // 0xEFBBBF;
const int UTF16_BE = 0xFFFE;
const int UTF16_LE = 0xFEFF;
const int UTF32_BE = 0xFFFE0000;
const int UTF32_LE = 0x0000FEFF;
// check source for all utf versions and convert to target data format
if (size >= 4 && data32[0] == (char32)UTF32_BE)
{
// UTF-32, big endian
SourceFormat = ETF_UTF32_BE;
convertTextData(data32+1, data8, (size/4)); // data32+1 because we need to skip the header
}
else
if (size >= 4 && data32[0] == (char32)UTF32_LE)
{
// UTF-32, little endian
SourceFormat = ETF_UTF32_LE;
convertTextData(data32+1, data8, (size/4)); // data32+1 because we need to skip the header
}
else
if (size >= 2 && data16[0] == UTF16_BE)
{
// UTF-16, big endian
SourceFormat = ETF_UTF16_BE;
convertTextData(data16+1, data8, (size/2)); // data16+1 because we need to skip the header
}
else
if (size >= 2 && data16[0] == UTF16_LE)
{
// UTF-16, little endian
SourceFormat = ETF_UTF16_LE;
convertTextData(data16+1, data8, (size/2)); // data16+1 because we need to skip the header
}
else
if (size >= 3 && data8[0] == UTF8[0] && data8[1] == UTF8[1] && data8[2] == UTF8[2])
{
// UTF-8
SourceFormat = ETF_UTF8;
convertTextData(data8+3, data8, size); // data8+3 because we need to skip the header
}
else
{
// ASCII
SourceFormat = ETF_ASCII;
convertTextData(data8, data8, size);
}
return true;
}
//! converts the text file into the desired format.
//! \param source: begin of the text (without byte order mark)
//! \param pointerToStore: pointer to text data block which can be
//! stored or deleted based on the nesessary conversion.
//! \param sizeWithoutHeader: Text size in characters without header
template<class src_char_type>
void convertTextData(src_char_type* source, char* pointerToStore, int sizeWithoutHeader)
{
// convert little to big endian if necessary
if (sizeof(src_char_type) > 1 &&
isLittleEndian(TargetFormat) != isLittleEndian(SourceFormat))
convertToLittleEndian(source);
// check if conversion is necessary:
if (sizeof(src_char_type) == sizeof(char_type))
{
// no need to convert
TextBegin = (char_type*)source;
TextData = (char_type*)pointerToStore;
TextSize = sizeWithoutHeader;
}
else
{
// convert source into target data format.
// TODO: implement a real conversion. This one just
// copies bytes. This is a problem when there are
// unicode symbols using more than one character.
TextData = new char_type[sizeWithoutHeader];
// MSVC debugger complains here about loss of data ...
size_t numShift = sizeof( char_type) * 8;
assert(numShift < 64);
const src_char_type cc = (src_char_type)(((uint64_t(1u) << numShift) - 1));
for (int i=0; i<sizeWithoutHeader; ++i)
TextData[i] = char_type( source[i] & cc);
TextBegin = TextData;
TextSize = sizeWithoutHeader;
// delete original data because no longer needed
delete [] pointerToStore;
}
}
//! converts whole text buffer to little endian
template<class src_char_type>
void convertToLittleEndian(src_char_type* t)
{
if (sizeof(src_char_type) == 4)
{
// 32 bit
while(*t)
{
*t = ((*t & 0xff000000) >> 24) |
((*t & 0x00ff0000) >> 8) |
((*t & 0x0000ff00) << 8) |
((*t & 0x000000ff) << 24);
++t;
}
}
else
{
// 16 bit
while(*t)
{
*t = (*t >> 8) | (*t << 8);
++t;
}
}
}
//! returns if a format is little endian
inline bool isLittleEndian(ETEXT_FORMAT f)
{
return f == ETF_ASCII ||
f == ETF_UTF8 ||
f == ETF_UTF16_LE ||
f == ETF_UTF32_LE;
}
//! returns true if a character is whitespace
inline bool isWhiteSpace(char_type c)
{
return (c==' ' || c=='\t' || c=='\n' || c=='\r');
}
//! generates a list with xml special characters
void createSpecialCharacterList()
{
// list of strings containing special symbols,
// the first character is the special character,
// the following is the symbol string without trailing &.
SpecialCharacters.push_back("&amp;");
SpecialCharacters.push_back("<lt;");
SpecialCharacters.push_back(">gt;");
SpecialCharacters.push_back("\"quot;");
SpecialCharacters.push_back("'apos;");
}
//! compares the first n characters of the strings
bool equalsn(const char_type* str1, const char_type* str2, int len)
{
int i;
for(i=0; str1[i] && str2[i] && i < len; ++i)
if (str1[i] != str2[i])
return false;
// if one (or both) of the strings was smaller then they
// are only equal if they have the same lenght
return (i == len) || (str1[i] == 0 && str2[i] == 0);
}
//! stores the target text format
void storeTargetFormat()
{
// get target format. We could have done this using template specialization,
// but VisualStudio 6 don't like it and we want to support it.
switch(sizeof(char_type))
{
case 1:
TargetFormat = ETF_UTF8;
break;
case 2:
TargetFormat = ETF_UTF16_LE;
break;
case 4:
TargetFormat = ETF_UTF32_LE;
break;
default:
TargetFormat = ETF_ASCII; // should never happen.
}
}
// instance variables:
char_type* TextData; // data block of the text file
char_type* P; // current point in text to parse
char_type* TextBegin; // start of text to parse
unsigned int TextSize; // size of text to parse in characters, not bytes
EXML_NODE CurrentNodeType; // type of the currently parsed node
ETEXT_FORMAT SourceFormat; // source format of the xml file
ETEXT_FORMAT TargetFormat; // output format of this parser
core::string<char_type> NodeName; // name of the node currently in
core::string<char_type> EmptyString; // empty string to be returned by getSafe() methods
bool IsEmptyElement; // is the currently parsed node empty?
core::array< core::string<char_type> > SpecialCharacters; // see createSpecialCharacterList()
core::array<SAttribute> Attributes; // attributes of current element
}; // end CXMLReaderImpl
} // end namespace
} // end namespace
#endif

View File

@ -1,73 +0,0 @@
// Copyright (C) 2002-2005 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __IRR_HEAPSORT_H_INCLUDED__
#define __IRR_HEAPSORT_H_INCLUDED__
#include "irrTypes.h"
namespace irr
{
namespace core
{
//! Sinks an element into the heap.
template<class T>
inline void heapsink(T*array, s32 element, s32 max)
{
while ((element<<1) < max) // there is a left child
{
s32 j = (element<<1);
if (j+1 < max && array[j] < array[j+1])
j = j+1; // take right child
if (array[element] < array[j])
{
T t = array[j]; // swap elements
array[j] = array[element];
array[element] = t;
element = j;
}
else
return;
}
}
//! Sorts an array with size 'size' using heapsort.
template<class T>
inline void heapsort(T* array_, s32 size)
{
// for heapsink we pretent this is not c++, where
// arrays start with index 0. So we decrease the array pointer,
// the maximum always +2 and the element always +1
T* virtualArray = array_ - 1;
s32 virtualSize = size + 2;
s32 i;
// build heap
for (i=((size-1)/2); i>=0; --i)
heapsink(virtualArray, i+1, virtualSize-1);
// sort array
for (i=size-1; i>=0; --i)
{
T t = array_[0];
array_[0] = array_[i];
array_[i] = t;
heapsink(virtualArray, 1, i + 1);
}
}
} // end namespace core
} // end namespace irr
#endif

View File

@ -1,443 +0,0 @@
// Copyright (C) 2002-2005 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine" and the "irrXML" project.
// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h
#ifndef __IRR_ARRAY_H_INCLUDED__
#define __IRR_ARRAY_H_INCLUDED__
#include "irrTypes.h"
#include "heapsort.h"
namespace irr
{
namespace core
{
//! Self reallocating template array (like stl vector) with additional features.
/** Some features are: Heap sorting, binary search methods, easier debugging.
*/
template <class T>
class array
{
public:
array()
: data(0), allocated(0), used(0),
free_when_destroyed(true), is_sorted(true)
{
}
//! Constructs a array and allocates an initial chunk of memory.
//! \param start_count: Amount of elements to allocate.
array(u32 start_count)
: data(0), allocated(0), used(0),
free_when_destroyed(true), is_sorted(true)
{
reallocate(start_count);
}
//! Copy constructor
array(const array<T>& other)
: data(0)
{
*this = other;
}
//! Destructor. Frees allocated memory, if set_free_when_destroyed
//! was not set to false by the user before.
~array()
{
if (free_when_destroyed)
delete [] data;
}
//! Reallocates the array, make it bigger or smaller.
//! \param new_size: New size of array.
void reallocate(u32 new_size)
{
T* old_data = data;
data = new T[new_size];
allocated = new_size;
s32 end = used < new_size ? used : new_size;
for (s32 i=0; i<end; ++i)
data[i] = old_data[i];
if (allocated < used)
used = allocated;
delete [] old_data;
}
//! Adds an element at back of array. If the array is to small to
//! add this new element, the array is made bigger.
//! \param element: Element to add at the back of the array.
void push_back(const T& element)
{
if (used + 1 > allocated)
{
// reallocate(used * 2 +1);
// this doesn't work if the element is in the same array. So
// we'll copy the element first to be sure we'll get no data
// corruption
T e;
e = element; // copy element
reallocate(used * 2 +1); // increase data block
data[used++] = e; // push_back
is_sorted = false;
return;
}
data[used++] = element;
is_sorted = false;
}
//! Adds an element at the front of the array. If the array is to small to
//! add this new element, the array is made bigger. Please note that this
//! is slow, because the whole array needs to be copied for this.
//! \param element: Element to add at the back of the array.
void push_front(const T& element)
{
if (used + 1 > allocated)
reallocate(used * 2 +1);
for (int i=(int)used; i>0; --i)
data[i] = data[i-1];
data[0] = element;
is_sorted = false;
++used;
}
//! Insert item into array at specified position. Please use this
//! only if you know what you are doing (possible performance loss).
//! The preferred method of adding elements should be push_back().
//! \param element: Element to be inserted
//! \param index: Where position to insert the new element.
void insert(const T& element, u32 index=0)
{
_IRR_DEBUG_BREAK_IF(index>used) // access violation
if (used + 1 > allocated)
reallocate(used * 2 +1);
for (u32 i=used++; i>index; i--)
data[i] = data[i-1];
data[index] = element;
is_sorted = false;
}
//! Clears the array and deletes all allocated memory.
void clear()
{
delete [] data;
data = 0;
used = 0;
allocated = 0;
is_sorted = true;
}
//! Sets pointer to new array, using this as new workspace.
//! \param newPointer: Pointer to new array of elements.
//! \param size: Size of the new array.
void set_pointer(T* newPointer, u32 size)
{
delete [] data;
data = newPointer;
allocated = size;
used = size;
is_sorted = false;
}
//! Sets if the array should delete the memory it used.
//! \param f: If true, the array frees the allocated memory in its
//! destructor, otherwise not. The default is true.
void set_free_when_destroyed(bool f)
{
free_when_destroyed = f;
}
//! Sets the size of the array.
//! \param usedNow: Amount of elements now used.
void set_used(u32 usedNow)
{
if (allocated < usedNow)
reallocate(usedNow);
used = usedNow;
}
//! Assignement operator
void operator=(const array<T>& other)
{
if (data)
delete [] data;
//if (allocated < other.allocated)
if (other.allocated == 0)
data = 0;
else
data = new T[other.allocated];
used = other.used;
free_when_destroyed = other.free_when_destroyed;
is_sorted = other.is_sorted;
allocated = other.allocated;
for (u32 i=0; i<other.used; ++i)
data[i] = other.data[i];
}
//! Direct access operator
T& operator [](u32 index)
{
_IRR_DEBUG_BREAK_IF(index>=used) // access violation
return data[index];
}
//! Direct access operator
const T& operator [](u32 index) const
{
_IRR_DEBUG_BREAK_IF(index>=used) // access violation
return data[index];
}
//! Gets last frame
const T& getLast() const
{
_IRR_DEBUG_BREAK_IF(!used) // access violation
return data[used-1];
}
//! Gets last frame
T& getLast()
{
_IRR_DEBUG_BREAK_IF(!used) // access violation
return data[used-1];
}
//! Returns a pointer to the array.
//! \return Pointer to the array.
T* pointer()
{
return data;
}
//! Returns a const pointer to the array.
//! \return Pointer to the array.
const T* const_pointer() const
{
return data;
}
//! Returns size of used array.
//! \return Size of elements in the array.
u32 size() const
{
return used;
}
//! Returns amount memory allocated.
//! \return Returns amount of memory allocated. The amount of bytes
//! allocated would be allocated_size() * sizeof(ElementsUsed);
u32 allocated_size() const
{
return allocated;
}
//! Returns true if array is empty
//! \return True if the array is empty, false if not.
bool empty() const
{
return used == 0;
}
//! Sorts the array using heapsort. There is no additional memory waste and
//! the algorithm performs (O) n log n in worst case.
void sort()
{
if (is_sorted || used<2)
return;
heapsort(data, used);
is_sorted = true;
}
//! Performs a binary search for an element, returns -1 if not found.
//! The array will be sorted before the binary search if it is not
//! already sorted.
//! \param element: Element to search for.
//! \return Returns position of the searched element if it was found,
//! otherwise -1 is returned.
s32 binary_search(const T& element)
{
return binary_search(element, 0, used-1);
}
//! Performs a binary search for an element, returns -1 if not found.
//! The array will be sorted before the binary search if it is not
//! already sorted.
//! \param element: Element to search for.
//! \param left: First left index
//! \param right: Last right index.
//! \return Returns position of the searched element if it was found,
//! otherwise -1 is returned.
s32 binary_search(const T& element, s32 left, s32 right)
{
if (!used)
return -1;
sort();
s32 m;
do
{
m = (left+right)>>1;
if (element < data[m])
right = m - 1;
else
left = m + 1;
} while((element < data[m] || data[m] < element) && left<=right);
// this last line equals to:
// " while((element != array[m]) && left<=right);"
// but we only want to use the '<' operator.
// the same in next line, it is "(element == array[m])"
if (!(element < data[m]) && !(data[m] < element))
return m;
return -1;
}
//! Finds an element in linear time, which is very slow. Use
//! binary_search for faster finding. Only works if =operator is implemented.
//! \param element: Element to search for.
//! \return Returns position of the searched element if it was found,
//! otherwise -1 is returned.
s32 linear_search(T& element)
{
for (u32 i=0; i<used; ++i)
if (!(element < data[i]) && !(data[i] < element))
return (s32)i;
return -1;
}
//! Finds an element in linear time, which is very slow. Use
//! binary_search for faster finding. Only works if =operator is implemented.
//! \param element: Element to search for.
//! \return Returns position of the searched element if it was found,
//! otherwise -1 is returned.
s32 linear_reverse_search(T& element)
{
for (s32 i=used-1; i>=0; --i)
if (data[i] == element)
return (s32)i;
return -1;
}
//! Erases an element from the array. May be slow, because all elements
//! following after the erased element have to be copied.
//! \param index: Index of element to be erased.
void erase(u32 index)
{
_IRR_DEBUG_BREAK_IF(index>=used || index<0) // access violation
for (u32 i=index+1; i<used; ++i)
data[i-1] = data[i];
--used;
}
//! Erases some elements from the array. may be slow, because all elements
//! following after the erased element have to be copied.
//! \param index: Index of the first element to be erased.
//! \param count: Amount of elements to be erased.
void erase(u32 index, s32 count)
{
_IRR_DEBUG_BREAK_IF(index>=used || index<0 || count<1 || index+count>used) // access violation
for (u32 i=index+count; i<used; ++i)
data[i-count] = data[i];
used-= count;
}
//! Sets if the array is sorted
void set_sorted(bool _is_sorted)
{
is_sorted = _is_sorted;
}
private:
T* data;
u32 allocated;
u32 used;
bool free_when_destroyed;
bool is_sorted;
};
} // end namespace core
} // end namespace irr
#endif

View File

@ -1,664 +0,0 @@
// Copyright (C) 2002-2005 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine" and the "irrXML" project.
// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h
#ifndef __IRR_STRING_H_INCLUDED__
#define __IRR_STRING_H_INCLUDED__
#include "irrTypes.h"
namespace irr
{
namespace core
{
//! Very simple string class with some useful features.
/** string<c8> and string<wchar_t> work both with unicode AND ascii,
so you can assign unicode to string<c8> and ascii to string<wchar_t>
(and the other way round) if your ever would want to.
Note that the conversation between both is not done using an encoding.
Known bugs:
Special characters like 'Ă„', 'Ăś' and 'Ă–' are ignored in the
methods make_upper, make_lower and equals_ignore_case.
*/
template <class T>
class string
{
public:
//! Default constructor
string()
: array(0), allocated(1), used(1)
{
array = new T[1];
array[0] = 0x0;
}
//! Constructor
string(const string<T>& other)
: array(0), allocated(0), used(0)
{
*this = other;
}
//! Constructs a string from an int
string(int number)
: array(0), allocated(0), used(0)
{
// store if negative and make positive
bool negative = false;
if (number < 0)
{
number *= -1;
negative = true;
}
// temporary buffer for 16 numbers
c8 tmpbuf[16];
tmpbuf[15] = 0;
s32 idx = 15;
// special case '0'
if (!number)
{
tmpbuf[14] = '0';
*this = &tmpbuf[14];
return;
}
// add numbers
while(number && idx)
{
idx--;
tmpbuf[idx] = (c8)('0' + (number % 10));
number = number / 10;
}
// add sign
if (negative)
{
idx--;
tmpbuf[idx] = '-';
}
*this = &tmpbuf[idx];
}
//! Constructor for copying a string from a pointer with a given lenght
template <class B>
string(const B* c, s32 lenght)
: array(0), allocated(0), used(0)
{
if (!c)
return;
allocated = used = lenght+1;
array = new T[used];
for (s32 l = 0; l<lenght; ++l)
array[l] = (T)c[l];
array[lenght] = 0;
}
//! Constructor for unicode and ascii strings
template <class B>
string(const B* c)
: array(0),allocated(0), used(0)
{
*this = c;
}
//! destructor
~string()
{
delete [] array;
}
//! Assignment operator
string<T>& operator=(const string<T>& other)
{
if (this == &other)
return *this;
delete [] array;
allocated = used = other.size()+1;
array = new T[used];
const T* p = other.c_str();
for (s32 i=0; i<used; ++i, ++p)
array[i] = *p;
return *this;
}
//! Assignment operator for strings, ascii and unicode
template <class B>
string<T>& operator=(const B* c)
{
if (!c)
{
if (!array)
{
array = new T[1];
allocated = 1;
used = 1;
}
array[0] = 0x0;
return *this;
}
if ((void*)c == (void*)array)
return *this;
s32 len = 0;
const B* p = c;
while(*p)
{
++len;
++p;
}
// we'll take the old string for a while, because the new string could be
// a part of the current string.
T* oldArray = array;
allocated = used = len+1;
array = new T[used];
for (s32 l = 0; l<len+1; ++l)
array[l] = (T)c[l];
delete [] oldArray;
return *this;
}
//! Add operator for other strings
string<T> operator+(const string<T>& other)
{
string<T> str(*this);
str.append(other);
return str;
}
//! Add operator for strings, ascii and unicode
template <class B>
string<T> operator+(const B* c)
{
string<T> str(*this);
str.append(c);
return str;
}
//! Direct access operator
T& operator [](const s32 index) const
{
_IRR_DEBUG_BREAK_IF(index>=used) // bad index
return array[index];
}
//! Comparison operator
bool operator ==(const T* str) const
{
int i;
for(i=0; array[i] && str[i]; ++i)
if (array[i] != str[i])
return false;
return !array[i] && !str[i];
}
//! Comparison operator
bool operator ==(const string<T>& other) const
{
for(s32 i=0; array[i] && other.array[i]; ++i)
if (array[i] != other.array[i])
return false;
return used == other.used;
}
//! Is smaller operator
bool operator <(const string<T>& other) const
{
for(s32 i=0; array[i] && other.array[i]; ++i)
if (array[i] != other.array[i])
return (array[i] < other.array[i]);
return used < other.used;
}
//! Equals not operator
bool operator !=(const string<T>& other) const
{
return !(*this == other);
}
//! Returns length of string
/** \return Returns length of the string in characters. */
s32 size() const
{
return used-1;
}
//! Returns character string
/** \return Returns pointer to C-style zero terminated string. */
const T* c_str() const
{
return array;
}
//! Makes the string lower case.
void make_lower()
{
const T A = (T)'A';
const T Z = (T)'Z';
const T diff = (T)'a' - A;
for (s32 i=0; i<used; ++i)
{
if (array[i]>=A && array[i]<=Z)
array[i] += diff;
}
}
//! Makes the string upper case.
void make_upper()
{
const T a = (T)'a';
const T z = (T)'z';
const T diff = (T)'A' - a;
for (s32 i=0; i<used; ++i)
{
if (array[i]>=a && array[i]<=z)
array[i] += diff;
}
}
//! Compares the string ignoring case.
/** \param other: Other string to compare.
\return Returns true if the string are equal ignoring case. */
bool equals_ignore_case(const string<T>& other) const
{
for(s32 i=0; array[i] && other[i]; ++i)
if (toLower(array[i]) != toLower(other[i]))
return false;
return used == other.used;
}
//! compares the first n characters of the strings
bool equalsn(const string<T>& other, int len)
{
int i;
for(i=0; array[i] && other[i] && i < len; ++i)
if (array[i] != other[i])
return false;
// if one (or both) of the strings was smaller then they
// are only equal if they have the same lenght
return (i == len) || (used == other.used);
}
//! compares the first n characters of the strings
bool equalsn(const T* str, int len)
{
int i;
for(i=0; array[i] && str[i] && i < len; ++i)
if (array[i] != str[i])
return false;
// if one (or both) of the strings was smaller then they
// are only equal if they have the same lenght
return (i == len) || (array[i] == 0 && str[i] == 0);
}
//! Appends a character to this string
/** \param character: Character to append. */
void append(T character)
{
if (used + 1 > allocated)
reallocate((s32)used + 1);
used += 1;
array[used-2] = character;
array[used-1] = 0;
}
//! Appends a string to this string
/** \param other: String to append. */
void append(const string<T>& other)
{
--used;
s32 len = other.size();
if (used + len + 1 > allocated)
reallocate((s32)used + (s32)len + 1);
for (s32 l=0; l<len+1; ++l)
array[l+used] = other[l];
used = used + len + 1;
}
//! Appends a string of the length l to this string.
/** \param other: other String to append to this string.
\param length: How much characters of the other string to add to this one. */
void append(const string<T>& other, s32 length)
{
s32 len = other.size();
if (len < length)
{
append(other);
return;
}
len = length;
--used;
if (used + len > allocated)
reallocate((s32)used + (s32)len);
for (s32 l=0; l<len; ++l)
array[l+used] = other[l];
used = used + len;
}
//! Reserves some memory.
/** \param count: Amount of characters to reserve. */
void reserve(s32 count)
{
if (count < allocated)
return;
reallocate(count);
}
//! finds first occurrence of character in string
/** \param c: Character to search for.
\return Returns position where the character has been found,
or -1 if not found. */
s32 findFirst(T c) const
{
for (s32 i=0; i<used; ++i)
if (array[i] == c)
return i;
return -1;
}
//! finds first occurrence of a character of a list in string
/** \param c: List of strings to find. For example if the method
should find the first occurance of 'a' or 'b', this parameter should be "ab".
\param count: Amount of characters in the list. Ususally,
this should be strlen(ofParameter1)
\return Returns position where one of the character has been found,
or -1 if not found. */
s32 findFirstChar(T* c, int count) const
{
for (s32 i=0; i<used; ++i)
for (int j=0; j<count; ++j)
if (array[i] == c[j])
return i;
return -1;
}
//! Finds first position of a character not in a given list.
/** \param c: List of characters not to find. For example if the method
should find the first occurance of a character not 'a' or 'b', this parameter should be "ab".
\param count: Amount of characters in the list. Ususally,
this should be strlen(ofParameter1)
\return Returns position where the character has been found,
or -1 if not found. */
template <class B>
s32 findFirstCharNotInList(B* c, int count) const
{
for (int i=0; i<used; ++i)
{
int j;
for (j=0; j<count; ++j)
if (array[i] == c[j])
break;
if (j==count)
return i;
}
return -1;
}
//! Finds last position of a character not in a given list.
/** \param c: List of characters not to find. For example if the method
should find the first occurance of a character not 'a' or 'b', this parameter should be "ab".
\param count: Amount of characters in the list. Ususally,
this should be strlen(ofParameter1)
\return Returns position where the character has been found,
or -1 if not found. */
template <class B>
s32 findLastCharNotInList(B* c, int count) const
{
for (int i=used-2; i>=0; --i)
{
int j;
for (j=0; j<count; ++j)
if (array[i] == c[j])
break;
if (j==count)
return i;
}
return -1;
}
//! finds next occurrence of character in string
/** \param c: Character to search for.
\param startPos: Position in string to start searching.
\return Returns position where the character has been found,
or -1 if not found. */
s32 findNext(T c, s32 startPos) const
{
for (s32 i=startPos; i<used; ++i)
if (array[i] == c)
return i;
return -1;
}
//! finds last occurrence of character in string
//! \param c: Character to search for.
//! \return Returns position where the character has been found,
//! or -1 if not found.
s32 findLast(T c) const
{
for (s32 i=used-1; i>=0; --i)
if (array[i] == c)
return i;
return -1;
}
//! Returns a substring
//! \param begin: Start of substring.
//! \param length: Length of substring.
string<T> subString(s32 begin, s32 length)
{
if (length <= 0)
return string<T>("");
string<T> o;
o.reserve(length+1);
for (s32 i=0; i<length; ++i)
o.array[i] = array[i+begin];
o.array[length] = 0;
o.used = o.allocated;
return o;
}
void operator += (T c)
{
append(c);
}
void operator += (const string<T>& other)
{
append(other);
}
void operator += (int i)
{
append(string<T>(i));
}
//! replaces all characters of a special type with another one
void replace(T toReplace, T replaceWith)
{
for (s32 i=0; i<used; ++i)
if (array[i] == toReplace)
array[i] = replaceWith;
}
//! trims the string.
/** Removes whitespace from begin and end of the string. */
void trim()
{
const char whitespace[] = " \t\n";
const int whitespacecount = 3;
// find start and end of real string without whitespace
int begin = findFirstCharNotInList(whitespace, whitespacecount);
if (begin == -1)
return;
int end = findLastCharNotInList(whitespace, whitespacecount);
if (end == -1)
return;
*this = subString(begin, (end +1) - begin);
}
//! Erases a character from the string. May be slow, because all elements
//! following after the erased element have to be copied.
//! \param index: Index of element to be erased.
void erase(int index)
{
_IRR_DEBUG_BREAK_IF(index>=used || index<0) // access violation
for (int i=index+1; i<used; ++i)
array[i-1] = array[i];
--used;
}
private:
//! Returns a character converted to lower case
T toLower(const T& t) const
{
if (t>=(T)'A' && t<=(T)'Z')
return t + ((T)'a' - (T)'A');
else
return t;
}
//! Reallocate the array, make it bigger or smaler
void reallocate(s32 new_size)
{
T* old_array = array;
array = new T[new_size];
allocated = new_size;
s32 amount = used < new_size ? used : new_size;
for (s32 i=0; i<amount; ++i)
array[i] = old_array[i];
if (allocated < used)
used = allocated;
delete [] old_array;
}
//--- member variables
T* array;
s32 allocated;
s32 used;
};
//! Typedef for character strings
typedef string<irr::c8> stringc;
//! Typedef for wide character strings
typedef string<wchar_t> stringw;
} // end namespace core
} // end namespace irr
#endif

View File

@ -1,108 +0,0 @@
// Copyright (C) 2002-2005 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __IRR_TYPES_H_INCLUDED__
#define __IRR_TYPES_H_INCLUDED__
namespace irr
{
//! 8 bit unsigned variable.
/** This is a typedef for unsigned char, it ensures portability of the engine. */
typedef unsigned char u8;
//! 8 bit signed variable.
/** This is a typedef for signed char, it ensures portability of the engine. */
typedef signed char s8;
//! 8 bit character variable.
/** This is a typedef for char, it ensures portability of the engine. */
typedef char c8;
//! 16 bit unsigned variable.
/** This is a typedef for unsigned short, it ensures portability of the engine. */
typedef unsigned short u16;
//! 16 bit signed variable.
/** This is a typedef for signed short, it ensures portability of the engine. */
typedef signed short s16;
//! 32 bit unsigned variable.
/** This is a typedef for unsigned int, it ensures portability of the engine. */
typedef unsigned int u32;
//! 32 bit signed variable.
/** This is a typedef for signed int, it ensures portability of the engine. */
typedef signed int s32;
// 64 bit signed variable.
// This is a typedef for __int64, it ensures portability of the engine.
// This type is currently not used by the engine and not supported by compilers
// other than Microsoft Compilers, so it is outcommented.
//typedef __int64 s64;
//! 32 bit floating point variable.
/** This is a typedef for float, it ensures portability of the engine. */
typedef float f32;
//! 64 bit floating point variable.
/** This is a typedef for double, it ensures portability of the engine. */
typedef double f64;
} // end namespace
// define the wchar_t type if not already built in.
#ifdef _MSC_VER
#ifndef _WCHAR_T_DEFINED
//! A 16 bit wide character type.
/**
Defines the wchar_t-type.
In VS6, its not possible to tell
the standard compiler to treat wchar_t as a built-in type, and
sometimes we just don't want to include the huge stdlib.h or wchar.h,
so we'll use this.
*/
typedef unsigned short wchar_t;
#define _WCHAR_T_DEFINED
#endif // wchar is not defined
#endif // microsoft compiler
//! define a break macro for debugging only in Win32 mode.
// WORKAROUND (assimp): remove __asm
#if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG)
#if defined(_M_IX86)
#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) /*if (_CONDITION_) {_asm int 3}*/
#else
#define _IRR_DEBUG_BREAK_IF( _CONDITION_ )
#endif
#else
#define _IRR_DEBUG_BREAK_IF( _CONDITION_ )
#endif
//! Defines a small statement to work around a microsoft compiler bug.
/** The microsft compiler 7.0 - 7.1 has a bug:
When you call unmanaged code that returns a bool type value of false from managed code,
the return value may appear as true. See
http://support.microsoft.com/default.aspx?kbid=823071 for details.
Compiler version defines: VC6.0 : 1200, VC7.0 : 1300, VC7.1 : 1310, VC8.0 : 1400*/
// WORKAROUND (assimp): remove __asm
#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER > 1299) && (_MSC_VER < 1400)
#define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX /*__asm mov eax,100*/
#else
#define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX
#endif // _IRR_MANAGED_MARSHALLING_BUGFIX
#endif // __IRR_TYPES_H_INCLUDED__

View File

@ -1,151 +0,0 @@
// Copyright (C) 2002-2005 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine" and the "irrXML" project.
// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h
// Need to include Assimp, too. We're using Assimp's version of fast_atof
// so we need stdint.h. But no PCH.
#include "irrXML.h"
#include "irrString.h"
#include "irrArray.h"
//#include <assimp/fast_atof.h>
#include "CXMLReaderImpl.h"
namespace irr
{
namespace io
{
//! Implementation of the file read callback for ordinary files
class IRRXML_API CFileReadCallBack : public IFileReadCallBack
{
public:
//! construct from filename
CFileReadCallBack(const char* filename)
: File(0), Size(0), Close(true)
{
// open file
File = fopen(filename, "rb");
if (File)
getFileSize();
}
//! construct from FILE pointer
CFileReadCallBack(FILE* file)
: File(file), Size(0), Close(false)
{
if (File)
getFileSize();
}
//! destructor
virtual ~CFileReadCallBack()
{
if (Close && File)
fclose(File);
}
//! Reads an amount of bytes from the file.
virtual int read(void* buffer, int sizeToRead)
{
if (!File)
return 0;
return (int)fread(buffer, 1, sizeToRead, File);
}
//! Returns size of file in bytes
virtual int getSize()
{
return Size;
}
private:
//! retrieves the file size of the open file
void getFileSize()
{
fseek(File, 0, SEEK_END);
Size = ftell(File);
fseek(File, 0, SEEK_SET);
}
FILE* File;
int Size;
bool Close;
}; // end class CFileReadCallBack
// FACTORY FUNCTIONS:
//! Creates an instance of an UFT-8 or ASCII character xml parser.
IrrXMLReader* createIrrXMLReader(const char* filename)
{
return new CXMLReaderImpl<char, IXMLBase>(new CFileReadCallBack(filename));
}
//! Creates an instance of an UFT-8 or ASCII character xml parser.
IrrXMLReader* createIrrXMLReader(FILE* file)
{
return new CXMLReaderImpl<char, IXMLBase>(new CFileReadCallBack(file));
}
//! Creates an instance of an UFT-8 or ASCII character xml parser.
IrrXMLReader* createIrrXMLReader(IFileReadCallBack* callback)
{
return new CXMLReaderImpl<char, IXMLBase>(callback, false);
}
//! Creates an instance of an UTF-16 xml parser.
IrrXMLReaderUTF16* createIrrXMLReaderUTF16(const char* filename)
{
return new CXMLReaderImpl<char16, IXMLBase>(new CFileReadCallBack(filename));
}
//! Creates an instance of an UTF-16 xml parser.
IrrXMLReaderUTF16* createIrrXMLReaderUTF16(FILE* file)
{
return new CXMLReaderImpl<char16, IXMLBase>(new CFileReadCallBack(file));
}
//! Creates an instance of an UTF-16 xml parser.
IrrXMLReaderUTF16* createIrrXMLReaderUTF16(IFileReadCallBack* callback)
{
return new CXMLReaderImpl<char16, IXMLBase>(callback, false);
}
//! Creates an instance of an UTF-32 xml parser.
IrrXMLReaderUTF32* createIrrXMLReaderUTF32(const char* filename)
{
return new CXMLReaderImpl<char32, IXMLBase>(new CFileReadCallBack(filename));
}
//! Creates an instance of an UTF-32 xml parser.
IrrXMLReaderUTF32* createIrrXMLReaderUTF32(FILE* file)
{
return new CXMLReaderImpl<char32, IXMLBase>(new CFileReadCallBack(file));
}
//! Creates an instance of an UTF-32 xml parser.
IrrXMLReaderUTF32* createIrrXMLReaderUTF32(IFileReadCallBack* callback)
{
return new CXMLReaderImpl<char32, IXMLBase>(callback, false);
}
} // end namespace io
} // end namespace irr

View File

@ -1,546 +0,0 @@
// Copyright (C) 2002-2005 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine" and the "irrXML" project.
// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h
#ifndef __IRR_XML_H_INCLUDED__
#define __IRR_XML_H_INCLUDED__
#include <stdio.h>
#ifdef _WIN32
# define IRRXML_API __declspec(dllexport)
#else
# define IRRXML_API __attribute__ ((visibility("default")))
#endif // _WIN32
/** \mainpage irrXML 1.2 API documentation
<div align="center"><img src="logobig.png" ></div>
\section intro Introduction
Welcome to the irrXML API documentation.
Here you'll find any information you'll need to develop applications with
irrXML. If you look for a tutorial on how to start, take a look at the \ref irrxmlexample,
at the homepage of irrXML at <A HREF="http://xml.irrlicht3d.org" >xml.irrlicht3d.org</A>
or into the SDK in the directory \example.
irrXML is intended to be a high speed and easy-to-use XML Parser for C++, and
this documentation is an important part of it. If you have any questions or
suggestions, just send a email to the author of the engine, Nikolaus Gebhardt
(niko (at) irrlicht3d.org). For more informations about this parser, see \ref history.
\section features Features
irrXML provides forward-only, read-only
access to a stream of non validated XML data. It was fully implemented by
Nikolaus Gebhardt. Its current features are:
- It it fast as lighting and has very low memory usage. It was
developed with the intention of being used in 3D games, as it already has been.
- irrXML is very small: It only consists of 60 KB of code and can be added easily
to your existing project.
- Of course, it is platform independent and works with lots of compilers.
- It is able to parse ASCII, UTF-8, UTF-16 and UTF-32 text files, both in
little and big endian format.
- Independent of the input file format, the parser can return all strings in ASCII, UTF-8,
UTF-16 and UTF-32 format.
- With its optional file access abstraction it has the advantage that it can read not
only from files but from any type of data (memory, network, ...). For example when
used with the Irrlicht Engine, it directly reads from compressed .zip files.
- Just like the Irrlicht Engine for which it was originally created, it is extremely easy
to use.
- It has no external dependencies, it does not even need the STL.
Although irrXML has some strenghts, it currently also has the following limitations:
- The input xml file is not validated and assumed to be correct.
\section irrxmlexample Example
The following code demonstrates the basic usage of irrXML. A simple xml
file like this is parsed:
\code
<?xml version="1.0"?>
<config>
<!-- This is a config file for the mesh viewer -->
<model file="dwarf.dea" />
<messageText caption="Irrlicht Engine Mesh Viewer">
Welcome to the Mesh Viewer of the &quot;Irrlicht Engine&quot;.
</messageText>
</config>
\endcode
The code for parsing this file would look like this:
\code
#include <irrXML.h>
using namespace irr; // irrXML is located in the namespace irr::io
using namespace io;
#include <string> // we use STL strings to store data in this example
void main()
{
// create the reader using one of the factory functions
IrrXMLReader* xml = createIrrXMLReader("config.xml");
// strings for storing the data we want to get out of the file
std::string modelFile;
std::string messageText;
std::string caption;
// parse the file until end reached
while(xml && xml->read())
{
switch(xml->getNodeType())
{
case EXN_TEXT:
// in this xml file, the only text which occurs is the messageText
messageText = xml->getNodeData();
break;
case EXN_ELEMENT:
{
if (!strcmp("model", xml->getNodeName()))
modelFile = xml->getAttributeValue("file");
else
if (!strcmp("messageText", xml->getNodeName()))
caption = xml->getAttributeValue("caption");
}
break;
}
}
// delete the xml parser after usage
delete xml;
}
\endcode
\section howto How to use
Simply add the source files in the /src directory of irrXML to your project. Done.
\section license License
The irrXML license is based on the zlib license. Basicly, this means you can do with
irrXML whatever you want:
Copyright (C) 2002-2005 Nikolaus Gebhardt
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
\section history History
As lots of references in this documentation and the source show, this xml
parser has originally been a part of the
<A HREF="http://irrlicht.sourceforge.net" >Irrlicht Engine</A>. But because
the parser has become very useful with the latest release, people asked for a
separate version of it, to be able to use it in non Irrlicht projects. With
irrXML 1.0, this has now been done.
*/
namespace irr
{
namespace io
{
//! Enumeration of all supported source text file formats
enum ETEXT_FORMAT
{
//! ASCII, file without byte order mark, or not a text file
ETF_ASCII,
//! UTF-8 format
ETF_UTF8,
//! UTF-16 format, big endian
ETF_UTF16_BE,
//! UTF-16 format, little endian
ETF_UTF16_LE,
//! UTF-32 format, big endian
ETF_UTF32_BE,
//! UTF-32 format, little endian
ETF_UTF32_LE
};
//! Enumeration for all xml nodes which are parsed by IrrXMLReader
enum EXML_NODE
{
//! No xml node. This is usually the node if you did not read anything yet.
EXN_NONE,
//! A xml element, like <foo>
EXN_ELEMENT,
//! End of an xml element, like </foo>
EXN_ELEMENT_END,
//! Text within a xml element: <foo> this is the text. </foo>
EXN_TEXT,
//! An xml comment like &lt;!-- I am a comment --&gt; or a DTD definition.
EXN_COMMENT,
//! An xml cdata section like &lt;![CDATA[ this is some CDATA ]]&gt;
EXN_CDATA,
//! Unknown element.
EXN_UNKNOWN
};
//! Callback class for file read abstraction.
/** With this, it is possible to make the xml parser read in other things
than just files. The Irrlicht engine is using this for example to
read xml from compressed .zip files. To make the parser read in
any other data, derive a class from this interface, implement the
two methods to read your data and give a pointer to an instance of
your implementation when calling createIrrXMLReader(),
createIrrXMLReaderUTF16() or createIrrXMLReaderUTF32() */
class IRRXML_API IFileReadCallBack
{
public:
//! virtual destructor
virtual ~IFileReadCallBack() {};
//! Reads an amount of bytes from the file.
/** \param buffer: Pointer to buffer where to read bytes will be written to.
\param sizeToRead: Amount of bytes to read from the file.
\return Returns how much bytes were read. */
virtual int read(void* buffer, int sizeToRead) = 0;
//! Returns size of file in bytes
virtual int getSize() = 0;
};
//! Empty class to be used as parent class for IrrXMLReader.
/** If you need another class as base class for the xml reader, you can do this by creating
the reader using for example new CXMLReaderImpl<char, YourBaseClass>(yourcallback);
The Irrlicht Engine for example needs IUnknown as base class for every object to
let it automaticly reference countend, hence it replaces IXMLBase with IUnknown.
See irrXML.cpp on how this can be done in detail. */
class IXMLBase
{
};
//! Interface providing easy read access to a XML file.
/** You can create an instance of this reader using one of the factory functions
createIrrXMLReader(), createIrrXMLReaderUTF16() and createIrrXMLReaderUTF32().
If using the parser from the Irrlicht Engine, please use IFileSystem::createXMLReader()
instead.
For a detailed intro how to use the parser, see \ref irrxmlexample and \ref features.
The typical usage of this parser looks like this:
\code
#include <irrXML.h>
using namespace irr; // irrXML is located in the namespace irr::io
using namespace io;
void main()
{
// create the reader using one of the factory functions
IrrXMLReader* xml = createIrrXMLReader("config.xml");
if (xml == 0)
return; // file could not be opened
// parse the file until end reached
while(xml->read())
{
// based on xml->getNodeType(), do something.
}
// delete the xml parser after usage
delete xml;
}
\endcode
See \ref irrxmlexample for a more detailed example.
*/
template<class char_type, class super_class>
class IIrrXMLReader : public super_class
{
public:
//! Destructor
virtual ~IIrrXMLReader() {};
//! Reads forward to the next xml node.
/** \return Returns false, if there was no further node. */
virtual bool read() = 0;
//! Returns the type of the current XML node.
virtual EXML_NODE getNodeType() const = 0;
//! Returns attribute count of the current XML node.
/** This is usually
non null if the current node is EXN_ELEMENT, and the element has attributes.
\return Returns amount of attributes of this xml node. */
virtual int getAttributeCount() const = 0;
//! Returns name of an attribute.
/** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1.
\return Name of the attribute, 0 if an attribute with this index does not exist. */
virtual const char_type* getAttributeName(int idx) const = 0;
//! Returns the value of an attribute.
/** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1.
\return Value of the attribute, 0 if an attribute with this index does not exist. */
virtual const char_type* getAttributeValue(int idx) const = 0;
//! Returns the value of an attribute.
/** \param name: Name of the attribute.
\return Value of the attribute, 0 if an attribute with this name does not exist. */
virtual const char_type* getAttributeValue(const char_type* name) const = 0;
//! Returns the value of an attribute in a safe way.
/** Like getAttributeValue(), but does not
return 0 if the attribute does not exist. An empty string ("") is returned then.
\param name: Name of the attribute.
\return Value of the attribute, and "" if an attribute with this name does not exist */
virtual const char_type* getAttributeValueSafe(const char_type* name) const = 0;
//! Returns the value of an attribute as integer.
/** \param name Name of the attribute.
\return Value of the attribute as integer, and 0 if an attribute with this name does not exist or
the value could not be interpreted as integer. */
virtual int getAttributeValueAsInt(const char_type* name) const = 0;
//! Returns the value of an attribute as integer.
/** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1.
\return Value of the attribute as integer, and 0 if an attribute with this index does not exist or
the value could not be interpreted as integer. */
virtual int getAttributeValueAsInt(int idx) const = 0;
//! Returns the value of an attribute as float.
/** \param name: Name of the attribute.
\return Value of the attribute as float, and 0 if an attribute with this name does not exist or
the value could not be interpreted as float. */
virtual float getAttributeValueAsFloat(const char_type* name) const = 0;
//! Returns the value of an attribute as float.
/** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1.
\return Value of the attribute as float, and 0 if an attribute with this index does not exist or
the value could not be interpreted as float. */
virtual float getAttributeValueAsFloat(int idx) const = 0;
//! Returns the name of the current node.
/** Only non null, if the node type is EXN_ELEMENT.
\return Name of the current node or 0 if the node has no name. */
virtual const char_type* getNodeName() const = 0;
//! Returns data of the current node.
/** Only non null if the node has some
data and it is of type EXN_TEXT or EXN_UNKNOWN. */
virtual const char_type* getNodeData() const = 0;
//! Returns if an element is an empty element, like <foo />
virtual bool isEmptyElement() const = 0;
//! Returns format of the source xml file.
/** It is not necessary to use
this method because the parser will convert the input file format
to the format wanted by the user when creating the parser. This
method is useful to get/display additional informations. */
virtual ETEXT_FORMAT getSourceFormat() const = 0;
//! Returns format of the strings returned by the parser.
/** This will be UTF8 for example when you created a parser with
IrrXMLReaderUTF8() and UTF32 when it has been created using
IrrXMLReaderUTF32. It should not be necessary to call this
method and only exists for informational purposes. */
virtual ETEXT_FORMAT getParserFormat() const = 0;
};
//! defines the utf-16 type.
/** Not using wchar_t for this because
wchar_t has 16 bit on windows and 32 bit on other operating systems. */
typedef unsigned short char16;
//! defines the utf-32 type.
/** Not using wchar_t for this because
wchar_t has 16 bit on windows and 32 bit on other operating systems. */
typedef unsigned long char32;
//! A UTF-8 or ASCII character xml parser.
/** This means that all character data will be returned in 8 bit ASCII or UTF-8 by this parser.
The file to read can be in any format, it will be converted to UTF-8 if it is not
in this format.
Create an instance of this with createIrrXMLReader();
See IIrrXMLReader for description on how to use it. */
typedef IIrrXMLReader<char, IXMLBase> IrrXMLReader;
//! A UTF-16 xml parser.
/** This means that all character data will be returned in UTF-16 by this parser.
The file to read can be in any format, it will be converted to UTF-16 if it is not
in this format.
Create an instance of this with createIrrXMLReaderUTF16();
See IIrrXMLReader for description on how to use it. */
typedef IIrrXMLReader<char16, IXMLBase> IrrXMLReaderUTF16;
//! A UTF-32 xml parser.
/** This means that all character data will be returned in UTF-32 by this parser.
The file to read can be in any format, it will be converted to UTF-32 if it is not
in this format.
Create an instance of this with createIrrXMLReaderUTF32();
See IIrrXMLReader for description on how to use it. */
typedef IIrrXMLReader<char32, IXMLBase> IrrXMLReaderUTF32;
//! Creates an instance of an UFT-8 or ASCII character xml parser.
/** This means that all character data will be returned in 8 bit ASCII or UTF-8.
The file to read can be in any format, it will be converted to UTF-8 if it is not in this format.
If you are using the Irrlicht Engine, it is better not to use this function but
IFileSystem::createXMLReaderUTF8() instead.
\param filename: Name of file to be opened.
\return Returns a pointer to the created xml parser. This pointer should be
deleted using 'delete' after no longer needed. Returns 0 if an error occured
and the file could not be opened. */
IRRXML_API IrrXMLReader* createIrrXMLReader(const char* filename);
//! Creates an instance of an UFT-8 or ASCII character xml parser.
/** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can
be in any format, it will be converted to UTF-8 if it is not in this format.
If you are using the Irrlicht Engine, it is better not to use this function but
IFileSystem::createXMLReaderUTF8() instead.
\param file: Pointer to opened file, must have been opened in binary mode, e.g.
using fopen("foo.bar", "wb"); The file will not be closed after it has been read.
\return Returns a pointer to the created xml parser. This pointer should be
deleted using 'delete' after no longer needed. Returns 0 if an error occured
and the file could not be opened. */
IRRXML_API IrrXMLReader* createIrrXMLReader(FILE* file);
//! Creates an instance of an UFT-8 or ASCII character xml parser.
/** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can
be in any format, it will be converted to UTF-8 if it is not in this format.
If you are using the Irrlicht Engine, it is better not to use this function but
IFileSystem::createXMLReaderUTF8() instead.
\param callback: Callback for file read abstraction. Implement your own
callback to make the xml parser read in other things than just files. See
IFileReadCallBack for more information about this.
\return Returns a pointer to the created xml parser. This pointer should be
deleted using 'delete' after no longer needed. Returns 0 if an error occured
and the file could not be opened. */
IRRXML_API IrrXMLReader* createIrrXMLReader(IFileReadCallBack* callback);
//! Creates an instance of an UFT-16 xml parser.
/** This means that
all character data will be returned in UTF-16. The file to read can
be in any format, it will be converted to UTF-16 if it is not in this format.
If you are using the Irrlicht Engine, it is better not to use this function but
IFileSystem::createXMLReader() instead.
\param filename: Name of file to be opened.
\return Returns a pointer to the created xml parser. This pointer should be
deleted using 'delete' after no longer needed. Returns 0 if an error occured
and the file could not be opened. */
IRRXML_API IrrXMLReaderUTF16* createIrrXMLReaderUTF16(const char* filename);
//! Creates an instance of an UFT-16 xml parser.
/** This means that all character data will be returned in UTF-16. The file to read can
be in any format, it will be converted to UTF-16 if it is not in this format.
If you are using the Irrlicht Engine, it is better not to use this function but
IFileSystem::createXMLReader() instead.
\param file: Pointer to opened file, must have been opened in binary mode, e.g.
using fopen("foo.bar", "wb"); The file will not be closed after it has been read.
\return Returns a pointer to the created xml parser. This pointer should be
deleted using 'delete' after no longer needed. Returns 0 if an error occured
and the file could not be opened. */
IRRXML_API IrrXMLReaderUTF16* createIrrXMLReaderUTF16(FILE* file);
//! Creates an instance of an UFT-16 xml parser.
/** This means that all character data will be returned in UTF-16. The file to read can
be in any format, it will be converted to UTF-16 if it is not in this format.
If you are using the Irrlicht Engine, it is better not to use this function but
IFileSystem::createXMLReader() instead.
\param callback: Callback for file read abstraction. Implement your own
callback to make the xml parser read in other things than just files. See
IFileReadCallBack for more information about this.
\return Returns a pointer to the created xml parser. This pointer should be
deleted using 'delete' after no longer needed. Returns 0 if an error occured
and the file could not be opened. */
IRRXML_API IrrXMLReaderUTF16* createIrrXMLReaderUTF16(IFileReadCallBack* callback);
//! Creates an instance of an UFT-32 xml parser.
/** This means that all character data will be returned in UTF-32. The file to read can
be in any format, it will be converted to UTF-32 if it is not in this format.
If you are using the Irrlicht Engine, it is better not to use this function but
IFileSystem::createXMLReader() instead.
\param filename: Name of file to be opened.
\return Returns a pointer to the created xml parser. This pointer should be
deleted using 'delete' after no longer needed. Returns 0 if an error occured
and the file could not be opened. */
IRRXML_API IrrXMLReaderUTF32* createIrrXMLReaderUTF32(const char* filename);
//! Creates an instance of an UFT-32 xml parser.
/** This means that all character data will be returned in UTF-32. The file to read can
be in any format, it will be converted to UTF-32 if it is not in this format.
if you are using the Irrlicht Engine, it is better not to use this function but
IFileSystem::createXMLReader() instead.
\param file: Pointer to opened file, must have been opened in binary mode, e.g.
using fopen("foo.bar", "wb"); The file will not be closed after it has been read.
\return Returns a pointer to the created xml parser. This pointer should be
deleted using 'delete' after no longer needed. Returns 0 if an error occured
and the file could not be opened. */
IRRXML_API IrrXMLReaderUTF32* createIrrXMLReaderUTF32(FILE* file);
//! Creates an instance of an UFT-32 xml parser.
/** This means that
all character data will be returned in UTF-32. The file to read can
be in any format, it will be converted to UTF-32 if it is not in this format.
If you are using the Irrlicht Engine, it is better not to use this function but
IFileSystem::createXMLReader() instead.
\param callback: Callback for file read abstraction. Implement your own
callback to make the xml parser read in other things than just files. See
IFileReadCallBack for more information about this.
\return Returns a pointer to the created xml parser. This pointer should be
deleted using 'delete' after no longer needed. Returns 0 if an error occured
and the file could not be opened. */
IRRXML_API IrrXMLReaderUTF32* createIrrXMLReaderUTF32(IFileReadCallBack* callback);
/*! \file irrxml.h
\brief Header file of the irrXML, the Irrlicht XML parser.
This file includes everything needed for using irrXML,
the XML parser of the Irrlicht Engine. To use irrXML,
you only need to include this file in your project:
\code
#include <irrXML.h>
\endcode
It is also common to use the two namespaces in which irrXML is included,
directly after #including irrXML.h:
\code
#include <irrXML.h>
using namespace irr;
using namespace io;
\endcode
*/
} // end namespace io
} // end namespace irr
#endif // __IRR_XML_H_INCLUDED__

View File

@ -44,13 +44,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define INCLUDED_AI_IRRXML_WRAPPER #define INCLUDED_AI_IRRXML_WRAPPER
// some long includes .... // some long includes ....
#ifdef ASSIMP_USE_HUNTER
# include <irrXML/irrXML.h>
#else
# include <irrXML.h>
#endif
#include "IOStream.hpp"
#include "BaseImporter.h" #include "BaseImporter.h"
#include "IOStream.hpp"
#include <pugixml.hpp>
#include <vector> #include <vector>
namespace Assimp { namespace Assimp {
@ -75,7 +71,7 @@ namespace Assimp {
* } * }
* @endcode * @endcode
**/ **/
class CIrrXML_IOStreamReader : public irr::io::IFileReadCallBack { /*class CIrrXML_IOStreamReader : public irr::io::IFileReadCallBack {
public: public:
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
@ -110,14 +106,14 @@ public:
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
//! Virtual destructor //! Virtual destructor
virtual ~CIrrXML_IOStreamReader() {} virtual ~CIrrXML_IOStreamReader() {}*/
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
//! Reads an amount of bytes from the file. //! Reads an amount of bytes from the file.
/** @param buffer: Pointer to output buffer. /** @param buffer: Pointer to output buffer.
* @param sizeToRead: Amount of bytes to read * @param sizeToRead: Amount of bytes to read
* @return Returns how much bytes were read. */ * @return Returns how much bytes were read. */
virtual int read(void* buffer, int sizeToRead) { /*virtual int read(void* buffer, int sizeToRead) {
if(sizeToRead<0) { if(sizeToRead<0) {
return 0; return 0;
} }
@ -143,7 +139,51 @@ private:
size_t t; size_t t;
}; // ! class CIrrXML_IOStreamReader }; // ! class CIrrXML_IOStreamReader
*/
} // ! Assimp class XmlParser {
public:
XmlParser() :
mDoc(nullptr), mRoot(nullptr), mData() {
// empty
}
~XmlParser() {
clear();
}
void clear() {
mData.resize(0);
delete mDoc;
mDoc = nullptr;
}
pugi::xml_node *parse(IOStream *stream) {
if (nullptr == stream) {
return nullptr;
}
mData.resize(stream->FileSize());
stream->Read(&mData[0], mData.size(), 1);
mDoc = new pugi::xml_document();
pugi::xml_parse_result result = mDoc->load_string(&mData[0]);
if (result.status == pugi::status_ok) {
mRoot = &mDoc->root();
}
return mRoot;
}
pugi::xml_document *getDocument() const {
return mDoc;
}
private:
pugi::xml_document *mDoc;
pugi::xml_node *mRoot;
std::vector<char> mData;
};
} // namespace Assimp
#endif // !! INCLUDED_AI_IRRXML_WRAPPER #endif // !! INCLUDED_AI_IRRXML_WRAPPER