IrrXml: replaced irrXml by pugixml.
parent
d48b93cf34
commit
a905303764
|
@ -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>
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
|
@ -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})
|
|
|
@ -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("&");
|
|
||||||
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
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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__
|
|
||||||
|
|
|
@ -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
|
|
|
@ -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 "Irrlicht Engine".
|
|
||||||
</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 <!-- I am a comment --> or a DTD definition.
|
|
||||||
EXN_COMMENT,
|
|
||||||
|
|
||||||
//! An xml cdata section like <![CDATA[ this is some CDATA ]]>
|
|
||||||
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__
|
|
||||||
|
|
|
@ -44,16 +44,12 @@ 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 {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
/** @brief Utility class to make IrrXML work together with our custom IO system
|
/** @brief Utility class to make IrrXML work together with our custom IO system
|
||||||
|
@ -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
|
Loading…
Reference in New Issue