diff --git a/code/BaseImporter.cpp b/code/BaseImporter.cpp index 4c777cace..910facf28 100644 --- a/code/BaseImporter.cpp +++ b/code/BaseImporter.cpp @@ -97,5 +97,46 @@ void BaseImporter::SetupProperties(const Importer* pImp) // the default implementation does nothing } +// ------------------------------------------------------------------------------------------------ +bool BaseImporter::SearchFileHeaderForToken(IOSystem* pIOHandler, + const std::string& pFile, + const char** tokens, + unsigned int numTokens, + unsigned int searchBytes /* = 200 */) +{ + ai_assert(NULL != tokens && 0 != numTokens && NULL != pIOHandler && 0 != searchBytes); + + boost::scoped_ptr pStream (pIOHandler->Open(pFile)); + if (pStream.get() ) + { + // read 200 characters from the file + boost::scoped_ptr _buffer (new char[searchBytes]); + char* buffer = _buffer.get(); + + unsigned int read = (unsigned int)pStream->Read(buffer,1,searchBytes); + if (!read)return false; + + for (unsigned int i = 0; i < read;++i) + buffer[i] = ::tolower(buffer[i]); + + // It is not a proper handling of unicode files here ... + // ehm ... but it works in most cases. + char* cur = buffer,*cur2 = buffer,*end = &buffer[read]; + while (cur != end) + { + if (*cur)*cur2++ = *cur; + ++cur; + } + *cur2 = '\0'; + + for (unsigned int i = 0; i < numTokens;++i) + { + ai_assert(NULL != tokens[i]); + if (::strstr(buffer,tokens[i]))return true; + } + } + return false; +} + diff --git a/code/BaseImporter.h b/code/BaseImporter.h index 822e1cc6d..ad2bc2407 100644 --- a/code/BaseImporter.h +++ b/code/BaseImporter.h @@ -194,6 +194,27 @@ protected: virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) = 0; + + // ------------------------------------------------------------------- + /** A utility for CanRead(). + * + * The function searches the header of a file for a specific token + * and returns true if this token is found. This works for text + * files only. There is a rudimentary handling if UNICODE files. + * The comparison is case independent. + * + * @param pIOSystem IO System to work with + * @param file File name of the file + * @param tokens List of tokens to search for + * @param numTokens Size of the token array + * @param searchBytes Number of bytes to be searched for the tokens. + */ + static bool SearchFileHeaderForToken(IOSystem* pIOSystem, + const std::string& file, + const char** tokens, + unsigned int numTokens, + unsigned int searchBytes = 200); + protected: /** Error description in case there was one. */ diff --git a/code/DXFLoader.cpp b/code/DXFLoader.cpp index be7c5ae51..2818e1305 100644 --- a/code/DXFLoader.cpp +++ b/code/DXFLoader.cpp @@ -47,7 +47,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "DXFLoader.h" #include "ParsingUtils.h" #include "fast_atof.h" -#include "MaterialSystem.h" using namespace Assimp; @@ -246,7 +245,7 @@ void DXFImporter::InternReadFile( const std::string& pFile, { aiFace& face = pMesh->mFaces[i]; - // check whether we need four,three or two indices here + // check whether we need four, three or two indices here if (vp[1] == vp[2]) { face.mNumIndices = 2; @@ -263,7 +262,7 @@ void DXFImporter::InternReadFile( const std::string& pFile, *vpOut++ = vp[a]; if (clr) { - if (std::numeric_limits::quiet_NaN() != clr[a].r) + if (is_not_qnan( clr[a].r )) *clrOut = clr[a]; ++clrOut; @@ -437,7 +436,7 @@ bool DXFImporter::ParsePolyLine() // optional number of faces case 72: { - indices.reserve(strtol10(cursor) * 4u); + indices.reserve(strtol10(cursor)); break; } diff --git a/code/IRRMeshLoader.cpp b/code/IRRMeshLoader.cpp new file mode 100644 index 000000000..a4a00689c --- /dev/null +++ b/code/IRRMeshLoader.cpp @@ -0,0 +1,743 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file Implementation of the IrrMesh importer class */ + +#include "AssimpPCH.h" + + +#include "IRRMeshLoader.h" +#include "ParsingUtils.h" +#include "fast_atof.h" + +using namespace Assimp; + + +// ------------------------------------------------------------------------------------------------ +// Constructor to be privately used by Importer +IRRMeshImporter::IRRMeshImporter() +{ + // nothing to do here +} + +// ------------------------------------------------------------------------------------------------ +// Destructor, private as well +IRRMeshImporter::~IRRMeshImporter() +{ + // nothing to do here +} + +// ------------------------------------------------------------------------------------------------ +// Returns whether the class can handle the format of the given file. +bool IRRMeshImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const +{ + /* NOTE: A simple check for the file extension is not enough + * here. Irrmesh and irr are easy, but xml is too generic + * and could be collada, too. So we need to open the file and + * search for typical tokens. + */ + + std::string::size_type pos = pFile.find_last_of('.'); + + // no file extension - can't read + if( pos == std::string::npos) + return false; + + std::string extension = pFile.substr( pos); + for (std::string::iterator i = extension.begin(); i != extension.end();++i) + *i = ::tolower(*i); + + if (extension == ".irrmesh")return true; + else if (extension == ".xml") + { + /* If CanRead() is called to check whether the loader + * supports a specific file extension in general we + * must return true here. + */ + if (!pIOHandler)return true; + const char* tokens[] = {"irrlicht","irrmesh"}; + return SearchFileHeaderForToken(pIOHandler,pFile,tokens,2); + } + return false; +} + +// ------------------------------------------------------------------------------------------------ +// read a property in hexadecimal format (i.e. ffffffff) +void IRRMeshImporter::ReadHexProperty (HexProperty& out) +{ + for (int i = 0; i < reader->getAttributeCount();++i) + { + if (!ASSIMP_stricmp(reader->getAttributeName(i),"name")) + { + out.name = std::string( reader->getAttributeValue(i) ); + } + else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value")) + { + // parse the hexadecimal value + out.value = strtol16(reader->getAttributeValue(i)); + } + } +} + +// ------------------------------------------------------------------------------------------------ +// read a string property +void IRRMeshImporter::ReadStringProperty (StringProperty& out) +{ + for (int i = 0; i < reader->getAttributeCount();++i) + { + if (!ASSIMP_stricmp(reader->getAttributeName(i),"name")) + { + out.name = std::string( reader->getAttributeValue(i) ); + } + else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value")) + { + // simple copy the string + out.value = std::string (reader->getAttributeValue(i)); + } + } +} + +// ------------------------------------------------------------------------------------------------ +// read a boolean property +void IRRMeshImporter::ReadBoolProperty (BoolProperty& out) +{ + for (int i = 0; i < reader->getAttributeCount();++i) + { + if (!ASSIMP_stricmp(reader->getAttributeName(i),"name")) + { + out.name = std::string( reader->getAttributeValue(i) ); + } + else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value")) + { + // true or false, case insensitive + out.value = (ASSIMP_stricmp( reader->getAttributeValue(i), + "true") ? false : true); + } + } +} + +// ------------------------------------------------------------------------------------------------ +// read a float property +void IRRMeshImporter::ReadFloatProperty (FloatProperty& out) +{ + for (int i = 0; i < reader->getAttributeCount();++i) + { + if (!ASSIMP_stricmp(reader->getAttributeName(i),"name")) + { + out.name = std::string( reader->getAttributeValue(i) ); + } + else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value")) + { + // true or false, case insensitive + out.value = fast_atof( reader->getAttributeValue(i) ); + } + } +} + +// ------------------------------------------------------------------------------------------------ +void ColorFromARGBPacked(uint32_t in, aiColor4D& clr) +{ + clr.a = ((in >> 24) & 0xff) / 255.f; + clr.r = ((in >> 16) & 0xff) / 255.f; + clr.g = ((in >> 8) & 0xff) / 255.f; + clr.b = ((in ) & 0xff) / 255.f; +} + +// ------------------------------------------------------------------------------------------------ +int ConvertMappingMode(const std::string& mode) +{ + if (mode == "texture_clamp_repeat") + return aiTextureMapMode_Wrap; + else if (mode == "texture_clamp_mirror") + return aiTextureMapMode_Mirror; + + return aiTextureMapMode_Clamp; +} + +// ------------------------------------------------------------------------------------------------ +// Parse a material from the XML file +aiMaterial* IRRMeshImporter::ParseMaterial(unsigned int& matFlags) +{ + MaterialHelper* mat = new MaterialHelper(); + aiColor4D clr; + aiString s; + + matFlags = 0; + + // Continue reading from the file + while (reader->read()) + { + switch (reader->getNodeType()) + { + case EXN_ELEMENT: + + // Hex properties + if (!ASSIMP_stricmp(reader->getNodeName(),"color")) + { + HexProperty prop; + ReadHexProperty(prop); + if (prop.name == "Diffuse") + { + ColorFromARGBPacked(prop.value,clr); + mat->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE); + } + else if (prop.name == "Ambient") + { + ColorFromARGBPacked(prop.value,clr); + mat->AddProperty(&clr,1,AI_MATKEY_COLOR_AMBIENT); + } + else if (prop.name == "Specular") + { + ColorFromARGBPacked(prop.value,clr); + mat->AddProperty(&clr,1,AI_MATKEY_COLOR_SPECULAR); + } + else if (prop.name == "Emissive") + { + ColorFromARGBPacked(prop.value,clr); + mat->AddProperty(&clr,1,AI_MATKEY_COLOR_EMISSIVE); + } + } + // Float properties + else if (!ASSIMP_stricmp(reader->getNodeName(),"float")) + { + FloatProperty prop; + ReadFloatProperty(prop); + if (prop.name == "Shininess") + { + mat->AddProperty(&prop.value,1,AI_MATKEY_SHININESS); + } + } + // Bool properties + else if (!ASSIMP_stricmp(reader->getNodeName(),"bool")) + { + BoolProperty prop; + ReadBoolProperty(prop); + if (prop.name == "Wireframe") + { + int val = (prop.value ? true : false); + mat->AddProperty(&val,1,AI_MATKEY_ENABLE_WIREFRAME); + } + else if (prop.name == "GouraudShading") + { + int val = (prop.value ? aiShadingMode_Gouraud + : aiShadingMode_NoShading); + mat->AddProperty(&val,1,AI_MATKEY_SHADING_MODEL); + } + } + // String properties - textures and texture related properties + else if (!ASSIMP_stricmp(reader->getNodeName(),"texture") || + !ASSIMP_stricmp(reader->getNodeName(),"enum")) + { + StringProperty prop; + ReadStringProperty(prop); + int cnt = 0; + + if (prop.value.length()) + { + // material type (shader) + if (prop.name == "Type") + { + if (prop.value == "trans_vertex_alpha") + { + matFlags = AI_IRRMESH_MAT_trans_vertex_alpha; + } + else if (prop.value == "lightmap") + { + matFlags = AI_IRRMESH_MAT_lightmap; + } + else if (prop.value == "lightmap_m2") + { + matFlags = AI_IRRMESH_MAT_lightmap_m2; + } + else if (prop.value == "lightmap_m4") + { + matFlags = AI_IRRMESH_MAT_lightmap_m4; + } + } + + // Up to 4 texture channels are supported + else if (prop.name == "Texture1") + { + ++cnt; + s.Set(prop.value); + mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0)); + } + else if (prop.name == "Texture2") + { + ++cnt; + s.Set(prop.value); + mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(1)); + } + else if (prop.name == "Texture3") + { + ++cnt; + s.Set(prop.value); + mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(2)); + } + else if (prop.name == "Texture4" ) + { + ++cnt; + s.Set(prop.value); + mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(3)); + } + + // Texture mapping options + if (prop.name == "TextureWrap1" && cnt >= 1) + { + int map = ConvertMappingMode(prop.value); + mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0)); + mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0)); + } + else if (prop.name == "TextureWrap2" && cnt >= 2) + { + int map = ConvertMappingMode(prop.value); + mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(1)); + mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(1)); + } + else if (prop.name == "TextureWrap3" && cnt >= 3) + { + int map = ConvertMappingMode(prop.value); + mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(2)); + mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(2)); + } + else if (prop.name == "TextureWrap4" && cnt >= 4) + { + int map = ConvertMappingMode(prop.value); + mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(3)); + mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(3)); + } + } + } + break; + case EXN_ELEMENT_END: + + /* Assume there are no further nested nodes in elements + */ + + return mat; + + default: + + // GCC complains here ... + break; + } + } + DefaultLogger::get()->error("IRRMESH: Unexpected end of file. Material is not complete"); + return mat; +} + +// ------------------------------------------------------------------------------------------------ +// Imports the given file into the given scene structure. +void IRRMeshImporter::InternReadFile( const std::string& pFile, + aiScene* pScene, IOSystem* pIOHandler) +{ + boost::scoped_ptr file( pIOHandler->Open( pFile)); + + // Check whether we can read from the file + if( file.get() == NULL) + throw new ImportErrorException( "Failed to open IRRMESH file " + pFile + ""); + + // Construct the irrXML parser + CIrrXML_IOStreamReader st(file.get()); + reader = createIrrXMLReader((IFileReadCallBack*) &st); + + // final data + std::vector materials; + std::vector meshes; + materials.reserve (5); + meshes.reserve (5); + + // temporary data - current mesh buffer + aiMaterial* curMat = NULL; + aiMesh* curMesh = NULL; + unsigned int curMatFlags; + + std::vector curVertices,curNormals,curTangents,curBitangents; + std::vector curColors; + std::vector curUVs,curUV2s; + + // some temporary variables + int textMeaning = 0; + int vertexFormat = 0; // 0 = normal; 1 = 2 tcoords, 2 = tangents + bool useColors = false; + + // Parse the XML file + while (reader->read()) + { + switch (reader->getNodeType()) + { + case EXN_ELEMENT: + + if (!ASSIMP_stricmp(reader->getNodeName(),"buffer") && (curMat || curMesh)) + { + // end of previous buffer. A material and a mesh should be there + if ( !curMat || !curMesh) + { + DefaultLogger::get()->error("IRRMESH: A buffer must contain a mesh and a material"); + delete curMat; + delete curMesh; + } + else + { + materials.push_back(curMat); + meshes.push_back(curMesh); + } + curMat = NULL; + curMesh = NULL; + + curVertices.clear(); + curColors.clear(); + curNormals.clear(); + curUV2s.clear(); + curUVs.clear(); + } + + + if (!ASSIMP_stricmp(reader->getNodeName(),"material")) + { + if (curMat) + { + DefaultLogger::get()->warn("IRRMESH: Only one material description per buffer, please"); + delete curMat; + } + curMat = ParseMaterial(curMatFlags); + } + /* no else here! */ if (!ASSIMP_stricmp(reader->getNodeName(),"vertices")) + { + int num = reader->getAttributeValueAsInt("vertexCount"); + curVertices.reserve (num); + curNormals.reserve (num); + curColors.reserve (num); + curUVs.reserve (num); + + // Determine the file format + const char* t = reader->getAttributeValueSafe("type"); + if (!ASSIMP_stricmp("2tcoords", t)) + { + curUV2s.reserve (num); + vertexFormat = 1; + } + else if (!ASSIMP_stricmp("tangents", t)) + { + curTangents.reserve (num); + curBitangents.reserve (num); + vertexFormat = 2; + } + else if (ASSIMP_stricmp("standard", t)) + { + DefaultLogger::get()->warn("IRRMESH: Unknown vertex format"); + } + else vertexFormat = 0; + textMeaning = 1; + } + else if (!ASSIMP_stricmp(reader->getNodeName(),"indices")) + { + if (curVertices.empty()) + throw new ImportErrorException("IRRMESH: indices must come after vertices"); + + textMeaning = 2; + + // start a new mesh + curMesh = new aiMesh(); + + // allocate storage for all faces + curMesh->mNumVertices = reader->getAttributeValueAsInt("indexCount"); + if (curMesh->mNumVertices % 3) + { + DefaultLogger::get()->warn("IRRMESH: Number if indices isn't divisible by 3"); + } + + curMesh->mNumFaces = curMesh->mNumVertices / 3; + curMesh->mFaces = new aiFace[curMesh->mNumFaces]; + + // setup some members + curMesh->mMaterialIndex = (unsigned int)materials.size(); + curMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; + + // allocate storage for all vertices + curMesh->mVertices = new aiVector3D[curMesh->mNumVertices]; + + if (curNormals.size() == curVertices.size()) + { + curMesh->mNormals = new aiVector3D[curMesh->mNumVertices]; + } + if (curTangents.size() == curVertices.size()) + { + curMesh->mTangents = new aiVector3D[curMesh->mNumVertices]; + } + if (curBitangents.size() == curVertices.size()) + { + curMesh->mBitangents = new aiVector3D[curMesh->mNumVertices]; + } + if (curColors.size() == curVertices.size() && useColors) + { + curMesh->mColors[0] = new aiColor4D[curMesh->mNumVertices]; + } + if (curUVs.size() == curVertices.size()) + { + curMesh->mTextureCoords[0] = new aiVector3D[curMesh->mNumVertices]; + } + if (curUV2s.size() == curVertices.size()) + { + curMesh->mTextureCoords[1] = new aiVector3D[curMesh->mNumVertices]; + } + } + break; + + case EXN_TEXT: + { + const char* sz = reader->getNodeData(); + if (textMeaning == 1) + { + textMeaning = 0; + + // read vertices + do + { + SkipSpacesAndLineEnd(&sz); + aiVector3D temp;aiColor4D c; + + // Read the vertex position + sz = fast_atof_move(sz,(float&)temp.x); + SkipSpaces(&sz); + + sz = fast_atof_move(sz,(float&)temp.z); + SkipSpaces(&sz); + + sz = fast_atof_move(sz,(float&)temp.y); + SkipSpaces(&sz); + temp.y *= -1.0f; + curVertices.push_back(temp); + + // Read the vertex normals + sz = fast_atof_move(sz,(float&)temp.x); + SkipSpaces(&sz); + + sz = fast_atof_move(sz,(float&)temp.z); + SkipSpaces(&sz); + + sz = fast_atof_move(sz,(float&)temp.y); + SkipSpaces(&sz); + temp.y *= -1.0f; + curNormals.push_back(temp); + + // read the vertex colors + uint32_t clr = strtol16(sz,&sz); + ColorFromARGBPacked(clr,c); + + if (!curColors.empty() && c != *(curColors.end()-1)) + useColors = true; + + curColors.push_back(c); + SkipSpaces(&sz); + + + // read the first UV coordinate set + sz = fast_atof_move(sz,(float&)temp.x); + SkipSpaces(&sz); + + sz = fast_atof_move(sz,(float&)temp.y); + SkipSpaces(&sz); + temp.z = 0.f; + temp.y = 1.f - temp.y; // DX to OGL + curUVs.push_back(temp); + + // read the (optional) second UV coordinate set + if (vertexFormat == 1) + { + sz = fast_atof_move(sz,(float&)temp.x); + SkipSpaces(&sz); + + sz = fast_atof_move(sz,(float&)temp.y); + temp.y = 1.f - temp.y; // DX to OGL + curUV2s.push_back(temp); + } + // read optional tangent and bitangent vectors + if (vertexFormat == 2) + { + // tangents + sz = fast_atof_move(sz,(float&)temp.x); + SkipSpaces(&sz); + + sz = fast_atof_move(sz,(float&)temp.z); + SkipSpaces(&sz); + + sz = fast_atof_move(sz,(float&)temp.y); + SkipSpaces(&sz); + temp.y *= -1.0f; + curTangents.push_back(temp); + + // bitangents + sz = fast_atof_move(sz,(float&)temp.x); + SkipSpaces(&sz); + + sz = fast_atof_move(sz,(float&)temp.z); + SkipSpaces(&sz); + + sz = fast_atof_move(sz,(float&)temp.y); + SkipSpaces(&sz); + temp.y *= -1.0f; + curBitangents.push_back(temp); + } + } + + /* IMPORTANT: We assume that each vertex is specified in one + line. So we can skip the rest of the line - unknown vertex + elements are ignored. + */ + + while (SkipLine(&sz)); + } + else if (textMeaning == 2) + { + textMeaning = 0; + + // read indices + aiFace* curFace = curMesh->mFaces; + aiFace* const faceEnd = curMesh->mFaces + curMesh->mNumFaces; + + aiVector3D* pcV = curMesh->mVertices; + aiVector3D* pcN = curMesh->mNormals; + aiVector3D* pcT = curMesh->mTangents; + aiVector3D* pcB = curMesh->mBitangents; + aiColor4D* pcC0 = curMesh->mColors[0]; + aiVector3D* pcT0 = curMesh->mTextureCoords[0]; + aiVector3D* pcT1 = curMesh->mTextureCoords[1]; + + unsigned int curIdx = 0; + unsigned int total = 0; + while(SkipSpacesAndLineEnd(&sz)) + { + if (curFace >= faceEnd) + { + DefaultLogger::get()->error("IRRMESH: Too many indices"); + break; + } + if (!curIdx) + { + curFace->mNumIndices = 3; + curFace->mIndices = new unsigned int[3]; + } + + unsigned int idx = strtol10(sz,&sz); + if (idx >= curVertices.size()) + { + DefaultLogger::get()->error("IRRMESH: Index out of range"); + idx = 0; + } + + curFace->mIndices[curIdx] = total++; + + *pcV++ = curVertices[idx]; + if (pcN)*pcN++ = curNormals[idx]; + if (pcT)*pcT++ = curTangents[idx]; + if (pcB)*pcB++ = curBitangents[idx]; + if (pcC0)*pcC0++ = curColors[idx]; + if (pcT0)*pcT0++ = curUVs[idx]; + if (pcT1)*pcT1++ = curUV2s[idx]; + + if (++curIdx == 3) + { + ++curFace; + curIdx = 0; + } + } + + if (curFace != faceEnd) + DefaultLogger::get()->error("IRRMESH: Not enough indices"); + + // Finish processing the mesh - do some small material workarounds + if (curMatFlags == AI_IRRMESH_MAT_trans_vertex_alpha && !useColors) + { + // Take the opacity value of the current material + // from the common vertex color alpha + MaterialHelper* mat = (MaterialHelper*)curMat; + mat->AddProperty(&curColors[0].a,1,AI_MATKEY_OPACITY); + } + + /* TODO: Add lightmapping support here */ + }} + break; + + default: + + // GCC complains here ... + break; + + }; + } + + // end of the last buffer. A material and a mesh should be there + if (curMat || curMesh) + { + if ( !curMat || !curMesh) + { + DefaultLogger::get()->error("IRRMESH: A buffer must contain a mesh and a material"); + delete curMat; + delete curMesh; + } + else + { + materials.push_back(curMat); + meshes.push_back(curMesh); + } + } + + // now generate the output scene + pScene->mNumMeshes = (unsigned int)meshes.size(); + pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; + ::memcpy(pScene->mMeshes,&meshes[0],sizeof(void*)*pScene->mNumMeshes); + + pScene->mNumMaterials = (unsigned int)materials.size(); + pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; + ::memcpy(pScene->mMaterials,&materials[0],sizeof(void*)*pScene->mNumMaterials); + + pScene->mRootNode = new aiNode(); + pScene->mRootNode->mName.Set(""); + pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; + pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes]; + + for (unsigned int i = 0; i < pScene->mNumMeshes;++i) + pScene->mRootNode->mMeshes[i] = i; + + delete reader; + AI_DEBUG_INVALIDATE_PTR(reader); +} \ No newline at end of file diff --git a/code/IRRMeshLoader.h b/code/IRRMeshLoader.h new file mode 100644 index 000000000..0d30b10e5 --- /dev/null +++ b/code/IRRMeshLoader.h @@ -0,0 +1,143 @@ +/* +Open Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file Declaration of the .irrMesh (Irrlight Engine Mesh Format) + importer class. */ +#ifndef AI_IRRMESHLOADER_H_INCLUDED +#define AI_IRRMESHLOADER_H_INCLUDED + +#include "./irrXML/irrXMLWrapper.h" + +namespace Assimp { + +#define AI_IRRMESH_MAT_trans_vertex_alpha 0x1 +#define AI_IRRMESH_MAT_lightmap 0x2 +#define AI_IRRMESH_MAT_lightmap_m2 (AI_IRRMESH_MAT_lightmap|0x4) +#define AI_IRRMESH_MAT_lightmap_m4 (AI_IRRMESH_MAT_lightmap|0x5) + +// --------------------------------------------------------------------------- +/** IrrMesh importer class. + * + * IrrMesh is the native file format of the Irrlight engine and its editor + * irrEdit. As IrrEdit itself is capable of importing quite many file formats, + * it might be a good file format for data exchange. + */ +class IRRMeshImporter : public BaseImporter +{ + friend class Importer; + +protected: + /** Constructor to be privately used by Importer */ + IRRMeshImporter(); + + /** Destructor, private as well */ + ~IRRMeshImporter(); + +public: + + // ------------------------------------------------------------------- + /** Returns whether the class can handle the format of the given file. + * See BaseImporter::CanRead() for details. + */ + bool CanRead( const std::string& pFile, IOSystem* pIOHandler) const; + +protected: + + // ------------------------------------------------------------------- + /** Called by Importer::GetExtensionList() for each loaded importer. + * See BaseImporter::GetExtensionList() for details + */ + void GetExtensionList(std::string& append) + { + + /* NOTE: The file extenxsion .xml is too generic. We'll + * need to open the file in CanRead() and check whether it is + * a real irrlicht file + */ + + append.append("*.xml;*.irrmesh"); + } + + // ------------------------------------------------------------------- + /** Imports the given file into the given scene structure. + * See BaseImporter::InternReadFile() for details + */ + void InternReadFile( const std::string& pFile, aiScene* pScene, + IOSystem* pIOHandler); + +private: + + + template + struct Property + { + std::string name; + T value; + }; + + typedef Property HexProperty; + typedef Property StringProperty; + typedef Property BoolProperty; + typedef Property FloatProperty; + + IrrXMLReader* reader; + + + // ------------------------------------------------------------------- + /** Parse a material description from the XML + * @return The created material + * @param matFlags Receives AI_IRRMESH_MAT_XX flags + */ + aiMaterial* ParseMaterial(unsigned int& matFlags); + + + // ------------------------------------------------------------------- + /** Read a property of the specified type from the current XML element. + * @param out Recives output data + */ + void ReadHexProperty (HexProperty& out); + void ReadStringProperty (StringProperty& out); + void ReadBoolProperty (BoolProperty& out); + void ReadFloatProperty (FloatProperty& out); +}; + +} // end of namespace Assimp + +#endif // AI_IRRMESHIMPORTER_H_INC diff --git a/code/Importer.cpp b/code/Importer.cpp index f8f3b6961..d698584ef 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -116,6 +116,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_BUILD_NO_BVH_IMPORTER # include "BVHLoader.h" #endif +#ifndef AI_BUILD_NO_IRRMESH_IMPORTER +# include "IRRMeshLoader.h" +#endif + // PostProcess-Steps @@ -263,6 +267,9 @@ Importer::Importer() : #if (!defined AI_BUILD_NO_BVH_IMPORTER) mImporter.push_back( new BVHLoader()); #endif +#if (!defined AI_BUILD_NO_IRRMESH_IMPORTER) + mImporter.push_back( new IRRMeshImporter()); +#endif // add an instance of each post processing step here in the order // of sequence it is executed. steps that are added here are not validated - diff --git a/code/LWSLoader.h b/code/LWSLoader.h index bd7743c9e..c8ec2cefc 100644 --- a/code/LWSLoader.h +++ b/code/LWSLoader.h @@ -81,6 +81,13 @@ protected: append.append("*.lws"); } + // ------------------------------------------------------------------- + /** Imports the given file into the given scene structure. + * See BaseImporter::InternReadFile() for details + */ + void InternReadFile( const std::string& pFile, aiScene* pScene, + IOSystem* pIOHandler); + private: diff --git a/code/SceneCombiner.cpp b/code/SceneCombiner.cpp index ed090d12a..7d618981f 100644 --- a/code/SceneCombiner.cpp +++ b/code/SceneCombiner.cpp @@ -50,6 +50,31 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { +// ------------------------------------------------------------------------------------------------ +// Add a prefix to a string +inline void PrefixString(aiString& string,const char* prefix, unsigned int len) +{ + // Add the prefix + ::memmove(string.data+len,string.data,string.length+1); + ::memcpy (string.data, prefix, len); + + // And update the string's length + string.length += len; +} + +// ------------------------------------------------------------------------------------------------ +// Add a name prefix to all nodes in a hierarchy +void SceneCombiner::AddNodePrefixes(aiNode* node, const char* prefix, unsigned int len) +{ + ai_assert(NULL != prefix); + + PrefixString(node->mName,prefix,len); + + // Process all children recursively + for (unsigned int i = 0; i < node->mNumChildren;++i) + AddNodePrefixes(node->mChildren[i],prefix,len); +} + // ------------------------------------------------------------------------------------------------ // Merges two scenes. Currently only used by the LWS loader. void SceneCombiner::MergeScenes(aiScene* dest,std::vector& src, @@ -88,7 +113,10 @@ void SceneCombiner::MergeScenes(aiScene* dest,std::vector& src, if ((*cur)->mNumAnimations > 0 || (*cur)->mNumCameras > 0 || - (*cur)->mNumLights > 0)bNeedPrefix = true; + (*cur)->mNumLights > 0) + { + bNeedPrefix = true; + } } // generate the output texture list + an offset table @@ -176,6 +204,17 @@ void SceneCombiner::MergeScenes(aiScene* dest,std::vector& src, if (bNeedPrefix) { + // Allocate space for light sources, cameras and animations + aiLight** ppLights = dest->mLights = (dest->mNumLights + ? new aiLight*[dest->mNumLights] : NULL); + + aiCamera** ppCameras = dest->mCameras = (dest->mNumCameras + ? new aiCamera*[dest->mNumCameras] : NULL); + + aiAnimation** ppAnims = dest->mAnimations = (dest->mNumAnimations + ? new aiAnimation*[dest->mNumAnimations] : NULL); + + for (cur = begin, cnt = 0; cur != end; ++cur) { char buffer[10]; @@ -187,13 +226,31 @@ void SceneCombiner::MergeScenes(aiScene* dest,std::vector& src, *sz++ = '_'; *sz++ = '\0'; -// AddNodePrefixes((*cur)->mRootNode,buffer,*cur); - /** CONTINUE WORK HERE **/ + const unsigned int len = (unsigned int)::strlen(buffer); + AddNodePrefixes((*cur)->mRootNode,buffer,len); + + // Copy light sources, add the prefix to them, too + for (unsigned int i = 0; i < (*cur)->mNumLights;++i,++ppLights) + { + *ppLights = (*cur)->mLights[i]; + PrefixString((*ppLights)->mName,buffer,len); + } + // Copy cameras, add the prefix to them, too + for (unsigned int i = 0; i < (*cur)->mNumCameras;++i,++ppCameras) + { + *ppCameras = (*cur)->mCameras[i]; + PrefixString((*ppCameras)->mName,buffer,len); + } + + // Copy animations, add the prefix to them, too + for (unsigned int i = 0; i < (*cur)->mNumAnimations;++i,++ppAnims) + { + *ppAnims = (*cur)->mAnimations[i]; + PrefixString((*ppAnims)->mName,buffer,len); + } } } - // now copy all cameras - // now delete all input scenes for (cur = begin; cur != end; ++cur) { diff --git a/code/SceneCombiner.h b/code/SceneCombiner.h index 2cc9621ba..4d0fc08fb 100644 --- a/code/SceneCombiner.h +++ b/code/SceneCombiner.h @@ -86,6 +86,17 @@ public: */ static void MergeMeshes(aiMesh* dest,std::vector& src, unsigned int flags); + + + // ------------------------------------------------------------------- + /** Add a name prefix to all nodes in a scene. + * + * @param Current node. This function is called recursively. + * @param prefix Prefix to be added to all nodes + * @param len STring length + */ + static void AddNodePrefixes(aiNode* node, const char* prefix, + unsigned int len); }; } diff --git a/code/irrXML/CXMLReaderImpl.h b/code/irrXML/CXMLReaderImpl.h new file mode 100644 index 000000000..de5ba59f0 --- /dev/null +++ b/code/irrXML/CXMLReaderImpl.h @@ -0,0 +1,801 @@ +// 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 "./../fast_atof.h" + +using namespace Assimp; + +#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 CXMLReaderImpl : public IIrrXMLReader +{ +public: + + //! Constructor + CXMLReaderImpl(IFileReadCallBack* callback, bool deleteCallBack = true) + : TextData(0), P(0), TextSize(0), TextBegin(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 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; + return fast_atof(c.c_str()); + } + + + //! 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 + 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; + + // more 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 s(start, (int)(end - start)); + NodeName = replaceSpecialCharacters(s); + + // current XML node type is text + CurrentNodeType = EXN_TEXT; + + return true; + } + + + + //! ignores an xml definition like + 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(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(attributeNameBegin, + (int)(attributeNameEnd - attributeNameBegin)); + + core::string 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(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; + + NodeName = core::string(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 '' && + (*(P-1) == L']') && + (*(P-2) == L']')) + { + cDataEnd = P - 2; + } + + ++P; + } + + if ( cDataEnd ) + NodeName = core::string(cDataBegin, (int)(cDataEnd - cDataBegin)); + else + NodeName = ""; + + return true; + } + + + // structure for storing attribute-name pairs + struct SAttribute + { + core::string Name; + core::string 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 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 replaceSpecialCharacters( + core::string& origstr) + { + int pos = origstr.findFirst(L'&'); + int oldPos = 0; + + if (pos == -1) + return origstr; + + core::string 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(data8); + char32* data32 = reinterpret_cast(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 + 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 ... + // todo ... I temporarily disabled the check in the build config + for (int i=0; i + 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("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 NodeName; // name of the node currently in + core::string EmptyString; // empty string to be returned by getSafe() methods + + bool IsEmptyElement; // is the currently parsed node empty? + + core::array< core::string > SpecialCharacters; // see createSpecialCharacterList() + + core::array Attributes; // attributes of current element + +}; // end CXMLReaderImpl + + +} // end namespace +} // end namespace + +#endif diff --git a/code/irrXML/fast_atof.h b/code/irrXML/fast_atof.h new file mode 100644 index 000000000..da5c65f75 --- /dev/null +++ b/code/irrXML/fast_atof.h @@ -0,0 +1,139 @@ +// 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 __FAST_A_TO_F_H_INCLUDED__ +#define __FAST_A_TO_F_H_INCLUDED__ + +#include +#include + +namespace irr +{ +namespace core +{ + +const float fast_atof_table[] = { + 0.f, + 0.1f, + 0.01f, + 0.001f, + 0.0001f, + 0.00001f, + 0.000001f, + 0.0000001f, + 0.00000001f, + 0.000000001f, + 0.0000000001f, + 0.00000000001f, + 0.000000000001f, + 0.0000000000001f, + 0.00000000000001f, + 0.000000000000001f + }; + +//! Provides a fast function for converting a string into a float, +//! about 6 times faster than atof in win32. +// If you find any bugs, please send them to me, niko (at) irrlicht3d.org. +inline char* fast_atof_move(char* c, float& out) +{ + bool inv = false; + char *t; + float f; + + if (*c=='-') + { + c++; + inv = true; + } + + f = (float)strtol(c, &t, 10); + + c = t; + + if (*c == '.') + { + c++; + + float pl = (float)strtol(c, &t, 10); + pl *= fast_atof_table[t-c]; + + f += pl; + + c = t; + + if (*c == 'e') + { + ++c; + float exp = (float)strtol(c, &t, 10); + f *= (float)pow(10.0f, exp); + c = t; + } + } + + if (inv) + f *= -1.0f; + + out = f; + return c; +} + +//! Provides a fast function for converting a string into a float, +//! about 6 times faster than atof in win32. +// If you find any bugs, please send them to me, niko (at) irrlicht3d.org. +inline const char* fast_atof_move_const(const char* c, float& out) +{ + bool inv = false; + char *t; + float f; + + if (*c=='-') + { + c++; + inv = true; + } + + f = (float)strtol(c, &t, 10); + + c = t; + + if (*c == '.') + { + c++; + + float pl = (float)strtol(c, &t, 10); + pl *= fast_atof_table[t-c]; + + f += pl; + + c = t; + + if (*c == 'e') + { + ++c; + f32 exp = (f32)strtol(c, &t, 10); + f *= (f32)powf(10.0f, exp); + c = t; + } + } + + if (inv) + f *= -1.0f; + + out = f; + return c; +} + + +inline float fast_atof(const char* c) +{ + float ret; + fast_atof_move_const(c, ret); + return ret; +} + +} // end namespace core +}// end namespace irr + +#endif + diff --git a/code/irrXML/heapsort.h b/code/irrXML/heapsort.h new file mode 100644 index 000000000..4395119df --- /dev/null +++ b/code/irrXML/heapsort.h @@ -0,0 +1,73 @@ +// 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 +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 +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 + diff --git a/code/irrXML/irrArray.h b/code/irrXML/irrArray.h new file mode 100644 index 000000000..5347f829a --- /dev/null +++ b/code/irrXML/irrArray.h @@ -0,0 +1,444 @@ +// 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 array +{ + +public: + + array() + : data(0), used(0), allocated(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), used(0), allocated(0), + free_when_destroyed(true), is_sorted(true) + { + reallocate(start_count); + } + + + //! Copy constructor + array(const array& 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 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& 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=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=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 || index<0 || count<1 || index+count>used) // access violation + + for (u32 i=index+count; i and string work both with unicode AND ascii, +so you can assign unicode to string and ascii to string +(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 string +{ +public: + + //! Default constructor + string() + : allocated(1), used(1), array(0) + { + array = new T[1]; + array[0] = 0x0; + } + + + + //! Constructor + string(const string& other) + : allocated(0), used(0), array(0) + { + *this = other; + } + + + //! Constructs a string from an int + string(int number) + : allocated(0), used(0), array(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 + string(const B* c, s32 lenght) + : allocated(0), used(0), array(0) + { + if (!c) + return; + + allocated = used = lenght+1; + array = new T[used]; + + for (s32 l = 0; l + string(const B* c) + : allocated(0), used(0), array(0) + { + *this = c; + } + + + + //! destructor + ~string() + { + delete [] array; + } + + + + //! Assignment operator + string& operator=(const string& 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 + string& 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 operator+(const string& other) + { + string str(*this); + str.append(other); + + return str; + } + + //! Add operator for strings, ascii and unicode + template + string operator+(const B* c) + { + string 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& 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& 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& 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=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=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& 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& 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& other) + { + --used; + + s32 len = other.size(); + + if (used + len + 1 > allocated) + reallocate((s32)used + (s32)len + 1); + + for (s32 l=0; l& 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 + s32 findFirstCharNotInList(B* c, int count) const + { + for (int i=0; i + s32 findLastCharNotInList(B* c, int count) const + { + for (int i=used-2; i>=0; --i) + { + int j; + for (j=0; j=0; --i) + if (array[i] == c) + return i; + + return -1; + } + + + //! Returns a substring + //! \param begin: Start of substring. + //! \param length: Length of substring. + string subString(s32 begin, s32 length) + { + if (length <= 0) + return string(""); + + string o; + o.reserve(length+1); + + for (s32 i=0; i& other) + { + append(other); + } + + void operator += (int i) + { + append(string(i)); + } + + //! replaces all characters of a special type with another one + void replace(T toReplace, T replaceWith) + { + for (s32 i=0; i=used || index<0) // access violation + + for (int i=index+1; i=(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 stringc; + +//! Typedef for wide character strings +typedef string stringw; + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/code/irrXML/irrTypes.h b/code/irrXML/irrTypes.h new file mode 100644 index 000000000..aa2254d1c --- /dev/null +++ b/code/irrXML/irrTypes.h @@ -0,0 +1,101 @@ +// 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. +#if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) +#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) if (_CONDITION_) {_asm int 3} +#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*/ +#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__ + diff --git a/code/irrXML/irrXML.cpp b/code/irrXML/irrXML.cpp new file mode 100644 index 000000000..e4dbaf7a7 --- /dev/null +++ b/code/irrXML/irrXML.cpp @@ -0,0 +1,152 @@ +// 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 + +#include "./../../include/aiTypes.h" + +#include "irrXML.h" +#include "irrString.h" +#include "irrArray.h" +#include "./../fast_atof.h" +#include "CXMLReaderImpl.h" + +namespace irr +{ +namespace io +{ + +//! Implementation of the file read callback for ordinary files +class 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(new CFileReadCallBack(filename)); +} + + +//! Creates an instance of an UFT-8 or ASCII character xml parser. +IrrXMLReader* createIrrXMLReader(FILE* file) +{ + return new CXMLReaderImpl(new CFileReadCallBack(file)); +} + + +//! Creates an instance of an UFT-8 or ASCII character xml parser. +IrrXMLReader* createIrrXMLReader(IFileReadCallBack* callback) +{ + return new CXMLReaderImpl(callback, false); +} + + +//! Creates an instance of an UTF-16 xml parser. +IrrXMLReaderUTF16* createIrrXMLReaderUTF16(const char* filename) +{ + return new CXMLReaderImpl(new CFileReadCallBack(filename)); +} + + +//! Creates an instance of an UTF-16 xml parser. +IrrXMLReaderUTF16* createIrrXMLReaderUTF16(FILE* file) +{ + return new CXMLReaderImpl(new CFileReadCallBack(file)); +} + + +//! Creates an instance of an UTF-16 xml parser. +IrrXMLReaderUTF16* createIrrXMLReaderUTF16(IFileReadCallBack* callback) +{ + return new CXMLReaderImpl(callback, false); +} + + +//! Creates an instance of an UTF-32 xml parser. +IrrXMLReaderUTF32* createIrrXMLReaderUTF32(const char* filename) +{ + return new CXMLReaderImpl(new CFileReadCallBack(filename)); +} + + +//! Creates an instance of an UTF-32 xml parser. +IrrXMLReaderUTF32* createIrrXMLReaderUTF32(FILE* file) +{ + return new CXMLReaderImpl(new CFileReadCallBack(file)); +} + + +//! Creates an instance of an UTF-32 xml parser. +IrrXMLReaderUTF32* createIrrXMLReaderUTF32(IFileReadCallBack* callback) +{ + return new CXMLReaderImpl(callback, false); +} + + +} // end namespace io +} // end namespace irr diff --git a/code/irrXML/irrXML.h b/code/irrXML/irrXML.h new file mode 100644 index 000000000..23eb2a11b --- /dev/null +++ b/code/irrXML/irrXML.h @@ -0,0 +1,540 @@ +// 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 + +/** \mainpage irrXML 1.2 API documentation +
+ + \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 xml.irrlicht3d.org + 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 + + + + + + Welcome to the Mesh Viewer of the "Irrlicht Engine". + + + \endcode + + The code for parsing this file would look like this: + \code + #include + using namespace irr; // irrXML is located in the namespace irr::io + using namespace io; + + #include // 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 + Irrlicht Engine. 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 + EXN_ELEMENT, + + //! End of an xml element, like + EXN_ELEMENT_END, + + //! Text within a xml element: this is the text. + 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 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(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 + 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 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 + 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 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 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 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. */ + 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. */ + 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. */ + 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. */ + 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. */ + 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. */ + 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. */ + 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. */ + 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. */ + 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 + \endcode + + It is also common to use the two namespaces in which irrXML is included, + directly after #including irrXML.h: + + \code + #include + using namespace irr; + using namespace io; + \endcode + */ + +} // end namespace io +} // end namespace irr + +#endif // __IRR_XML_H_INCLUDED__ + diff --git a/code/irrXML/irrXMLWrapper.h b/code/irrXML/irrXMLWrapper.h new file mode 100644 index 000000000..8e171b05c --- /dev/null +++ b/code/irrXML/irrXMLWrapper.h @@ -0,0 +1,46 @@ + +#ifndef AI_IRRXML_WRAPPER_H_INCLUDED +#define AI_IRRXML_WRAPPER_H_INCLUDED + +#include "irrXML.h" +#include "./../../include/IOStream.h" + +namespace Assimp { +using namespace irr; +using namespace irr::io; + +class CIrrXML_IOStreamReader +{ +public: + + CIrrXML_IOStreamReader(IOStream* _stream) + : stream (_stream) + {} + + //! virtual destructor + virtual ~CIrrXML_IOStreamReader() {}; + + //! 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) + { + return (int)stream->Read(buffer,1,sizeToRead); + } + + //! Returns size of file in bytes + virtual int getSize() + { + return (int)stream->FileSize(); + } + +private: + + IOStream* stream; +}; + + +} // ! Assimp + +#endif \ No newline at end of file diff --git a/code/makefile b/code/makefile index 4b26e7547..f3808fd82 100644 --- a/code/makefile +++ b/code/makefile @@ -67,7 +67,9 @@ SOURCES = AssimpPCH.cpp \ SceneCombiner.cpp \ SkeletonMeshBuilder.cpp \ FindDegenerates.cpp \ - XFileParser.cpp + XFileParser.cpp \ + ./irrXML/irrXML.cpp \ + IRRMeshLoader.cpp OBJECTS = $(SOURCES:.cpp=.o) diff --git a/code/makefile.mingw b/code/makefile.mingw index a0ea5f01e..c5c19ddbe 100644 --- a/code/makefile.mingw +++ b/code/makefile.mingw @@ -67,7 +67,9 @@ SOURCES = AssimpPCH.cpp \ SceneCombiner.cpp \ FindDegenerates.cpp \ SkeletonMeshBuilder.cpp \ - BVHLoader.cpp + BVHLoader.cpp \ + ./irrXML/irrXML.cpp \ + IRRMeshLoader.cpp OBJECTS = $(SOURCES:.cpp=.o) diff --git a/contrib/tinyxml-2.53/Makefile b/contrib/tinyxml-2.53/Makefile deleted file mode 100644 index fb8982a2d..000000000 --- a/contrib/tinyxml-2.53/Makefile +++ /dev/null @@ -1,130 +0,0 @@ -#**************************************************************************** -# -# Makefile for TinyXml test. -# Lee Thomason -# www.grinninglizard.com -# -# This is a GNU make (gmake) makefile -#**************************************************************************** - -# DEBUG can be set to YES to include debugging info, or NO otherwise -DEBUG := YES - -# PROFILE can be set to YES to include profiling info, or NO otherwise -PROFILE := NO - -# TINYXML_USE_STL can be used to turn on STL support. NO, then STL -# will not be used. YES will include the STL files. -TINYXML_USE_STL := YES - -#**************************************************************************** - -CC := gcc -CXX := g++ -LD := g++ -AR := ar rc -RANLIB := ranlib - -DEBUG_CFLAGS := -Wall -Wno-format -g -DDEBUG -RELEASE_CFLAGS := -Wall -Wno-unknown-pragmas -Wno-format -O3 - -LIBS := - -DEBUG_CXXFLAGS := ${DEBUG_CFLAGS} -RELEASE_CXXFLAGS := ${RELEASE_CFLAGS} - -DEBUG_LDFLAGS := -g -RELEASE_LDFLAGS := - -ifeq (YES, ${DEBUG}) - CFLAGS := ${DEBUG_CFLAGS} - CXXFLAGS := ${DEBUG_CXXFLAGS} - LDFLAGS := ${DEBUG_LDFLAGS} -else - CFLAGS := ${RELEASE_CFLAGS} - CXXFLAGS := ${RELEASE_CXXFLAGS} - LDFLAGS := ${RELEASE_LDFLAGS} -endif - -ifeq (YES, ${PROFILE}) - CFLAGS := ${CFLAGS} -pg -O3 - CXXFLAGS := ${CXXFLAGS} -pg -O3 - LDFLAGS := ${LDFLAGS} -pg -endif - -#**************************************************************************** -# Preprocessor directives -#**************************************************************************** - -ifeq (YES, ${TINYXML_USE_STL}) - DEFS := -DTIXML_USE_STL -else - DEFS := -endif - -#**************************************************************************** -# Include paths -#**************************************************************************** - -#INCS := -I/usr/include/g++-2 -I/usr/local/include -INCS := - - -#**************************************************************************** -# Makefile code common to all platforms -#**************************************************************************** - -CFLAGS := ${CFLAGS} ${DEFS} -CXXFLAGS := ${CXXFLAGS} ${DEFS} - -#**************************************************************************** -# Targets of the build -#**************************************************************************** - -OUTPUT := xmltest - -all: ${OUTPUT} - - -#**************************************************************************** -# Source files -#**************************************************************************** - -SRCS := tinyxml.cpp tinyxmlparser.cpp xmltest.cpp tinyxmlerror.cpp tinystr.cpp - -# Add on the sources for libraries -SRCS := ${SRCS} - -OBJS := $(addsuffix .o,$(basename ${SRCS})) - -#**************************************************************************** -# Output -#**************************************************************************** - -${OUTPUT}: ${OBJS} - ${LD} -o $@ ${LDFLAGS} ${OBJS} ${LIBS} ${EXTRA_LIBS} - -#**************************************************************************** -# common rules -#**************************************************************************** - -# Rules for compiling source files to object files -%.o : %.cpp - ${CXX} -c ${CXXFLAGS} ${INCS} $< -o $@ - -%.o : %.c - ${CC} -c ${CFLAGS} ${INCS} $< -o $@ - -dist: - bash makedistlinux - -clean: - -rm -f core ${OBJS} ${OUTPUT} - -depend: - #makedepend ${INCS} ${SRCS} - -tinyxml.o: tinyxml.h tinystr.h -tinyxmlparser.o: tinyxml.h tinystr.h -xmltest.o: tinyxml.h tinystr.h -tinyxmlerror.o: tinyxml.h tinystr.h diff --git a/contrib/tinyxml-2.53/changes.txt b/contrib/tinyxml-2.53/changes.txt deleted file mode 100644 index 4075fd620..000000000 --- a/contrib/tinyxml-2.53/changes.txt +++ /dev/null @@ -1,269 +0,0 @@ -Changes in version 1.0.1: -- Fixed comment tags which were outputing as ' include. Thanks - to Steve Lhomme for that. - -Changes in version 2.0.0 BETA -- Made the ToXXX() casts safe if 'this' is null. - When "LoadFile" is called with a filename, the value will correctly get set. - Thanks to Brian Yoder. -- Fixed bug where isalpha() and isalnum() would get called with a negative value for - high ascii numbers. Thanks to Alesky Aksenov. -- Fixed some errors codes that were not getting set. -- Made methods "const" that were not. -- Added a switch to enable or disable the ignoring of white space. ( TiXmlDocument::SetIgnoreWhiteSpace() ) -- Greater standardization and code re-use in the parser. -- Added a stream out operator. -- Added a stream in operator. -- Entity support, of predefined entites. &#x entities are untouched by input or output. -- Improved text out formatting. -- Fixed ReplaceChild bug, thanks to Tao Chen. - -Changes in version 2.0.1 -- Fixed hanging on loading a 0 length file. Thanks to Jeff Scozzafava. -- Fixed crashing on InsertBeforeChild and InsertAfterChild. Also possibility of bad links being - created by same function. Thanks to Frank De prins. -- Added missing licence text. Thanks to Lars Willemsens. -- Added include, at the suggestion of Steve Walters. - -Changes in version 2.1.0 -- Yves Berquin brings us the STL switch. The forum on SourceForge, and various emails to - me, have long debated all out STL vs. no STL at all. And now you can have it both ways. - TinyXml will compile either way. - -Changes in version 2.1.1 -- Compilation warnings. - -Changes in version 2.1.2 -- Uneeded code is not compiled in the STL case. -- Changed headers so that STL can be turned on or off in tinyxml.h - -Changes in version 2.1.3 -- Fixed non-const reference in API; now uses a pointer. -- Copy constructor of TiXmlString not checking for assignment to self. -- Nimrod Cohen found a truly evil bug in the STL implementation that occurs - when a string is converted to a c_str and then assigned to self. Search for - STL_STRING_BUG for a full description. I'm asserting this is a Microsoft STL - bug, since &string and string.c_str() should never be the same. Nevertheless, - the code works around it. -- Urivan Saaib pointed out a compiler conflict, where the C headers define - the isblank macro, which was wiping out the TiXmlString::isblank() method. - The method was unused and has been removed. - -Changes in version 2.1.4 -- Reworked the entity code. Entities were not correctly surving round trip input and output. - Will now automatically create entities for high ascii in output. - -Changes in version 2.1.5 -- Bug fix by kylotan : infinite loop on some input (tinyxmlparser.cpp rev 1.27) -- Contributed by Ivica Aracic (bytelord) : 1 new VC++ project to compile versions as static libraries (tinyxml_lib.dsp), - and an example usage in xmltest.dsp - (Patch request ID 678605) -- A suggestion by Ronald Fenner Jr (dormlock) to add #include and for Apple's Project Builder - (Patch request ID 697642) -- A patch from ohommes that allows to parse correctly dots in element names and attribute names - (Patch request 602600 and kylotan 701728) -- A patch from hermitgeek ( James ) and wasteland for improper error reporting -- Reviewed by Lee, with the following changes: - - Got sick of fighting the STL/non-STL thing in the windows build. Broke - them out as seperate projects. - - I have too long not included the dsw. Added. - - TinyXmlText had a protected Print. Odd. - - Made LinkEndChild public, with docs and appropriate warnings. - - Updated the docs. - -2.2.0 -- Fixed an uninitialized pointer in the TiXmlAttributes -- Fixed STL compilation problem in MinGW (and gcc 3?) - thanks Brian Yoder for finding this one -- Fixed a syntax error in TiXmlDeclaration - thanks Brian Yoder -- Fletcher Dunn proposed and submitted new error handling that tracked the row and column. Lee - modified it to not have performance impact. -- General cleanup suggestions from Fletcher Dunn. -- In error handling, general errors will no longer clear the error state of specific ones. -- Fix error in documentation : comments starting with ">) has now - been fixed. - -2.5.2 -- Lieven, and others, pointed out a missing const-cast that upset the Open Watcom compiler. - Should now be fixed. -- ErrorRow and ErrorCol should have been const, and weren't. Fixed thanks to Dmitry Polutov. - -2.5.3 -- zloe_zlo identified a missing string specialization for QueryValueAttribute() [ 1695429 ]. Worked - on this bug, but not sure how to fix it in a safe, cross-compiler way. -- increased warning level to 4 and turned on detect 64 bit portability issues for VC2005. - May address [ 1677737 ] VS2005: /Wp64 warnings -- grosheck identified several problems with the Document copy. Many thanks for [ 1660367 ] -- Nice catch, and suggested fix, be Gilad Novik on the Printer dropping entities. - "[ 1600650 ] Bug when printing xml text" is now fixed. -- A subtle fix from Nicos Gollan in the tinystring initializer: - [ 1581449 ] Fix initialiser of TiXmlString::nullrep_ -- Great catch, although there isn't a submitter for the bug. [ 1475201 ] TinyXML parses entities in comments. - Comments should not, in fact, parse entities. Fixed the code path and added tests. -- We were not catching all the returns from ftell. Thanks to Bernard for catching that. - diff --git a/contrib/tinyxml-2.53/echo.dsp b/contrib/tinyxml-2.53/echo.dsp deleted file mode 100644 index 21eb89626..000000000 --- a/contrib/tinyxml-2.53/echo.dsp +++ /dev/null @@ -1,113 +0,0 @@ -# Microsoft Developer Studio Project File - Name="echo" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=echo - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "echo.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "echo.mak" CFG="echo - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "echo - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "echo - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "echo - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "echoRelease" -# PROP Intermediate_Dir "echoRelease" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "TIXML_USE_STL" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "echo - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "echo___Win32_Debug" -# PROP BASE Intermediate_Dir "echo___Win32_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "echoDebug" -# PROP Intermediate_Dir "echoDebug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "TIXML_USE_STL" /FR /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "echo - Win32 Release" -# Name "echo - Win32 Debug" -# Begin Source File - -SOURCE=.\xmltester\bugtest.cpp -# End Source File -# Begin Source File - -SOURCE=.\tinystr.cpp -# End Source File -# Begin Source File - -SOURCE=.\tinystr.h -# End Source File -# Begin Source File - -SOURCE=.\tinyxml.cpp -# End Source File -# Begin Source File - -SOURCE=.\tinyxml.h -# End Source File -# Begin Source File - -SOURCE=.\tinyxmlerror.cpp -# End Source File -# Begin Source File - -SOURCE=.\tinyxmlparser.cpp -# End Source File -# End Target -# End Project diff --git a/contrib/tinyxml-2.53/readme.txt b/contrib/tinyxml-2.53/readme.txt deleted file mode 100644 index 14ec3d2e0..000000000 --- a/contrib/tinyxml-2.53/readme.txt +++ /dev/null @@ -1,530 +0,0 @@ -/** @mainpage - -

TinyXML

- -TinyXML is a simple, small, C++ XML parser that can be easily -integrated into other programs. - -

What it does.

- -In brief, TinyXML parses an XML document, and builds from that a -Document Object Model (DOM) that can be read, modified, and saved. - -XML stands for "eXtensible Markup Language." It allows you to create -your own document markups. Where HTML does a very good job of marking -documents for browsers, XML allows you to define any kind of document -markup, for example a document that describes a "to do" list for an -organizer application. XML is a very structured and convenient format. -All those random file formats created to store application data can -all be replaced with XML. One parser for everything. - -The best place for the complete, correct, and quite frankly hard to -read spec is at -http://www.w3.org/TR/2004/REC-xml-20040204/. An intro to XML -(that I really like) can be found at -http://skew.org/xml/tutorial. - -There are different ways to access and interact with XML data. -TinyXML uses a Document Object Model (DOM), meaning the XML data is parsed -into a C++ objects that can be browsed and manipulated, and then -written to disk or another output stream. You can also construct an XML document -from scratch with C++ objects and write this to disk or another output -stream. - -TinyXML is designed to be easy and fast to learn. It is two headers -and four cpp files. Simply add these to your project and off you go. -There is an example file - xmltest.cpp - to get you started. - -TinyXML is released under the ZLib license, -so you can use it in open source or commercial code. The details -of the license are at the top of every source file. - -TinyXML attempts to be a flexible parser, but with truly correct and -compliant XML output. TinyXML should compile on any reasonably C++ -compliant system. It does not rely on exceptions or RTTI. It can be -compiled with or without STL support. TinyXML fully supports -the UTF-8 encoding, and the first 64k character entities. - - -

What it doesn't do.

- -TinyXML doesn't parse or use DTDs (Document Type Definitions) or XSLs -(eXtensible Stylesheet Language.) There are other parsers out there -(check out www.sourceforge.org, search for XML) that are much more fully -featured. But they are also much bigger, take longer to set up in -your project, have a higher learning curve, and often have a more -restrictive license. If you are working with browsers or have more -complete XML needs, TinyXML is not the parser for you. - -The following DTD syntax will not parse at this time in TinyXML: - -@verbatim - - ]> -@endverbatim - -because TinyXML sees this as a !DOCTYPE node with an illegally -embedded !ELEMENT node. This may be addressed in the future. - -

Tutorials.

- -For the impatient, here is a tutorial to get you going. A great way to get started, -but it is worth your time to read this (very short) manual completely. - -- @subpage tutorial0 - -

Code Status.

- -TinyXML is mature, tested code. It is very stable. If you find -bugs, please file a bug report on the sourceforge web site -(www.sourceforge.net/projects/tinyxml). We'll get them straightened -out as soon as possible. - -There are some areas of improvement; please check sourceforge if you are -interested in working on TinyXML. - -

Related Projects

- -TinyXML projects you may find useful! (Descriptions provided by the projects.) - -
    -
  • TinyXPath (http://tinyxpath.sourceforge.net). TinyXPath is a small footprint - XPath syntax decoder, written in C++.
  • -
  • TinyXML++ (http://code.google.com/p/ticpp/). TinyXML++ is a completely new - interface to TinyXML that uses MANY of the C++ strengths. Templates, - exceptions, and much better error handling.
  • -
- -

Features

- -

Using STL

- -TinyXML can be compiled to use or not use STL. When using STL, TinyXML -uses the std::string class, and fully supports std::istream, std::ostream, -operator<<, and operator>>. Many API methods have both 'const char*' and -'const std::string&' forms. - -When STL support is compiled out, no STL files are included whatsoever. All -the string classes are implemented by TinyXML itself. API methods -all use the 'const char*' form for input. - -Use the compile time #define: - - TIXML_USE_STL - -to compile one version or the other. This can be passed by the compiler, -or set as the first line of "tinyxml.h". - -Note: If compiling the test code in Linux, setting the environment -variable TINYXML_USE_STL=YES/NO will control STL compilation. In the -Windows project file, STL and non STL targets are provided. In your project, -It's probably easiest to add the line "#define TIXML_USE_STL" as the first -line of tinyxml.h. - -

UTF-8

- -TinyXML supports UTF-8 allowing to manipulate XML files in any language. TinyXML -also supports "legacy mode" - the encoding used before UTF-8 support and -probably best described as "extended ascii". - -Normally, TinyXML will try to detect the correct encoding and use it. However, -by setting the value of TIXML_DEFAULT_ENCODING in the header file, TinyXML -can be forced to always use one encoding. - -TinyXML will assume Legacy Mode until one of the following occurs: -
    -
  1. If the non-standard but common "UTF-8 lead bytes" (0xef 0xbb 0xbf) - begin the file or data stream, TinyXML will read it as UTF-8.
  2. -
  3. If the declaration tag is read, and it has an encoding="UTF-8", then - TinyXML will read it as UTF-8.
  4. -
  5. If the declaration tag is read, and it has no encoding specified, then TinyXML will - read it as UTF-8.
  6. -
  7. If the declaration tag is read, and it has an encoding="something else", then TinyXML - will read it as Legacy Mode. In legacy mode, TinyXML will work as it did before. It's - not clear what that mode does exactly, but old content should keep working.
  8. -
  9. Until one of the above criteria is met, TinyXML runs in Legacy Mode.
  10. -
- -What happens if the encoding is incorrectly set or detected? TinyXML will try -to read and pass through text seen as improperly encoded. You may get some strange results or -mangled characters. You may want to force TinyXML to the correct mode. - -You may force TinyXML to Legacy Mode by using LoadFile( TIXML_ENCODING_LEGACY ) or -LoadFile( filename, TIXML_ENCODING_LEGACY ). You may force it to use legacy mode all -the time by setting TIXML_DEFAULT_ENCODING = TIXML_ENCODING_LEGACY. Likewise, you may -force it to TIXML_ENCODING_UTF8 with the same technique. - -For English users, using English XML, UTF-8 is the same as low-ASCII. You -don't need to be aware of UTF-8 or change your code in any way. You can think -of UTF-8 as a "superset" of ASCII. - -UTF-8 is not a double byte format - but it is a standard encoding of Unicode! -TinyXML does not use or directly support wchar, TCHAR, or Microsoft's _UNICODE at this time. -It is common to see the term "Unicode" improperly refer to UTF-16, a wide byte encoding -of unicode. This is a source of confusion. - -For "high-ascii" languages - everything not English, pretty much - TinyXML can -handle all languages, at the same time, as long as the XML is encoded -in UTF-8. That can be a little tricky, older programs and operating systems -tend to use the "default" or "traditional" code page. Many apps (and almost all -modern ones) can output UTF-8, but older or stubborn (or just broken) ones -still output text in the default code page. - -For example, Japanese systems traditionally use SHIFT-JIS encoding. -Text encoded as SHIFT-JIS can not be read by TinyXML. -A good text editor can import SHIFT-JIS and then save as UTF-8. - -The Skew.org link does a great -job covering the encoding issue. - -The test file "utf8test.xml" is an XML containing English, Spanish, Russian, -and Simplified Chinese. (Hopefully they are translated correctly). The file -"utf8test.gif" is a screen capture of the XML file, rendered in IE. Note that -if you don't have the correct fonts (Simplified Chinese or Russian) on your -system, you won't see output that matches the GIF file even if you can parse -it correctly. Also note that (at least on my Windows machine) console output -is in a Western code page, so that Print() or printf() cannot correctly display -the file. This is not a bug in TinyXML - just an OS issue. No data is lost or -destroyed by TinyXML. The console just doesn't render UTF-8. - - -

Entities

-TinyXML recognizes the pre-defined "character entities", meaning special -characters. Namely: - -@verbatim - & & - < < - > > - " " - ' ' -@endverbatim - -These are recognized when the XML document is read, and translated to there -UTF-8 equivalents. For instance, text with the XML of: - -@verbatim - Far & Away -@endverbatim - -will have the Value() of "Far & Away" when queried from the TiXmlText object, -and will be written back to the XML stream/file as an ampersand. Older versions -of TinyXML "preserved" character entities, but the newer versions will translate -them into characters. - -Additionally, any character can be specified by its Unicode code point: -The syntax " " or " " are both to the non-breaking space characher. - -

Printing

-TinyXML can print output in several different ways that all have strengths and limitations. - -- Print( FILE* ). Output to a std-C stream, which includes all C files as well as stdout. - - "Pretty prints", but you don't have control over printing options. - - The output is streamed directly to the FILE object, so there is no memory overhead - in the TinyXML code. - - used by Print() and SaveFile() - -- operator<<. Output to a c++ stream. - - Integrates with standart C++ iostreams. - - Outputs in "network printing" mode without line breaks. Good for network transmission - and moving XML between C++ objects, but hard for a human to read. - -- TiXmlPrinter. Output to a std::string or memory buffer. - - API is less concise - - Future printing options will be put here. - - Printing may change slightly in future versions as it is refined and expanded. - -

Streams

-With TIXML_USE_STL on TinyXML supports C++ streams (operator <<,>>) streams as well -as C (FILE*) streams. There are some differences that you may need to be aware of. - -C style output: - - based on FILE* - - the Print() and SaveFile() methods - - Generates formatted output, with plenty of white space, intended to be as - human-readable as possible. They are very fast, and tolerant of ill formed - XML documents. For example, an XML document that contains 2 root elements - and 2 declarations, will still print. - -C style input: - - based on FILE* - - the Parse() and LoadFile() methods - - A fast, tolerant read. Use whenever you don't need the C++ streams. - -C++ style output: - - based on std::ostream - - operator<< - - Generates condensed output, intended for network transmission rather than - readability. Depending on your system's implementation of the ostream class, - these may be somewhat slower. (Or may not.) Not tolerant of ill formed XML: - a document should contain the correct one root element. Additional root level - elements will not be streamed out. - -C++ style input: - - based on std::istream - - operator>> - - Reads XML from a stream, making it useful for network transmission. The tricky - part is knowing when the XML document is complete, since there will almost - certainly be other data in the stream. TinyXML will assume the XML data is - complete after it reads the root element. Put another way, documents that - are ill-constructed with more than one root element will not read correctly. - Also note that operator>> is somewhat slower than Parse, due to both - implementation of the STL and limitations of TinyXML. - -

White space

-The world simply does not agree on whether white space should be kept, or condensed. -For example, pretend the '_' is a space, and look at "Hello____world". HTML, and -at least some XML parsers, will interpret this as "Hello_world". They condense white -space. Some XML parsers do not, and will leave it as "Hello____world". (Remember -to keep pretending the _ is a space.) Others suggest that __Hello___world__ should become -Hello___world. - -It's an issue that hasn't been resolved to my satisfaction. TinyXML supports the -first 2 approaches. Call TiXmlBase::SetCondenseWhiteSpace( bool ) to set the desired behavior. -The default is to condense white space. - -If you change the default, you should call TiXmlBase::SetCondenseWhiteSpace( bool ) -before making any calls to Parse XML data, and I don't recommend changing it after -it has been set. - - -

Handles

- -Where browsing an XML document in a robust way, it is important to check -for null returns from method calls. An error safe implementation can -generate a lot of code like: - -@verbatim -TiXmlElement* root = document.FirstChildElement( "Document" ); -if ( root ) -{ - TiXmlElement* element = root->FirstChildElement( "Element" ); - if ( element ) - { - TiXmlElement* child = element->FirstChildElement( "Child" ); - if ( child ) - { - TiXmlElement* child2 = child->NextSiblingElement( "Child" ); - if ( child2 ) - { - // Finally do something useful. -@endverbatim - -Handles have been introduced to clean this up. Using the TiXmlHandle class, -the previous code reduces to: - -@verbatim -TiXmlHandle docHandle( &document ); -TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); -if ( child2 ) -{ - // do something useful -@endverbatim - -Which is much easier to deal with. See TiXmlHandle for more information. - - -

Row and Column tracking

-Being able to track nodes and attributes back to their origin location -in source files can be very important for some applications. Additionally, -knowing where parsing errors occured in the original source can be very -time saving. - -TinyXML can tracks the row and column origin of all nodes and attributes -in a text file. The TiXmlBase::Row() and TiXmlBase::Column() methods return -the origin of the node in the source text. The correct tabs can be -configured in TiXmlDocument::SetTabSize(). - - -

Using and Installing

- -To Compile and Run xmltest: - -A Linux Makefile and a Windows Visual C++ .dsw file is provided. -Simply compile and run. It will write the file demotest.xml to your -disk and generate output on the screen. It also tests walking the -DOM by printing out the number of nodes found using different -techniques. - -The Linux makefile is very generic and runs on many systems - it -is currently tested on mingw and -MacOSX. You do not need to run 'make depend'. The dependecies have been -hard coded. - -

Windows project file for VC6

-
    -
  • tinyxml: tinyxml library, non-STL
  • -
  • tinyxmlSTL: tinyxml library, STL
  • -
  • tinyXmlTest: test app, non-STL
  • -
  • tinyXmlTestSTL: test app, STL
  • -
- -

Makefile

-At the top of the makefile you can set: - -PROFILE, DEBUG, and TINYXML_USE_STL. Details (such that they are) are in -the makefile. - -In the tinyxml directory, type "make clean" then "make". The executable -file 'xmltest' will be created. - - - -

To Use in an Application:

- -Add tinyxml.cpp, tinyxml.h, tinyxmlerror.cpp, tinyxmlparser.cpp, tinystr.cpp, and tinystr.h to your -project or make file. That's it! It should compile on any reasonably -compliant C++ system. You do not need to enable exceptions or -RTTI for TinyXML. - - -

How TinyXML works.

- -An example is probably the best way to go. Take: -@verbatim - - - - Go to the Toy store! - Do bills - -@endverbatim - -Its not much of a To Do list, but it will do. To read this file -(say "demo.xml") you would create a document, and parse it in: -@verbatim - TiXmlDocument doc( "demo.xml" ); - doc.LoadFile(); -@endverbatim - -And its ready to go. Now lets look at some lines and how they -relate to the DOM. - -@verbatim - -@endverbatim - - The first line is a declaration, and gets turned into the - TiXmlDeclaration class. It will be the first child of the - document node. - - This is the only directive/special tag parsed by by TinyXML. - Generally directive tags are stored in TiXmlUnknown so the - commands wont be lost when it is saved back to disk. - -@verbatim - -@endverbatim - - A comment. Will become a TiXmlComment object. - -@verbatim - -@endverbatim - - The "ToDo" tag defines a TiXmlElement object. This one does not have - any attributes, but does contain 2 other elements. - -@verbatim - -@endverbatim - - Creates another TiXmlElement which is a child of the "ToDo" element. - This element has 1 attribute, with the name "priority" and the value - "1". - -@verbatim -Go to the -@endverbatim - - A TiXmlText. This is a leaf node and cannot contain other nodes. - It is a child of the "Item" TiXmlElement. - -@verbatim - -@endverbatim - - - Another TiXmlElement, this one a child of the "Item" element. - -Etc. - -Looking at the entire object tree, you end up with: -@verbatim -TiXmlDocument "demo.xml" - TiXmlDeclaration "version='1.0'" "standalone=no" - TiXmlComment " Our to do list data" - TiXmlElement "ToDo" - TiXmlElement "Item" Attribtutes: priority = 1 - TiXmlText "Go to the " - TiXmlElement "bold" - TiXmlText "Toy store!" - TiXmlElement "Item" Attributes: priority=2 - TiXmlText "Do bills" -@endverbatim - -

Documentation

- -The documentation is build with Doxygen, using the 'dox' -configuration file. - -

License

- -TinyXML is released under the zlib license: - -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. - -

References

- -The World Wide Web Consortium is the definitive standard body for -XML, and there web pages contain huge amounts of information. - -The definitive spec: -http://www.w3.org/TR/2004/REC-xml-20040204/ - -I also recommend "XML Pocket Reference" by Robert Eckstein and published by -OReilly...the book that got the whole thing started. - -

Contributors, Contacts, and a Brief History

- -Thanks very much to everyone who sends suggestions, bugs, ideas, and -encouragement. It all helps, and makes this project fun. A special thanks -to the contributors on the web pages that keep it lively. - -So many people have sent in bugs and ideas, that rather than list here -we try to give credit due in the "changes.txt" file. - -TinyXML was originally written by Lee Thomason. (Often the "I" still -in the documentation.) Lee reviews changes and releases new versions, -with the help of Yves Berquin, Andrew Ellerton, and the tinyXml community. - -We appreciate your suggestions, and would love to know if you -use TinyXML. Hopefully you will enjoy it and find it useful. -Please post questions, comments, file bugs, or contact us at: - -www.sourceforge.net/projects/tinyxml - -Lee Thomason, Yves Berquin, Andrew Ellerton -*/ diff --git a/contrib/tinyxml-2.53/tinyXmlTest.dsp b/contrib/tinyxml-2.53/tinyXmlTest.dsp deleted file mode 100644 index f20a9dd07..000000000 --- a/contrib/tinyxml-2.53/tinyXmlTest.dsp +++ /dev/null @@ -1,92 +0,0 @@ -# Microsoft Developer Studio Project File - Name="tinyXmlTest" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=tinyXmlTest - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "tinyXmlTest.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "tinyXmlTest.mak" CFG="tinyXmlTest - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "tinyXmlTest - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "tinyXmlTest - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "tinyXmlTest - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "tinyXmlTest___Win32_Release" -# PROP BASE Intermediate_Dir "tinyXmlTest___Win32_Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "tinyXmlTest___Win32_Release" -# PROP Intermediate_Dir "tinyXmlTest___Win32_Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 ./Release/tinyxml.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "tinyXmlTest - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "tinyXmlTest___Win32_Debug" -# PROP BASE Intermediate_Dir "tinyXmlTest___Win32_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "tinyXmlTest___Win32_Debug" -# PROP Intermediate_Dir "tinyXmlTest___Win32_Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "TUNE" /FR /FD /GZ /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 ./Debug/tinyxmld.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "tinyXmlTest - Win32 Release" -# Name "tinyXmlTest - Win32 Debug" -# Begin Source File - -SOURCE=.\xmltest.cpp -# End Source File -# End Target -# End Project diff --git a/contrib/tinyxml-2.53/tinyXmlTest.vcproj b/contrib/tinyxml-2.53/tinyXmlTest.vcproj deleted file mode 100644 index f9e5a2042..000000000 --- a/contrib/tinyxml-2.53/tinyXmlTest.vcproj +++ /dev/null @@ -1,227 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/contrib/tinyxml-2.53/tinyXmlTestSTL.dsp b/contrib/tinyxml-2.53/tinyXmlTestSTL.dsp deleted file mode 100644 index f262a3028..000000000 --- a/contrib/tinyxml-2.53/tinyXmlTestSTL.dsp +++ /dev/null @@ -1,92 +0,0 @@ -# Microsoft Developer Studio Project File - Name="tinyXmlTestSTL" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=tinyXmlTestSTL - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "tinyXmlTestSTL.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "tinyXmlTestSTL.mak" CFG="tinyXmlTestSTL - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "tinyXmlTestSTL - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "tinyXmlTestSTL - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "tinyXmlTestSTL - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "tinyXmlTestSTL___Win32_Release" -# PROP BASE Intermediate_Dir "tinyXmlTestSTL___Win32_Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "tinyXmlTestSTL___Win32_Release" -# PROP Intermediate_Dir "tinyXmlTestSTL___Win32_Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "TIXML_USE_STL" /FD /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 ./Release_STL/tinyxml_stl.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "tinyXmlTestSTL - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "tinyXmlTestSTL___Win32_Debug" -# PROP BASE Intermediate_Dir "tinyXmlTestSTL___Win32_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "tinyXmlTestSTL___Win32_Debug" -# PROP Intermediate_Dir "tinyXmlTestSTL___Win32_Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "TIXML_USE_STL" /D "TUNE" /FR /FD /GZ /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 ./Debug_STL/tinyxmld_stl.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "tinyXmlTestSTL - Win32 Release" -# Name "tinyXmlTestSTL - Win32 Debug" -# Begin Source File - -SOURCE=.\xmltest.cpp -# End Source File -# End Target -# End Project diff --git a/contrib/tinyxml-2.53/tinyXmlTestSTL.vcproj b/contrib/tinyxml-2.53/tinyXmlTestSTL.vcproj deleted file mode 100644 index b3203a143..000000000 --- a/contrib/tinyxml-2.53/tinyXmlTestSTL.vcproj +++ /dev/null @@ -1,226 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/contrib/tinyxml-2.53/tinystr.cpp b/contrib/tinyxml-2.53/tinystr.cpp deleted file mode 100644 index 681250714..000000000 --- a/contrib/tinyxml-2.53/tinystr.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original file by Yves Berquin. - -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. -*/ - -/* - * THIS FILE WAS ALTERED BY Tyge Lvset, 7. April 2005. - */ - - -#ifndef TIXML_USE_STL - -#include "tinystr.h" - -// Error value for find primitive -const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1); - - -// Null rep. -TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } }; - - -void TiXmlString::reserve (size_type cap) -{ - if (cap > capacity()) - { - TiXmlString tmp; - tmp.init(length(), cap); - memcpy(tmp.start(), data(), length()); - swap(tmp); - } -} - - -TiXmlString& TiXmlString::assign(const char* str, size_type len) -{ - size_type cap = capacity(); - if (len > cap || cap > 3*(len + 8)) - { - TiXmlString tmp; - tmp.init(len); - memcpy(tmp.start(), str, len); - swap(tmp); - } - else - { - memmove(start(), str, len); - set_size(len); - } - return *this; -} - - -TiXmlString& TiXmlString::append(const char* str, size_type len) -{ - size_type newsize = length() + len; - if (newsize > capacity()) - { - reserve (newsize + capacity()); - } - memmove(finish(), str, len); - set_size(newsize); - return *this; -} - - -TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) -{ - TiXmlString tmp; - tmp.reserve(a.length() + b.length()); - tmp += a; - tmp += b; - return tmp; -} - -TiXmlString operator + (const TiXmlString & a, const char* b) -{ - TiXmlString tmp; - TiXmlString::size_type b_len = static_cast( strlen(b) ); - tmp.reserve(a.length() + b_len); - tmp += a; - tmp.append(b, b_len); - return tmp; -} - -TiXmlString operator + (const char* a, const TiXmlString & b) -{ - TiXmlString tmp; - TiXmlString::size_type a_len = static_cast( strlen(a) ); - tmp.reserve(a_len + b.length()); - tmp.append(a, a_len); - tmp += b; - return tmp; -} - - -#endif // TIXML_USE_STL diff --git a/contrib/tinyxml-2.53/tinystr.h b/contrib/tinyxml-2.53/tinystr.h deleted file mode 100644 index 3c2aa9d54..000000000 --- a/contrib/tinyxml-2.53/tinystr.h +++ /dev/null @@ -1,319 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original file by Yves Berquin. - -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. -*/ - -/* - * THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005. - * - * - completely rewritten. compact, clean, and fast implementation. - * - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems) - * - fixed reserve() to work as per specification. - * - fixed buggy compares operator==(), operator<(), and operator>() - * - fixed operator+=() to take a const ref argument, following spec. - * - added "copy" constructor with length, and most compare operators. - * - added swap(), clear(), size(), capacity(), operator+(). - */ - -#ifndef TIXML_USE_STL - -#ifndef TIXML_STRING_INCLUDED -#define TIXML_STRING_INCLUDED - -#include -#include - -/* The support for explicit isn't that universal, and it isn't really - required - it is used to check that the TiXmlString class isn't incorrectly - used. Be nice to old compilers and macro it here: -*/ -#if defined(_MSC_VER) && (_MSC_VER >= 1200 ) - // Microsoft visual studio, version 6 and higher. - #define TIXML_EXPLICIT explicit -#elif defined(__GNUC__) && (__GNUC__ >= 3 ) - // GCC version 3 and higher.s - #define TIXML_EXPLICIT explicit -#else - #define TIXML_EXPLICIT -#endif - - -/* - TiXmlString is an emulation of a subset of the std::string template. - Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. - Only the member functions relevant to the TinyXML project have been implemented. - The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase - a string and there's no more room, we allocate a buffer twice as big as we need. -*/ -class TiXmlString -{ - public : - // The size type used - typedef size_t size_type; - - // Error value for find primitive - static const size_type npos; // = -1; - - - // TiXmlString empty constructor - TiXmlString () : rep_(&nullrep_) - { - } - - // TiXmlString copy constructor - TiXmlString ( const TiXmlString & copy) : rep_(0) - { - init(copy.length()); - memcpy(start(), copy.data(), length()); - } - - // TiXmlString constructor, based on a string - TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) - { - init( static_cast( strlen(copy) )); - memcpy(start(), copy, length()); - } - - // TiXmlString constructor, based on a string - TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) - { - init(len); - memcpy(start(), str, len); - } - - // TiXmlString destructor - ~TiXmlString () - { - quit(); - } - - // = operator - TiXmlString& operator = (const char * copy) - { - return assign( copy, (size_type)strlen(copy)); - } - - // = operator - TiXmlString& operator = (const TiXmlString & copy) - { - return assign(copy.start(), copy.length()); - } - - - // += operator. Maps to append - TiXmlString& operator += (const char * suffix) - { - return append(suffix, static_cast( strlen(suffix) )); - } - - // += operator. Maps to append - TiXmlString& operator += (char single) - { - return append(&single, 1); - } - - // += operator. Maps to append - TiXmlString& operator += (const TiXmlString & suffix) - { - return append(suffix.data(), suffix.length()); - } - - - // Convert a TiXmlString into a null-terminated char * - const char * c_str () const { return rep_->str; } - - // Convert a TiXmlString into a char * (need not be null terminated). - const char * data () const { return rep_->str; } - - // Return the length of a TiXmlString - size_type length () const { return rep_->size; } - - // Alias for length() - size_type size () const { return rep_->size; } - - // Checks if a TiXmlString is empty - bool empty () const { return rep_->size == 0; } - - // Return capacity of string - size_type capacity () const { return rep_->capacity; } - - - // single char extraction - const char& at (size_type index) const - { - assert( index < length() ); - return rep_->str[ index ]; - } - - // [] operator - char& operator [] (size_type index) const - { - assert( index < length() ); - return rep_->str[ index ]; - } - - // find a char in a string. Return TiXmlString::npos if not found - size_type find (char lookup) const - { - return find(lookup, 0); - } - - // find a char in a string from an offset. Return TiXmlString::npos if not found - size_type find (char tofind, size_type offset) const - { - if (offset >= length()) return npos; - - for (const char* p = c_str() + offset; *p != '\0'; ++p) - { - if (*p == tofind) return static_cast< size_type >( p - c_str() ); - } - return npos; - } - - void clear () - { - //Lee: - //The original was just too strange, though correct: - // TiXmlString().swap(*this); - //Instead use the quit & re-init: - quit(); - init(0,0); - } - - /* Function to reserve a big amount of data when we know we'll need it. Be aware that this - function DOES NOT clear the content of the TiXmlString if any exists. - */ - void reserve (size_type cap); - - TiXmlString& assign (const char* str, size_type len); - - TiXmlString& append (const char* str, size_type len); - - void swap (TiXmlString& other) - { - Rep* r = rep_; - rep_ = other.rep_; - other.rep_ = r; - } - - private: - - void init(size_type sz) { init(sz, sz); } - void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } - char* start() const { return rep_->str; } - char* finish() const { return rep_->str + rep_->size; } - - struct Rep - { - size_type size, capacity; - char str[1]; - }; - - void init(size_type sz, size_type cap) - { - if (cap) - { - // Lee: the original form: - // rep_ = static_cast(operator new(sizeof(Rep) + cap)); - // doesn't work in some cases of new being overloaded. Switching - // to the normal allocation, although use an 'int' for systems - // that are overly picky about structure alignment. - const size_type bytesNeeded = sizeof(Rep) + cap; - const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); - rep_ = reinterpret_cast( new int[ intsNeeded ] ); - - rep_->str[ rep_->size = sz ] = '\0'; - rep_->capacity = cap; - } - else - { - rep_ = &nullrep_; - } - } - - void quit() - { - if (rep_ != &nullrep_) - { - // The rep_ is really an array of ints. (see the allocator, above). - // Cast it back before delete, so the compiler won't incorrectly call destructors. - delete [] ( reinterpret_cast( rep_ ) ); - } - } - - Rep * rep_; - static Rep nullrep_; - -} ; - - -inline bool operator == (const TiXmlString & a, const TiXmlString & b) -{ - return ( a.length() == b.length() ) // optimization on some platforms - && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare -} -inline bool operator < (const TiXmlString & a, const TiXmlString & b) -{ - return strcmp(a.c_str(), b.c_str()) < 0; -} - -inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } -inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } -inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } -inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } - -inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } -inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } -inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } -inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } - -TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); -TiXmlString operator + (const TiXmlString & a, const char* b); -TiXmlString operator + (const char* a, const TiXmlString & b); - - -/* - TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. - Only the operators that we need for TinyXML have been developped. -*/ -class TiXmlOutStream : public TiXmlString -{ -public : - - // TiXmlOutStream << operator. - TiXmlOutStream & operator << (const TiXmlString & in) - { - *this += in; - return *this; - } - - // TiXmlOutStream << operator. - TiXmlOutStream & operator << (const char * in) - { - *this += in; - return *this; - } - -} ; - -#endif // TIXML_STRING_INCLUDED -#endif // TIXML_USE_STL diff --git a/contrib/tinyxml-2.53/tinyxml.cpp b/contrib/tinyxml-2.53/tinyxml.cpp deleted file mode 100644 index 5de21f6de..000000000 --- a/contrib/tinyxml-2.53/tinyxml.cpp +++ /dev/null @@ -1,1888 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) - -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. -*/ - -#include - -#ifdef TIXML_USE_STL -#include -#include -#endif - -#include "tinyxml.h" - - -bool TiXmlBase::condenseWhiteSpace = true; - -// Microsoft compiler security -FILE* TiXmlFOpen( const char* filename, const char* mode ) -{ - #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) - FILE* fp = 0; - errno_t err = fopen_s( &fp, filename, mode ); - if ( !err && fp ) - return fp; - return 0; - #else - return fopen( filename, mode ); - #endif -} - -void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) -{ - int i=0; - - while( i<(int)str.length() ) - { - unsigned char c = (unsigned char) str[i]; - - if ( c == '&' - && i < ( (int)str.length() - 2 ) - && str[i+1] == '#' - && str[i+2] == 'x' ) - { - // Hexadecimal character reference. - // Pass through unchanged. - // © -- copyright symbol, for example. - // - // The -1 is a bug fix from Rob Laveaux. It keeps - // an overflow from happening if there is no ';'. - // There are actually 2 ways to exit this loop - - // while fails (error case) and break (semicolon found). - // However, there is no mechanism (currently) for - // this function to return an error. - while ( i<(int)str.length()-1 ) - { - outString->append( str.c_str() + i, 1 ); - ++i; - if ( str[i] == ';' ) - break; - } - } - else if ( c == '&' ) - { - outString->append( entity[0].str, entity[0].strLength ); - ++i; - } - else if ( c == '<' ) - { - outString->append( entity[1].str, entity[1].strLength ); - ++i; - } - else if ( c == '>' ) - { - outString->append( entity[2].str, entity[2].strLength ); - ++i; - } - else if ( c == '\"' ) - { - outString->append( entity[3].str, entity[3].strLength ); - ++i; - } - else if ( c == '\'' ) - { - outString->append( entity[4].str, entity[4].strLength ); - ++i; - } - else if ( c < 32 ) - { - // Easy pass at non-alpha/numeric/symbol - // Below 32 is symbolic. - char buf[ 32 ]; - - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); - #else - sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); - #endif - - //*ME: warning C4267: convert 'size_t' to 'int' - //*ME: Int-Cast to make compiler happy ... - outString->append( buf, (int)strlen( buf ) ); - ++i; - } - else - { - //char realc = (char) c; - //outString->append( &realc, 1 ); - *outString += (char) c; // somewhat more efficient function call. - ++i; - } - } -} - - -TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() -{ - parent = 0; - type = _type; - firstChild = 0; - lastChild = 0; - prev = 0; - next = 0; -} - - -TiXmlNode::~TiXmlNode() -{ - TiXmlNode* node = firstChild; - TiXmlNode* temp = 0; - - while ( node ) - { - temp = node; - node = node->next; - delete temp; - } -} - - -void TiXmlNode::CopyTo( TiXmlNode* target ) const -{ - target->SetValue (value.c_str() ); - target->userData = userData; -} - - -void TiXmlNode::Clear() -{ - TiXmlNode* node = firstChild; - TiXmlNode* temp = 0; - - while ( node ) - { - temp = node; - node = node->next; - delete temp; - } - - firstChild = 0; - lastChild = 0; -} - - -TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) -{ - assert( node->parent == 0 || node->parent == this ); - assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); - - if ( node->Type() == TiXmlNode::DOCUMENT ) - { - delete node; - if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - node->parent = this; - - node->prev = lastChild; - node->next = 0; - - if ( lastChild ) - lastChild->next = node; - else - firstChild = node; // it was an empty list. - - lastChild = node; - return node; -} - - -TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) -{ - if ( addThis.Type() == TiXmlNode::DOCUMENT ) - { - if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - - return LinkEndChild( node ); -} - - -TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) -{ - if ( !beforeThis || beforeThis->parent != this ) { - return 0; - } - if ( addThis.Type() == TiXmlNode::DOCUMENT ) - { - if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - node->parent = this; - - node->next = beforeThis; - node->prev = beforeThis->prev; - if ( beforeThis->prev ) - { - beforeThis->prev->next = node; - } - else - { - assert( firstChild == beforeThis ); - firstChild = node; - } - beforeThis->prev = node; - return node; -} - - -TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) -{ - if ( !afterThis || afterThis->parent != this ) { - return 0; - } - if ( addThis.Type() == TiXmlNode::DOCUMENT ) - { - if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - node->parent = this; - - node->prev = afterThis; - node->next = afterThis->next; - if ( afterThis->next ) - { - afterThis->next->prev = node; - } - else - { - assert( lastChild == afterThis ); - lastChild = node; - } - afterThis->next = node; - return node; -} - - -TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) -{ - if ( replaceThis->parent != this ) - return 0; - - TiXmlNode* node = withThis.Clone(); - if ( !node ) - return 0; - - node->next = replaceThis->next; - node->prev = replaceThis->prev; - - if ( replaceThis->next ) - replaceThis->next->prev = node; - else - lastChild = node; - - if ( replaceThis->prev ) - replaceThis->prev->next = node; - else - firstChild = node; - - delete replaceThis; - node->parent = this; - return node; -} - - -bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) -{ - if ( removeThis->parent != this ) - { - assert( 0 ); - return false; - } - - if ( removeThis->next ) - removeThis->next->prev = removeThis->prev; - else - lastChild = removeThis->prev; - - if ( removeThis->prev ) - removeThis->prev->next = removeThis->next; - else - firstChild = removeThis->next; - - delete removeThis; - return true; -} - -const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = firstChild; node; node = node->next ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = lastChild; node; node = node->prev ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const -{ - if ( !previous ) - { - return FirstChild(); - } - else - { - assert( previous->parent == this ); - return previous->NextSibling(); - } -} - - -const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const -{ - if ( !previous ) - { - return FirstChild( val ); - } - else - { - assert( previous->parent == this ); - return previous->NextSibling( val ); - } -} - - -const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = next; node; node = node->next ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = prev; node; node = node->prev ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -void TiXmlElement::RemoveAttribute( const char * name ) -{ - #ifdef TIXML_USE_STL - TIXML_STRING str( name ); - TiXmlAttribute* node = attributeSet.Find( str ); - #else - TiXmlAttribute* node = attributeSet.Find( name ); - #endif - if ( node ) - { - attributeSet.Remove( node ); - delete node; - } -} - -const TiXmlElement* TiXmlNode::FirstChildElement() const -{ - const TiXmlNode* node; - - for ( node = FirstChild(); - node; - node = node->NextSibling() ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const -{ - const TiXmlNode* node; - - for ( node = FirstChild( _value ); - node; - node = node->NextSibling( _value ) ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::NextSiblingElement() const -{ - const TiXmlNode* node; - - for ( node = NextSibling(); - node; - node = node->NextSibling() ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const -{ - const TiXmlNode* node; - - for ( node = NextSibling( _value ); - node; - node = node->NextSibling( _value ) ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlDocument* TiXmlNode::GetDocument() const -{ - const TiXmlNode* node; - - for( node = this; node; node = node->parent ) - { - if ( node->ToDocument() ) - return node->ToDocument(); - } - return 0; -} - - -TiXmlElement::TiXmlElement (const char * _value) - : TiXmlNode( TiXmlNode::ELEMENT ) -{ - firstChild = lastChild = 0; - value = _value; -} - - -#ifdef TIXML_USE_STL -TiXmlElement::TiXmlElement( const std::string& _value ) - : TiXmlNode( TiXmlNode::ELEMENT ) -{ - firstChild = lastChild = 0; - value = _value; -} -#endif - - -TiXmlElement::TiXmlElement( const TiXmlElement& copy) - : TiXmlNode( TiXmlNode::ELEMENT ) -{ - firstChild = lastChild = 0; - copy.CopyTo( this ); -} - - -void TiXmlElement::operator=( const TiXmlElement& base ) -{ - ClearThis(); - base.CopyTo( this ); -} - - -TiXmlElement::~TiXmlElement() -{ - ClearThis(); -} - - -void TiXmlElement::ClearThis() -{ - Clear(); - while( attributeSet.First() ) - { - TiXmlAttribute* node = attributeSet.First(); - attributeSet.Remove( node ); - delete node; - } -} - - -const char* TiXmlElement::Attribute( const char* name ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( node ) - return node->Value(); - return 0; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( node ) - return &node->ValueStr(); - return 0; -} -#endif - - -const char* TiXmlElement::Attribute( const char* name, int* i ) const -{ - const char* s = Attribute( name ); - if ( i ) - { - if ( s ) { - *i = atoi( s ); - } - else { - *i = 0; - } - } - return s; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const -{ - const std::string* s = Attribute( name ); - if ( i ) - { - if ( s ) { - *i = atoi( s->c_str() ); - } - else { - *i = 0; - } - } - return s; -} -#endif - - -const char* TiXmlElement::Attribute( const char* name, double* d ) const -{ - const char* s = Attribute( name ); - if ( d ) - { - if ( s ) { - *d = atof( s ); - } - else { - *d = 0; - } - } - return s; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const -{ - const std::string* s = Attribute( name ); - if ( d ) - { - if ( s ) { - *d = atof( s->c_str() ); - } - else { - *d = 0; - } - } - return s; -} -#endif - - -int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - return node->QueryIntValue( ival ); -} - - -#ifdef TIXML_USE_STL -int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - return node->QueryIntValue( ival ); -} -#endif - - -int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - return node->QueryDoubleValue( dval ); -} - - -#ifdef TIXML_USE_STL -int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - return node->QueryDoubleValue( dval ); -} -#endif - - -void TiXmlElement::SetAttribute( const char * name, int val ) -{ - char buf[64]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "%d", val ); - #else - sprintf( buf, "%d", val ); - #endif - SetAttribute( name, buf ); -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetAttribute( const std::string& name, int val ) -{ - std::ostringstream oss; - oss << val; - SetAttribute( name, oss.str() ); -} -#endif - - -void TiXmlElement::SetDoubleAttribute( const char * name, double val ) -{ - char buf[256]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "%f", val ); - #else - sprintf( buf, "%f", val ); - #endif - SetAttribute( name, buf ); -} - - -void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) -{ - #ifdef TIXML_USE_STL - TIXML_STRING _name( cname ); - TIXML_STRING _value( cvalue ); - #else - const char* _name = cname; - const char* _value = cvalue; - #endif - - TiXmlAttribute* node = attributeSet.Find( _name ); - if ( node ) - { - node->SetValue( _value ); - return; - } - - TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue ); - if ( attrib ) - { - attributeSet.Add( attrib ); - } - else - { - TiXmlDocument* document = GetDocument(); - if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); - } -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value ) -{ - TiXmlAttribute* node = attributeSet.Find( name ); - if ( node ) - { - node->SetValue( _value ); - return; - } - - TiXmlAttribute* attrib = new TiXmlAttribute( name, _value ); - if ( attrib ) - { - attributeSet.Add( attrib ); - } - else - { - TiXmlDocument* document = GetDocument(); - if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); - } -} -#endif - - -void TiXmlElement::Print( FILE* cfile, int depth ) const -{ - int i; - assert( cfile ); - for ( i=0; iNext() ) - { - fprintf( cfile, " " ); - attrib->Print( cfile, depth ); - } - - // There are 3 different formatting approaches: - // 1) An element without children is printed as a node - // 2) An element with only a text child is printed as text - // 3) An element with children is printed on multiple lines. - TiXmlNode* node; - if ( !firstChild ) - { - fprintf( cfile, " />" ); - } - else if ( firstChild == lastChild && firstChild->ToText() ) - { - fprintf( cfile, ">" ); - firstChild->Print( cfile, depth + 1 ); - fprintf( cfile, "", value.c_str() ); - } - else - { - fprintf( cfile, ">" ); - - for ( node = firstChild; node; node=node->NextSibling() ) - { - if ( !node->ToText() ) - { - fprintf( cfile, "\n" ); - } - node->Print( cfile, depth+1 ); - } - fprintf( cfile, "\n" ); - for( i=0; i", value.c_str() ); - } -} - - -void TiXmlElement::CopyTo( TiXmlElement* target ) const -{ - // superclass: - TiXmlNode::CopyTo( target ); - - // Element class: - // Clone the attributes, then clone the children. - const TiXmlAttribute* attribute = 0; - for( attribute = attributeSet.First(); - attribute; - attribute = attribute->Next() ) - { - target->SetAttribute( attribute->Name(), attribute->Value() ); - } - - TiXmlNode* node = 0; - for ( node = firstChild; node; node = node->NextSibling() ) - { - target->LinkEndChild( node->Clone() ); - } -} - -bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const -{ - if ( visitor->VisitEnter( *this, attributeSet.First() ) ) - { - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - if ( !node->Accept( visitor ) ) - break; - } - } - return visitor->VisitExit( *this ); -} - - -TiXmlNode* TiXmlElement::Clone() const -{ - TiXmlElement* clone = new TiXmlElement( Value() ); - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -const char* TiXmlElement::GetText() const -{ - const TiXmlNode* child = this->FirstChild(); - if ( child ) { - const TiXmlText* childText = child->ToText(); - if ( childText ) { - return childText->Value(); - } - } - return 0; -} - - -TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - ClearError(); -} - -TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - value = documentName; - ClearError(); -} - - -#ifdef TIXML_USE_STL -TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - value = documentName; - ClearError(); -} -#endif - - -TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT ) -{ - copy.CopyTo( this ); -} - - -void TiXmlDocument::operator=( const TiXmlDocument& copy ) -{ - Clear(); - copy.CopyTo( this ); -} - - -bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) -{ - // See STL_STRING_BUG below. - //StringToBuffer buf( value ); - - return LoadFile( Value(), encoding ); -} - - -bool TiXmlDocument::SaveFile() const -{ - // See STL_STRING_BUG below. -// StringToBuffer buf( value ); -// -// if ( buf.buffer && SaveFile( buf.buffer ) ) -// return true; -// -// return false; - return SaveFile( Value() ); -} - -bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) -{ - // There was a really terrifying little bug here. The code: - // value = filename - // in the STL case, cause the assignment method of the std::string to - // be called. What is strange, is that the std::string had the same - // address as it's c_str() method, and so bad things happen. Looks - // like a bug in the Microsoft STL implementation. - // Add an extra string to avoid the crash. - TIXML_STRING filename( _filename ); - value = filename; - - // reading in binary mode so that tinyxml can normalize the EOL - FILE* file = TiXmlFOpen( value.c_str (), "rb" ); - - if ( file ) - { - bool result = LoadFile( file, encoding ); - fclose( file ); - return result; - } - else - { - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } -} - -bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) -{ - if ( !file ) - { - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // Delete the existing data: - Clear(); - location.Clear(); - - // Get the file size, so we can pre-allocate the string. HUGE speed impact. - long length = 0; - fseek( file, 0, SEEK_END ); - length = ftell( file ); - fseek( file, 0, SEEK_SET ); - - // Strange case, but good to handle up front. - if ( length <= 0 ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // If we have a file, assume it is all one big XML file, and read it in. - // The document parser may decide the document ends sooner than the entire file, however. - TIXML_STRING data; - data.reserve( length ); - - // Subtle bug here. TinyXml did use fgets. But from the XML spec: - // 2.11 End-of-Line Handling - // - // - // ...the XML processor MUST behave as if it normalized all line breaks in external - // parsed entities (including the document entity) on input, before parsing, by translating - // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to - // a single #xA character. - // - // - // It is not clear fgets does that, and certainly isn't clear it works cross platform. - // Generally, you expect fgets to translate from the convention of the OS to the c/unix - // convention, and not work generally. - - /* - while( fgets( buf, sizeof(buf), file ) ) - { - data += buf; - } - */ - - char* buf = new char[ length+1 ]; - buf[0] = 0; - - if ( fread( buf, length, 1, file ) != 1 ) { - delete [] buf; - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - const char* lastPos = buf; - const char* p = buf; - - buf[length] = 0; - while( *p ) { - assert( p < (buf+length) ); - if ( *p == 0xa ) { - // Newline character. No special rules for this. Append all the characters - // since the last string, and include the newline. - data.append( lastPos, (p-lastPos+1) ); // append, include the newline - ++p; // move past the newline - lastPos = p; // and point to the new buffer (may be 0) - assert( p <= (buf+length) ); - } - else if ( *p == 0xd ) { - // Carriage return. Append what we have so far, then - // handle moving forward in the buffer. - if ( (p-lastPos) > 0 ) { - data.append( lastPos, p-lastPos ); // do not add the CR - } - data += (char)0xa; // a proper newline - - if ( *(p+1) == 0xa ) { - // Carriage return - new line sequence - p += 2; - lastPos = p; - assert( p <= (buf+length) ); - } - else { - // it was followed by something else...that is presumably characters again. - ++p; - lastPos = p; - assert( p <= (buf+length) ); - } - } - else { - ++p; - } - } - // Handle any left over characters. - if ( p-lastPos ) { - data.append( lastPos, p-lastPos ); - } - delete [] buf; - buf = 0; - - Parse( data.c_str(), 0, encoding ); - - if ( Error() ) - return false; - else - return true; -} - - -bool TiXmlDocument::SaveFile( const char * filename ) const -{ - // The old c stuff lives on... - FILE* fp = TiXmlFOpen( filename, "w" ); - if ( fp ) - { - bool result = SaveFile( fp ); - fclose( fp ); - return result; - } - return false; -} - - -bool TiXmlDocument::SaveFile( FILE* fp ) const -{ - if ( useMicrosoftBOM ) - { - const unsigned char TIXML_UTF_LEAD_0 = 0xefU; - const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; - const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; - - fputc( TIXML_UTF_LEAD_0, fp ); - fputc( TIXML_UTF_LEAD_1, fp ); - fputc( TIXML_UTF_LEAD_2, fp ); - } - Print( fp, 0 ); - return (ferror(fp) == 0); -} - - -void TiXmlDocument::CopyTo( TiXmlDocument* target ) const -{ - TiXmlNode::CopyTo( target ); - - target->error = error; - target->errorId = errorId; - target->errorDesc = errorDesc; - target->tabsize = tabsize; - target->errorLocation = errorLocation; - target->useMicrosoftBOM = useMicrosoftBOM; - - TiXmlNode* node = 0; - for ( node = firstChild; node; node = node->NextSibling() ) - { - target->LinkEndChild( node->Clone() ); - } -} - - -TiXmlNode* TiXmlDocument::Clone() const -{ - TiXmlDocument* clone = new TiXmlDocument(); - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlDocument::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - node->Print( cfile, depth ); - fprintf( cfile, "\n" ); - } -} - - -bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const -{ - if ( visitor->VisitEnter( *this ) ) - { - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - if ( !node->Accept( visitor ) ) - break; - } - } - return visitor->VisitExit( *this ); -} - - -const TiXmlAttribute* TiXmlAttribute::Next() const -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( next->value.empty() && next->name.empty() ) - return 0; - return next; -} - -/* -TiXmlAttribute* TiXmlAttribute::Next() -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( next->value.empty() && next->name.empty() ) - return 0; - return next; -} -*/ - -const TiXmlAttribute* TiXmlAttribute::Previous() const -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( prev->value.empty() && prev->name.empty() ) - return 0; - return prev; -} - -/* -TiXmlAttribute* TiXmlAttribute::Previous() -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( prev->value.empty() && prev->name.empty() ) - return 0; - return prev; -} -*/ - -void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const -{ - TIXML_STRING n, v; - - EncodeString( name, &n ); - EncodeString( value, &v ); - - if (value.find ('\"') == TIXML_STRING::npos) { - if ( cfile ) { - fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); - } - if ( str ) { - (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; - } - } - else { - if ( cfile ) { - fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); - } - if ( str ) { - (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; - } - } -} - - -int TiXmlAttribute::QueryIntValue( int* ival ) const -{ - if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; -} - -int TiXmlAttribute::QueryDoubleValue( double* dval ) const -{ - if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; -} - -void TiXmlAttribute::SetIntValue( int _value ) -{ - char buf [64]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); - #else - sprintf (buf, "%d", _value); - #endif - SetValue (buf); -} - -void TiXmlAttribute::SetDoubleValue( double _value ) -{ - char buf [256]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value); - #else - sprintf (buf, "%lf", _value); - #endif - SetValue (buf); -} - -int TiXmlAttribute::IntValue() const -{ - return atoi (value.c_str ()); -} - -double TiXmlAttribute::DoubleValue() const -{ - return atof (value.c_str ()); -} - - -TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT ) -{ - copy.CopyTo( this ); -} - - -void TiXmlComment::operator=( const TiXmlComment& base ) -{ - Clear(); - base.CopyTo( this ); -} - - -void TiXmlComment::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - for ( int i=0; i", value.c_str() ); -} - - -void TiXmlComment::CopyTo( TiXmlComment* target ) const -{ - TiXmlNode::CopyTo( target ); -} - - -bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlComment::Clone() const -{ - TiXmlComment* clone = new TiXmlComment(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlText::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - if ( cdata ) - { - int i; - fprintf( cfile, "\n" ); - for ( i=0; i\n", value.c_str() ); // unformatted output - } - else - { - TIXML_STRING buffer; - EncodeString( value, &buffer ); - fprintf( cfile, "%s", buffer.c_str() ); - } -} - - -void TiXmlText::CopyTo( TiXmlText* target ) const -{ - TiXmlNode::CopyTo( target ); - target->cdata = cdata; -} - - -bool TiXmlText::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlText::Clone() const -{ - TiXmlText* clone = 0; - clone = new TiXmlText( "" ); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -TiXmlDeclaration::TiXmlDeclaration( const char * _version, - const char * _encoding, - const char * _standalone ) - : TiXmlNode( TiXmlNode::DECLARATION ) -{ - version = _version; - encoding = _encoding; - standalone = _standalone; -} - - -#ifdef TIXML_USE_STL -TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, - const std::string& _encoding, - const std::string& _standalone ) - : TiXmlNode( TiXmlNode::DECLARATION ) -{ - version = _version; - encoding = _encoding; - standalone = _standalone; -} -#endif - - -TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) - : TiXmlNode( TiXmlNode::DECLARATION ) -{ - copy.CopyTo( this ); -} - - -void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) -{ - Clear(); - copy.CopyTo( this ); -} - - -void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const -{ - if ( cfile ) fprintf( cfile, "" ); - if ( str ) (*str) += "?>"; -} - - -void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const -{ - TiXmlNode::CopyTo( target ); - - target->version = version; - target->encoding = encoding; - target->standalone = standalone; -} - - -bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlDeclaration::Clone() const -{ - TiXmlDeclaration* clone = new TiXmlDeclaration(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlUnknown::Print( FILE* cfile, int depth ) const -{ - for ( int i=0; i", value.c_str() ); -} - - -void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const -{ - TiXmlNode::CopyTo( target ); -} - - -bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlUnknown::Clone() const -{ - TiXmlUnknown* clone = new TiXmlUnknown(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -TiXmlAttributeSet::TiXmlAttributeSet() -{ - sentinel.next = &sentinel; - sentinel.prev = &sentinel; -} - - -TiXmlAttributeSet::~TiXmlAttributeSet() -{ - assert( sentinel.next == &sentinel ); - assert( sentinel.prev == &sentinel ); -} - - -void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) -{ - #ifdef TIXML_USE_STL - assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. - #else - assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. - #endif - - addMe->next = &sentinel; - addMe->prev = sentinel.prev; - - sentinel.prev->next = addMe; - sentinel.prev = addMe; -} - -void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) -{ - TiXmlAttribute* node; - - for( node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node == removeMe ) - { - node->prev->next = node->next; - node->next->prev = node->prev; - node->next = 0; - node->prev = 0; - return; - } - } - assert( 0 ); // we tried to remove a non-linked attribute. -} - - -#ifdef TIXML_USE_STL -const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const -{ - for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node->name == name ) - return node; - } - return 0; -} - -/* -TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) -{ - for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node->name == name ) - return node; - } - return 0; -} -*/ -#endif - - -const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const -{ - for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( strcmp( node->name.c_str(), name ) == 0 ) - return node; - } - return 0; -} - -/* -TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) -{ - for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( strcmp( node->name.c_str(), name ) == 0 ) - return node; - } - return 0; -} -*/ - -#ifdef TIXML_USE_STL -std::istream& operator>> (std::istream & in, TiXmlNode & base) -{ - TIXML_STRING tag; - tag.reserve( 8 * 1000 ); - base.StreamIn( &in, &tag ); - - base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); - return in; -} -#endif - - -#ifdef TIXML_USE_STL -std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) -{ - TiXmlPrinter printer; - printer.SetStreamPrinting(); - base.Accept( &printer ); - out << printer.Str(); - - return out; -} - - -std::string& operator<< (std::string& out, const TiXmlNode& base ) -{ - TiXmlPrinter printer; - printer.SetStreamPrinting(); - base.Accept( &printer ); - out.append( printer.Str() ); - - return out; -} -#endif - - -TiXmlHandle TiXmlHandle::FirstChild() const -{ - if ( node ) - { - TiXmlNode* child = node->FirstChild(); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const -{ - if ( node ) - { - TiXmlNode* child = node->FirstChild( value ); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChildElement() const -{ - if ( node ) - { - TiXmlElement* child = node->FirstChildElement(); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const -{ - if ( node ) - { - TiXmlElement* child = node->FirstChildElement( value ); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::Child( int count ) const -{ - if ( node ) - { - int i; - TiXmlNode* child = node->FirstChild(); - for ( i=0; - child && iNextSibling(), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const -{ - if ( node ) - { - int i; - TiXmlNode* child = node->FirstChild( value ); - for ( i=0; - child && iNextSibling( value ), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::ChildElement( int count ) const -{ - if ( node ) - { - int i; - TiXmlElement* child = node->FirstChildElement(); - for ( i=0; - child && iNextSiblingElement(), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const -{ - if ( node ) - { - int i; - TiXmlElement* child = node->FirstChildElement( value ); - for ( i=0; - child && iNextSiblingElement( value ), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) -{ - return true; -} - -bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) -{ - return true; -} - -bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) -{ - DoIndent(); - buffer += "<"; - buffer += element.Value(); - - for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) - { - buffer += " "; - attrib->Print( 0, 0, &buffer ); - } - - if ( !element.FirstChild() ) - { - buffer += " />"; - DoLineBreak(); - } - else - { - buffer += ">"; - if ( element.FirstChild()->ToText() - && element.LastChild() == element.FirstChild() - && element.FirstChild()->ToText()->CDATA() == false ) - { - simpleTextPrint = true; - // no DoLineBreak()! - } - else - { - DoLineBreak(); - } - } - ++depth; - return true; -} - - -bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) -{ - --depth; - if ( !element.FirstChild() ) - { - // nothing. - } - else - { - if ( simpleTextPrint ) - { - simpleTextPrint = false; - } - else - { - DoIndent(); - } - buffer += ""; - DoLineBreak(); - } - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlText& text ) -{ - if ( text.CDATA() ) - { - DoIndent(); - buffer += ""; - DoLineBreak(); - } - else if ( simpleTextPrint ) - { - TIXML_STRING str; - TiXmlBase::EncodeString( text.ValueTStr(), &str ); - buffer += str; - } - else - { - DoIndent(); - TIXML_STRING str; - TiXmlBase::EncodeString( text.ValueTStr(), &str ); - buffer += str; - DoLineBreak(); - } - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) -{ - DoIndent(); - declaration.Print( 0, 0, &buffer ); - DoLineBreak(); - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlComment& comment ) -{ - DoIndent(); - buffer += ""; - DoLineBreak(); - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) -{ - DoIndent(); - buffer += "<"; - buffer += unknown.Value(); - buffer += ">"; - DoLineBreak(); - return true; -} - diff --git a/contrib/tinyxml-2.53/tinyxml.dsw b/contrib/tinyxml-2.53/tinyxml.dsw deleted file mode 100644 index d09d0eec7..000000000 --- a/contrib/tinyxml-2.53/tinyxml.dsw +++ /dev/null @@ -1,71 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "tinyXmlTest"=.\tinyXmlTest.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name tinyxml - End Project Dependency -}}} - -############################################################################### - -Project: "tinyXmlTestSTL"=.\tinyXmlTestSTL.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name tinyxmlSTL - End Project Dependency -}}} - -############################################################################### - -Project: "tinyxml"=.\tinyxml_lib.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "tinyxmlSTL"=.\tinyxmlSTL.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/contrib/tinyxml-2.53/tinyxml.h b/contrib/tinyxml-2.53/tinyxml.h deleted file mode 100644 index c6f40cc27..000000000 --- a/contrib/tinyxml-2.53/tinyxml.h +++ /dev/null @@ -1,1802 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) - -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. -*/ - - -#ifndef TINYXML_INCLUDED -#define TINYXML_INCLUDED - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4530 ) -#pragma warning( disable : 4786 ) -#endif - -#include -#include -#include -#include -#include - -// Help out windows: -#if defined( _DEBUG ) && !defined( DEBUG ) -#define DEBUG -#endif - -#ifdef TIXML_USE_STL - #include - #include - #include - #define TIXML_STRING std::string -#else - #include "tinystr.h" - #define TIXML_STRING TiXmlString -#endif - -// Deprecated library function hell. Compilers want to use the -// new safe versions. This probably doesn't fully address the problem, -// but it gets closer. There are too many compilers for me to fully -// test. If you get compilation troubles, undefine TIXML_SAFE -#define TIXML_SAFE - -#ifdef TIXML_SAFE - #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) - // Microsoft visual studio, version 2005 and higher. - #define TIXML_SNPRINTF _snprintf_s - #define TIXML_SNSCANF _snscanf_s - #define TIXML_SSCANF sscanf_s - #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) - // Microsoft visual studio, version 6 and higher. - //#pragma message( "Using _sn* functions." ) - #define TIXML_SNPRINTF _snprintf - #define TIXML_SNSCANF _snscanf - #define TIXML_SSCANF sscanf - #elif defined(__GNUC__) && (__GNUC__ >= 3 ) - // GCC version 3 and higher.s - //#warning( "Using sn* functions." ) - #define TIXML_SNPRINTF snprintf - #define TIXML_SNSCANF snscanf - #define TIXML_SSCANF sscanf - #else - #define TIXML_SSCANF sscanf - #endif -#endif - -class TiXmlDocument; -class TiXmlElement; -class TiXmlComment; -class TiXmlUnknown; -class TiXmlAttribute; -class TiXmlText; -class TiXmlDeclaration; -class TiXmlParsingData; - -const int TIXML_MAJOR_VERSION = 2; -const int TIXML_MINOR_VERSION = 5; -const int TIXML_PATCH_VERSION = 3; - -/* Internal structure for tracking location of items - in the XML file. -*/ -struct TiXmlCursor -{ - TiXmlCursor() { Clear(); } - void Clear() { row = col = -1; } - - int row; // 0 based. - int col; // 0 based. -}; - - -/** - If you call the Accept() method, it requires being passed a TiXmlVisitor - class to handle callbacks. For nodes that contain other nodes (Document, Element) - you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves - are simple called with Visit(). - - If you return 'true' from a Visit method, recursive parsing will continue. If you return - false, no children of this node or its sibilings will be Visited. - - All flavors of Visit methods have a default implementation that returns 'true' (continue - visiting). You need to only override methods that are interesting to you. - - Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. - - You should never change the document from a callback. - - @sa TiXmlNode::Accept() -*/ -class TiXmlVisitor -{ -public: - virtual ~TiXmlVisitor() {} - - /// Visit a document. - virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } - /// Visit a document. - virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } - - /// Visit an element. - virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } - /// Visit an element. - virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } - - /// Visit a declaration - virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } - /// Visit a text node - virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } - /// Visit a comment node - virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } - /// Visit an unknow node - virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } -}; - -// Only used by Attribute::Query functions -enum -{ - TIXML_SUCCESS, - TIXML_NO_ATTRIBUTE, - TIXML_WRONG_TYPE -}; - - -// Used by the parsing routines. -enum TiXmlEncoding -{ - TIXML_ENCODING_UNKNOWN, - TIXML_ENCODING_UTF8, - TIXML_ENCODING_LEGACY -}; - -const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; - -/** TiXmlBase is a base class for every class in TinyXml. - It does little except to establish that TinyXml classes - can be printed and provide some utility functions. - - In XML, the document and elements can contain - other elements and other types of nodes. - - @verbatim - A Document can contain: Element (container or leaf) - Comment (leaf) - Unknown (leaf) - Declaration( leaf ) - - An Element can contain: Element (container or leaf) - Text (leaf) - Attributes (not on tree) - Comment (leaf) - Unknown (leaf) - - A Decleration contains: Attributes (not on tree) - @endverbatim -*/ -class TiXmlBase -{ - friend class TiXmlNode; - friend class TiXmlElement; - friend class TiXmlDocument; - -public: - TiXmlBase() : userData(0) {} - virtual ~TiXmlBase() {} - - /** All TinyXml classes can print themselves to a filestream - or the string class (TiXmlString in non-STL mode, std::string - in STL mode.) Either or both cfile and str can be null. - - This is a formatted print, and will insert - tabs and newlines. - - (For an unformatted stream, use the << operator.) - */ - virtual void Print( FILE* cfile, int depth ) const = 0; - - /** The world does not agree on whether white space should be kept or - not. In order to make everyone happy, these global, static functions - are provided to set whether or not TinyXml will condense all white space - into a single space or not. The default is to condense. Note changing this - value is not thread safe. - */ - static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } - - /// Return the current white space setting. - static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } - - /** Return the position, in the original source file, of this node or attribute. - The row and column are 1-based. (That is the first row and first column is - 1,1). If the returns values are 0 or less, then the parser does not have - a row and column value. - - Generally, the row and column value will be set when the TiXmlDocument::Load(), - TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set - when the DOM was created from operator>>. - - The values reflect the initial load. Once the DOM is modified programmatically - (by adding or changing nodes and attributes) the new values will NOT update to - reflect changes in the document. - - There is a minor performance cost to computing the row and column. Computation - can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. - - @sa TiXmlDocument::SetTabSize() - */ - int Row() const { return location.row + 1; } - int Column() const { return location.col + 1; } ///< See Row() - - void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. - void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. - const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. - - // Table that returs, for a given lead byte, the total number of bytes - // in the UTF-8 sequence. - static const int utf8ByteTable[256]; - - virtual const char* Parse( const char* p, - TiXmlParsingData* data, - TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; - - /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, - or they will be transformed into entities! - */ - static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); - - enum - { - TIXML_NO_ERROR = 0, - TIXML_ERROR, - TIXML_ERROR_OPENING_FILE, - TIXML_ERROR_OUT_OF_MEMORY, - TIXML_ERROR_PARSING_ELEMENT, - TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, - TIXML_ERROR_READING_ELEMENT_VALUE, - TIXML_ERROR_READING_ATTRIBUTES, - TIXML_ERROR_PARSING_EMPTY, - TIXML_ERROR_READING_END_TAG, - TIXML_ERROR_PARSING_UNKNOWN, - TIXML_ERROR_PARSING_COMMENT, - TIXML_ERROR_PARSING_DECLARATION, - TIXML_ERROR_DOCUMENT_EMPTY, - TIXML_ERROR_EMBEDDED_NULL, - TIXML_ERROR_PARSING_CDATA, - TIXML_ERROR_DOCUMENT_TOP_ONLY, - - TIXML_ERROR_STRING_COUNT - }; - -protected: - - static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); - inline static bool IsWhiteSpace( char c ) - { - return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); - } - inline static bool IsWhiteSpace( int c ) - { - if ( c < 256 ) - return IsWhiteSpace( (char) c ); - return false; // Again, only truly correct for English/Latin...but usually works. - } - - #ifdef TIXML_USE_STL - static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); - static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); - #endif - - /* Reads an XML name into the string provided. Returns - a pointer just past the last character of the name, - or 0 if the function has an error. - */ - static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); - - /* Reads text. Returns a pointer past the given end tag. - Wickedly complex options, but it keeps the (sensitive) code in one place. - */ - static const char* ReadText( const char* in, // where to start - TIXML_STRING* text, // the string read - bool ignoreWhiteSpace, // whether to keep the white space - const char* endTag, // what ends this text - bool ignoreCase, // whether to ignore case in the end tag - TiXmlEncoding encoding ); // the current encoding - - // If an entity has been found, transform it into a character. - static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); - - // Get a character, while interpreting entities. - // The length can be from 0 to 4 bytes. - inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) - { - assert( p ); - if ( encoding == TIXML_ENCODING_UTF8 ) - { - *length = utf8ByteTable[ *((const unsigned char*)p) ]; - assert( *length >= 0 && *length < 5 ); - } - else - { - *length = 1; - } - - if ( *length == 1 ) - { - if ( *p == '&' ) - return GetEntity( p, _value, length, encoding ); - *_value = *p; - return p+1; - } - else if ( *length ) - { - //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), - // and the null terminator isn't needed - for( int i=0; p[i] && i<*length; ++i ) { - _value[i] = p[i]; - } - return p + (*length); - } - else - { - // Not valid text. - return 0; - } - } - - // Return true if the next characters in the stream are any of the endTag sequences. - // Ignore case only works for english, and should only be relied on when comparing - // to English words: StringEqual( p, "version", true ) is fine. - static bool StringEqual( const char* p, - const char* endTag, - bool ignoreCase, - TiXmlEncoding encoding ); - - static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; - - TiXmlCursor location; - - /// Field containing a generic user pointer - void* userData; - - // None of these methods are reliable for any language except English. - // Good for approximation, not great for accuracy. - static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); - static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); - inline static int ToLower( int v, TiXmlEncoding encoding ) - { - if ( encoding == TIXML_ENCODING_UTF8 ) - { - if ( v < 128 ) return tolower( v ); - return v; - } - else - { - return tolower( v ); - } - } - static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); - -private: - TiXmlBase( const TiXmlBase& ); // not implemented. - void operator=( const TiXmlBase& base ); // not allowed. - - struct Entity - { - const char* str; - unsigned int strLength; - char chr; - }; - enum - { - NUM_ENTITY = 5, - MAX_ENTITY_LENGTH = 6 - - }; - static Entity entity[ NUM_ENTITY ]; - static bool condenseWhiteSpace; -}; - - -/** The parent class for everything in the Document Object Model. - (Except for attributes). - Nodes have siblings, a parent, and children. A node can be - in a document, or stand on its own. The type of a TiXmlNode - can be queried, and it can be cast to its more defined type. -*/ -class TiXmlNode : public TiXmlBase -{ - friend class TiXmlDocument; - friend class TiXmlElement; - -public: - #ifdef TIXML_USE_STL - - /** An input stream operator, for every class. Tolerant of newlines and - formatting, but doesn't expect them. - */ - friend std::istream& operator >> (std::istream& in, TiXmlNode& base); - - /** An output stream operator, for every class. Note that this outputs - without any newlines or formatting, as opposed to Print(), which - includes tabs and new lines. - - The operator<< and operator>> are not completely symmetric. Writing - a node to a stream is very well defined. You'll get a nice stream - of output, without any extra whitespace or newlines. - - But reading is not as well defined. (As it always is.) If you create - a TiXmlElement (for example) and read that from an input stream, - the text needs to define an element or junk will result. This is - true of all input streams, but it's worth keeping in mind. - - A TiXmlDocument will read nodes until it reads a root element, and - all the children of that root element. - */ - friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); - - /// Appends the XML node or attribute to a std::string. - friend std::string& operator<< (std::string& out, const TiXmlNode& base ); - - #endif - - /** The types of XML nodes supported by TinyXml. (All the - unsupported types are picked up by UNKNOWN.) - */ - enum NodeType - { - DOCUMENT, - ELEMENT, - COMMENT, - UNKNOWN, - TEXT, - DECLARATION, - TYPECOUNT - }; - - virtual ~TiXmlNode(); - - /** The meaning of 'value' changes for the specific type of - TiXmlNode. - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - - The subclasses will wrap this function. - */ - const char *Value() const { return value.c_str (); } - - #ifdef TIXML_USE_STL - /** Return Value() as a std::string. If you only use STL, - this is more efficient than calling Value(). - Only available in STL mode. - */ - const std::string& ValueStr() const { return value; } - #endif - - const TIXML_STRING& ValueTStr() const { return value; } - - /** Changes the value of the node. Defined as: - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - */ - void SetValue(const char * _value) { value = _value;} - - #ifdef TIXML_USE_STL - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } - #endif - - /// Delete all the children of this node. Does not affect 'this'. - void Clear(); - - /// One step up the DOM. - TiXmlNode* Parent() { return parent; } - const TiXmlNode* Parent() const { return parent; } - - const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. - TiXmlNode* FirstChild() { return firstChild; } - const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. - /// The first child of this node with the matching 'value'. Will be null if none found. - TiXmlNode* FirstChild( const char * _value ) { - // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) - // call the method, cast the return back to non-const. - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); - } - const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. - TiXmlNode* LastChild() { return lastChild; } - - const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. - TiXmlNode* LastChild( const char * _value ) { - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. - #endif - - /** An alternate way to walk the children of a node. - One way to iterate over nodes is: - @verbatim - for( child = parent->FirstChild(); child; child = child->NextSibling() ) - @endverbatim - - IterateChildren does the same thing with the syntax: - @verbatim - child = 0; - while( child = parent->IterateChildren( child ) ) - @endverbatim - - IterateChildren takes the previous child as input and finds - the next one. If the previous child is null, it returns the - first. IterateChildren will return null when done. - */ - const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); - } - - /// This flavor of IterateChildren searches for children with a particular 'value' - const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - #endif - - /** Add a new node related to this. Adds a child past the LastChild. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); - - - /** Add a new node related to this. Adds a child past the LastChild. - - NOTE: the node to be added is passed by pointer, and will be - henceforth owned (and deleted) by tinyXml. This method is efficient - and avoids an extra copy, but should be used with care as it - uses a different memory model than the other insert functions. - - @sa InsertEndChild - */ - TiXmlNode* LinkEndChild( TiXmlNode* addThis ); - - /** Add a new node related to this. Adds a child before the specified child. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); - - /** Add a new node related to this. Adds a child after the specified child. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); - - /** Replace a child of this node. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); - - /// Delete a child of this node. - bool RemoveChild( TiXmlNode* removeThis ); - - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling() const { return prev; } - TiXmlNode* PreviousSibling() { return prev; } - - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling( const char * ) const; - TiXmlNode* PreviousSibling( const char *_prev ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. - #endif - - /// Navigate to a sibling node. - const TiXmlNode* NextSibling() const { return next; } - TiXmlNode* NextSibling() { return next; } - - /// Navigate to a sibling node with the given 'value'. - const TiXmlNode* NextSibling( const char * ) const; - TiXmlNode* NextSibling( const char* _next ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); - } - - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement() const; - TiXmlElement* NextSiblingElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); - } - - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement( const char * ) const; - TiXmlElement* NextSiblingElement( const char *_next ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - #endif - - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement() const; - TiXmlElement* FirstChildElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); - } - - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement( const char * _value ) const; - TiXmlElement* FirstChildElement( const char * _value ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - #endif - - /** Query the type (as an enumerated value, above) of this node. - The possible types are: DOCUMENT, ELEMENT, COMMENT, - UNKNOWN, TEXT, and DECLARATION. - */ - int Type() const { return type; } - - /** Return a pointer to the Document this node lives in. - Returns null if not in a document. - */ - const TiXmlDocument* GetDocument() const; - TiXmlDocument* GetDocument() { - return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); - } - - /// Returns true if this node has no children. - bool NoChildren() const { return !firstChild; } - - virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - - virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - - /** Create an exact duplicate of this node and return it. The memory must be deleted - by the caller. - */ - virtual TiXmlNode* Clone() const = 0; - - /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the - XML tree will be conditionally visited and the host will be called back - via the TiXmlVisitor interface. - - This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse - the XML for the callbacks, so the performance of TinyXML is unchanged by using this - interface versus any other.) - - The interface has been based on ideas from: - - - http://www.saxproject.org/ - - http://c2.com/cgi/wiki?HierarchicalVisitorPattern - - Which are both good references for "visiting". - - An example of using Accept(): - @verbatim - TiXmlPrinter printer; - tinyxmlDoc.Accept( &printer ); - const char* xmlcstr = printer.CStr(); - @endverbatim - */ - virtual bool Accept( TiXmlVisitor* visitor ) const = 0; - -protected: - TiXmlNode( NodeType _type ); - - // Copy to the allocated object. Shared functionality between Clone, Copy constructor, - // and the assignment operator. - void CopyTo( TiXmlNode* target ) const; - - #ifdef TIXML_USE_STL - // The real work of the input operator. - virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; - #endif - - // Figure out what is at *p, and parse it. Returns null if it is not an xml node. - TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); - - TiXmlNode* parent; - NodeType type; - - TiXmlNode* firstChild; - TiXmlNode* lastChild; - - TIXML_STRING value; - - TiXmlNode* prev; - TiXmlNode* next; - -private: - TiXmlNode( const TiXmlNode& ); // not implemented. - void operator=( const TiXmlNode& base ); // not allowed. -}; - - -/** An attribute is a name-value pair. Elements have an arbitrary - number of attributes, each with a unique name. - - @note The attributes are not TiXmlNodes, since they are not - part of the tinyXML document object model. There are other - suggested ways to look at this problem. -*/ -class TiXmlAttribute : public TiXmlBase -{ - friend class TiXmlAttributeSet; - -public: - /// Construct an empty attribute. - TiXmlAttribute() : TiXmlBase() - { - document = 0; - prev = next = 0; - } - - #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlAttribute( const std::string& _name, const std::string& _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } - #endif - - /// Construct an attribute with a name and value. - TiXmlAttribute( const char * _name, const char * _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } - - const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. - const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. - #ifdef TIXML_USE_STL - const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. - #endif - int IntValue() const; ///< Return the value of this attribute, converted to an integer. - double DoubleValue() const; ///< Return the value of this attribute, converted to a double. - - // Get the tinyxml string representation - const TIXML_STRING& NameTStr() const { return name; } - - /** QueryIntValue examines the value string. It is an alternative to the - IntValue() method with richer error checking. - If the value is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. - - A specialized but useful call. Note that for success it returns 0, - which is the opposite of almost all other TinyXml calls. - */ - int QueryIntValue( int* _value ) const; - /// QueryDoubleValue examines the value string. See QueryIntValue(). - int QueryDoubleValue( double* _value ) const; - - void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. - void SetValue( const char* _value ) { value = _value; } ///< Set the value. - - void SetIntValue( int _value ); ///< Set the value from an integer. - void SetDoubleValue( double _value ); ///< Set the value from a double. - - #ifdef TIXML_USE_STL - /// STL std::string form. - void SetName( const std::string& _name ) { name = _name; } - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } - #endif - - /// Get the next sibling attribute in the DOM. Returns null at end. - const TiXmlAttribute* Next() const; - TiXmlAttribute* Next() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); - } - - /// Get the previous sibling attribute in the DOM. Returns null at beginning. - const TiXmlAttribute* Previous() const; - TiXmlAttribute* Previous() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); - } - - bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } - bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } - bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } - - /* Attribute parsing starts: first letter of the name - returns: the next char after the value end quote - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - // Prints this Attribute to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } - void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - - // [internal use] - // Set the document pointer so the attribute can report errors. - void SetDocument( TiXmlDocument* doc ) { document = doc; } - -private: - TiXmlAttribute( const TiXmlAttribute& ); // not implemented. - void operator=( const TiXmlAttribute& base ); // not allowed. - - TiXmlDocument* document; // A pointer back to a document, for error reporting. - TIXML_STRING name; - TIXML_STRING value; - TiXmlAttribute* prev; - TiXmlAttribute* next; -}; - - -/* A class used to manage a group of attributes. - It is only used internally, both by the ELEMENT and the DECLARATION. - - The set can be changed transparent to the Element and Declaration - classes that use it, but NOT transparent to the Attribute - which has to implement a next() and previous() method. Which makes - it a bit problematic and prevents the use of STL. - - This version is implemented with circular lists because: - - I like circular lists - - it demonstrates some independence from the (typical) doubly linked list. -*/ -class TiXmlAttributeSet -{ -public: - TiXmlAttributeSet(); - ~TiXmlAttributeSet(); - - void Add( TiXmlAttribute* attribute ); - void Remove( TiXmlAttribute* attribute ); - - const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - - const TiXmlAttribute* Find( const char* _name ) const; - TiXmlAttribute* Find( const char* _name ) { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); - } - #ifdef TIXML_USE_STL - const TiXmlAttribute* Find( const std::string& _name ) const; - TiXmlAttribute* Find( const std::string& _name ) { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); - } - - #endif - -private: - //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), - //*ME: this class must be also use a hidden/disabled copy-constructor !!! - TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed - void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) - - TiXmlAttribute sentinel; -}; - - -/** The element is a container class. It has a value, the element name, - and can contain other elements, text, comments, and unknowns. - Elements also contain an arbitrary number of attributes. -*/ -class TiXmlElement : public TiXmlNode -{ -public: - /// Construct an element. - TiXmlElement (const char * in_value); - - #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlElement( const std::string& _value ); - #endif - - TiXmlElement( const TiXmlElement& ); - - void operator=( const TiXmlElement& base ); - - virtual ~TiXmlElement(); - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - */ - const char* Attribute( const char* name ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an integer, - the integer value will be put in the return 'i', if 'i' - is non-null. - */ - const char* Attribute( const char* name, int* i ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an double, - the double value will be put in the return 'd', if 'd' - is non-null. - */ - const char* Attribute( const char* name, double* d ) const; - - /** QueryIntAttribute examines the attribute - it is an alternative to the - Attribute() method with richer error checking. - If the attribute is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. If the attribute - does not exist, then TIXML_NO_ATTRIBUTE is returned. - */ - int QueryIntAttribute( const char* name, int* _value ) const; - /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). - int QueryDoubleAttribute( const char* name, double* _value ) const; - /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). - int QueryFloatAttribute( const char* name, float* _value ) const { - double d; - int result = QueryDoubleAttribute( name, &d ); - if ( result == TIXML_SUCCESS ) { - *_value = (float)d; - } - return result; - } - - #ifdef TIXML_USE_STL - /** Template form of the attribute query which will try to read the - attribute into the specified type. Very easy, very powerful, but - be careful to make sure to call this with the correct type. - - NOTE: This method doesn't work correctly for 'string' types. - - @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE - */ - template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - - std::stringstream sstream( node->ValueStr() ); - sstream >> *outValue; - if ( !sstream.fail() ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; - } - /* - This is - in theory - a bug fix for "QueryValueAtribute returns truncated std::string" - but template specialization is hard to get working cross-compiler. Leaving the bug for now. - - // The above will fail for std::string because the space character is used as a seperator. - // Specialize for strings. Bug [ 1695429 ] QueryValueAtribute returns truncated std::string - template<> int QueryValueAttribute( const std::string& name, std::string* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - *outValue = node->ValueStr(); - return TIXML_SUCCESS; - } - */ - #endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char* name, const char * _value ); - - #ifdef TIXML_USE_STL - const std::string* Attribute( const std::string& name ) const; - const std::string* Attribute( const std::string& name, int* i ) const; - const std::string* Attribute( const std::string& name, double* d ) const; - int QueryIntAttribute( const std::string& name, int* _value ) const; - int QueryDoubleAttribute( const std::string& name, double* _value ) const; - - /// STL std::string form. - void SetAttribute( const std::string& name, const std::string& _value ); - ///< STL std::string form. - void SetAttribute( const std::string& name, int _value ); - #endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char * name, int value ); - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetDoubleAttribute( const char * name, double value ); - - /** Deletes an attribute with the given name. - */ - void RemoveAttribute( const char * name ); - #ifdef TIXML_USE_STL - void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. - #endif - - const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. - TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } - const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. - TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } - - /** Convenience function for easy access to the text inside an element. Although easy - and concise, GetText() is limited compared to getting the TiXmlText child - and accessing it directly. - - If the first child of 'this' is a TiXmlText, the GetText() - returns the character string of the Text node, else null is returned. - - This is a convenient method for getting the text of simple contained text: - @verbatim - This is text - const char* str = fooElement->GetText(); - @endverbatim - - 'str' will be a pointer to "This is text". - - Note that this function can be misleading. If the element foo was created from - this XML: - @verbatim - This is text - @endverbatim - - then the value of str would be null. The first child node isn't a text node, it is - another element. From this XML: - @verbatim - This is text - @endverbatim - GetText() will return "This is ". - - WARNING: GetText() accesses a child node - don't become confused with the - similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are - safe type casts on the referenced node. - */ - const char* GetText() const; - - /// Creates a new Element and returns it - the returned element is a copy. - virtual TiXmlNode* Clone() const; - // Print the Element to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: next char past '<' - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - - void CopyTo( TiXmlElement* target ) const; - void ClearThis(); // like clear, but initializes 'this' object as well - - // Used to be public [internal use] - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - /* [internal use] - Reads the "value" of the element -- another element, or text. - This should terminate with the current end tag. - */ - const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - -private: - - TiXmlAttributeSet attributeSet; -}; - - -/** An XML comment. -*/ -class TiXmlComment : public TiXmlNode -{ -public: - /// Constructs an empty comment. - TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {} - /// Construct a comment from text. - TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::COMMENT ) { - SetValue( _value ); - } - TiXmlComment( const TiXmlComment& ); - void operator=( const TiXmlComment& base ); - - virtual ~TiXmlComment() {} - - /// Returns a copy of this Comment. - virtual TiXmlNode* Clone() const; - // Write this Comment to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: at the ! of the !-- - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - void CopyTo( TiXmlComment* target ) const; - - // used to be public - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif -// virtual void StreamOut( TIXML_OSTREAM * out ) const; - -private: - -}; - - -/** XML text. A text node can have 2 ways to output the next. "normal" output - and CDATA. It will default to the mode it was parsed from the XML file and - you generally want to leave it alone, but you can change the output mode with - SetCDATA() and query it with CDATA(). -*/ -class TiXmlText : public TiXmlNode -{ - friend class TiXmlElement; -public: - /** Constructor for text element. By default, it is treated as - normal, encoded text. If you want it be output as a CDATA text - element, set the parameter _cdata to 'true' - */ - TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TEXT) - { - SetValue( initValue ); - cdata = false; - } - virtual ~TiXmlText() {} - - #ifdef TIXML_USE_STL - /// Constructor. - TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT) - { - SetValue( initValue ); - cdata = false; - } - #endif - - TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT ) { copy.CopyTo( this ); } - void operator=( const TiXmlText& base ) { base.CopyTo( this ); } - - // Write this text object to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /// Queries whether this represents text using a CDATA section. - bool CDATA() const { return cdata; } - /// Turns on or off a CDATA representation of text. - void SetCDATA( bool _cdata ) { cdata = _cdata; } - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected : - /// [internal use] Creates a new Element and returns it. - virtual TiXmlNode* Clone() const; - void CopyTo( TiXmlText* target ) const; - - bool Blank() const; // returns true if all white space and new lines - // [internal use] - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - bool cdata; // true if this should be input and output as a CDATA style text element -}; - - -/** In correct XML the declaration is the first entry in the file. - @verbatim - - @endverbatim - - TinyXml will happily read or write files without a declaration, - however. There are 3 possible attributes to the declaration: - version, encoding, and standalone. - - Note: In this version of the code, the attributes are - handled as special cases, not generic attributes, simply - because there can only be at most 3 and they are always the same. -*/ -class TiXmlDeclaration : public TiXmlNode -{ -public: - /// Construct an empty declaration. - TiXmlDeclaration() : TiXmlNode( TiXmlNode::DECLARATION ) {} - -#ifdef TIXML_USE_STL - /// Constructor. - TiXmlDeclaration( const std::string& _version, - const std::string& _encoding, - const std::string& _standalone ); -#endif - - /// Construct. - TiXmlDeclaration( const char* _version, - const char* _encoding, - const char* _standalone ); - - TiXmlDeclaration( const TiXmlDeclaration& copy ); - void operator=( const TiXmlDeclaration& copy ); - - virtual ~TiXmlDeclaration() {} - - /// Version. Will return an empty string if none was found. - const char *Version() const { return version.c_str (); } - /// Encoding. Will return an empty string if none was found. - const char *Encoding() const { return encoding.c_str (); } - /// Is this a standalone document? - const char *Standalone() const { return standalone.c_str (); } - - /// Creates a copy of this Declaration and returns it. - virtual TiXmlNode* Clone() const; - // Print this declaration to a FILE stream. - virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - void CopyTo( TiXmlDeclaration* target ) const; - // used to be public - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - - TIXML_STRING version; - TIXML_STRING encoding; - TIXML_STRING standalone; -}; - - -/** Any tag that tinyXml doesn't recognize is saved as an - unknown. It is a tag of text, but should not be modified. - It will be written back to the XML, unchanged, when the file - is saved. - - DTD tags get thrown into TiXmlUnknowns. -*/ -class TiXmlUnknown : public TiXmlNode -{ -public: - TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {} - virtual ~TiXmlUnknown() {} - - TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN ) { copy.CopyTo( this ); } - void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } - - /// Creates a copy of this Unknown and returns it. - virtual TiXmlNode* Clone() const; - // Print this Unknown to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected: - void CopyTo( TiXmlUnknown* target ) const; - - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - -}; - - -/** Always the top level node. A document binds together all the - XML pieces. It can be saved, loaded, and printed to the screen. - The 'value' of a document node is the xml file name. -*/ -class TiXmlDocument : public TiXmlNode -{ -public: - /// Create an empty document, that has no name. - TiXmlDocument(); - /// Create a document with a name. The name of the document is also the filename of the xml. - TiXmlDocument( const char * documentName ); - - #ifdef TIXML_USE_STL - /// Constructor. - TiXmlDocument( const std::string& documentName ); - #endif - - TiXmlDocument( const TiXmlDocument& copy ); - void operator=( const TiXmlDocument& copy ); - - virtual ~TiXmlDocument() {} - - /** Load a file using the current document value. - Returns true if successful. Will delete any existing - document data before loading. - */ - bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the current document value. Returns true if successful. - bool SaveFile() const; - /// Load a file using the given filename. Returns true if successful. - bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given filename. Returns true if successful. - bool SaveFile( const char * filename ) const; - /** Load a file using the given FILE*. Returns true if successful. Note that this method - doesn't stream - the entire object pointed at by the FILE* - will be interpreted as an XML file. TinyXML doesn't stream in XML from the current - file location. Streaming may be added in the future. - */ - bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given FILE*. Returns true if successful. - bool SaveFile( FILE* ) const; - - #ifdef TIXML_USE_STL - bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. - { -// StringToBuffer f( filename ); -// return ( f.buffer && LoadFile( f.buffer, encoding )); - return LoadFile( filename.c_str(), encoding ); - } - bool SaveFile( const std::string& filename ) const ///< STL std::string version. - { -// StringToBuffer f( filename ); -// return ( f.buffer && SaveFile( f.buffer )); - return SaveFile( filename.c_str() ); - } - #endif - - /** Parse the given null terminated block of xml data. Passing in an encoding to this - method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml - to use that encoding, regardless of what TinyXml might otherwise try to detect. - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - - /** Get the root element -- the only top level element -- of the document. - In well formed XML, there should only be one. TinyXml is tolerant of - multiple elements at the document level. - */ - const TiXmlElement* RootElement() const { return FirstChildElement(); } - TiXmlElement* RootElement() { return FirstChildElement(); } - - /** If an error occurs, Error will be set to true. Also, - - The ErrorId() will contain the integer identifier of the error (not generally useful) - - The ErrorDesc() method will return the name of the error. (very useful) - - The ErrorRow() and ErrorCol() will return the location of the error (if known) - */ - bool Error() const { return error; } - - /// Contains a textual (english) description of the error if one occurs. - const char * ErrorDesc() const { return errorDesc.c_str (); } - - /** Generally, you probably want the error string ( ErrorDesc() ). But if you - prefer the ErrorId, this function will fetch it. - */ - int ErrorId() const { return errorId; } - - /** Returns the location (if known) of the error. The first column is column 1, - and the first row is row 1. A value of 0 means the row and column wasn't applicable - (memory errors, for example, have no row/column) or the parser lost the error. (An - error in the error reporting, in that case.) - - @sa SetTabSize, Row, Column - */ - int ErrorRow() const { return errorLocation.row+1; } - int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() - - /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) - to report the correct values for row and column. It does not change the output - or input in any way. - - By calling this method, with a tab size - greater than 0, the row and column of each node and attribute is stored - when the file is loaded. Very useful for tracking the DOM back in to - the source file. - - The tab size is required for calculating the location of nodes. If not - set, the default of 4 is used. The tabsize is set per document. Setting - the tabsize to 0 disables row/column tracking. - - Note that row and column tracking is not supported when using operator>>. - - The tab size needs to be enabled before the parse or load. Correct usage: - @verbatim - TiXmlDocument doc; - doc.SetTabSize( 8 ); - doc.Load( "myfile.xml" ); - @endverbatim - - @sa Row, Column - */ - void SetTabSize( int _tabsize ) { tabsize = _tabsize; } - - int TabSize() const { return tabsize; } - - /** If you have handled the error, it can be reset with this call. The error - state is automatically cleared if you Parse a new XML block. - */ - void ClearError() { error = false; - errorId = 0; - errorDesc = ""; - errorLocation.row = errorLocation.col = 0; - //errorLocation.last = 0; - } - - /** Write the document to standard out using formatted printing ("pretty print"). */ - void Print() const { Print( stdout, 0 ); } - - /* Write the document to a string using formatted printing ("pretty print"). This - will allocate a character array (new char[]) and return it as a pointer. The - calling code pust call delete[] on the return char* to avoid a memory leak. - */ - //char* PrintToMemory() const; - - /// Print this Document to a FILE stream. - virtual void Print( FILE* cfile, int depth = 0 ) const; - // [internal use] - void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - - virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected : - // [internal use] - virtual TiXmlNode* Clone() const; - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - void CopyTo( TiXmlDocument* target ) const; - - bool error; - int errorId; - TIXML_STRING errorDesc; - int tabsize; - TiXmlCursor errorLocation; - bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. -}; - - -/** - A TiXmlHandle is a class that wraps a node pointer with null checks; this is - an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml - DOM structure. It is a separate utility class. - - Take an example: - @verbatim - - - - - - - @endverbatim - - Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very - easy to write a *lot* of code that looks like: - - @verbatim - TiXmlElement* root = document.FirstChildElement( "Document" ); - if ( root ) - { - TiXmlElement* element = root->FirstChildElement( "Element" ); - if ( element ) - { - TiXmlElement* child = element->FirstChildElement( "Child" ); - if ( child ) - { - TiXmlElement* child2 = child->NextSiblingElement( "Child" ); - if ( child2 ) - { - // Finally do something useful. - @endverbatim - - And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity - of such code. A TiXmlHandle checks for null pointers so it is perfectly safe - and correct to use: - - @verbatim - TiXmlHandle docHandle( &document ); - TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); - if ( child2 ) - { - // do something useful - @endverbatim - - Which is MUCH more concise and useful. - - It is also safe to copy handles - internally they are nothing more than node pointers. - @verbatim - TiXmlHandle handleCopy = handle; - @endverbatim - - What they should not be used for is iteration: - - @verbatim - int i=0; - while ( true ) - { - TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); - if ( !child ) - break; - // do something - ++i; - } - @endverbatim - - It seems reasonable, but it is in fact two embedded while loops. The Child method is - a linear walk to find the element, so this code would iterate much more than it needs - to. Instead, prefer: - - @verbatim - TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); - - for( child; child; child=child->NextSiblingElement() ) - { - // do something - } - @endverbatim -*/ -class TiXmlHandle -{ -public: - /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. - TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } - /// Copy constructor - TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } - TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; } - - /// Return a handle to the first child node. - TiXmlHandle FirstChild() const; - /// Return a handle to the first child node with the given name. - TiXmlHandle FirstChild( const char * value ) const; - /// Return a handle to the first child element. - TiXmlHandle FirstChildElement() const; - /// Return a handle to the first child element with the given name. - TiXmlHandle FirstChildElement( const char * value ) const; - - /** Return a handle to the "index" child with the given name. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( const char* value, int index ) const; - /** Return a handle to the "index" child. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( int index ) const; - /** Return a handle to the "index" child element with the given name. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( const char* value, int index ) const; - /** Return a handle to the "index" child element. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( int index ) const; - - #ifdef TIXML_USE_STL - TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } - TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } - - TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } - TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } - #endif - - /** Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* ToNode() const { return node; } - /** Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } - /** Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } - /** Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } - - /** @deprecated use ToNode. - Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* Node() const { return ToNode(); } - /** @deprecated use ToElement. - Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* Element() const { return ToElement(); } - /** @deprecated use ToText() - Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* Text() const { return ToText(); } - /** @deprecated use ToUnknown() - Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* Unknown() const { return ToUnknown(); } - -private: - TiXmlNode* node; -}; - - -/** Print to memory functionality. The TiXmlPrinter is useful when you need to: - - -# Print to memory (especially in non-STL mode) - -# Control formatting (line endings, etc.) - - When constructed, the TiXmlPrinter is in its default "pretty printing" mode. - Before calling Accept() you can call methods to control the printing - of the XML document. After TiXmlNode::Accept() is called, the printed document can - be accessed via the CStr(), Str(), and Size() methods. - - TiXmlPrinter uses the Visitor API. - @verbatim - TiXmlPrinter printer; - printer.SetIndent( "\t" ); - - doc.Accept( &printer ); - fprintf( stdout, "%s", printer.CStr() ); - @endverbatim -*/ -class TiXmlPrinter : public TiXmlVisitor -{ -public: - TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), - buffer(), indent( " " ), lineBreak( "\n" ) {} - - virtual bool VisitEnter( const TiXmlDocument& doc ); - virtual bool VisitExit( const TiXmlDocument& doc ); - - virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); - virtual bool VisitExit( const TiXmlElement& element ); - - virtual bool Visit( const TiXmlDeclaration& declaration ); - virtual bool Visit( const TiXmlText& text ); - virtual bool Visit( const TiXmlComment& comment ); - virtual bool Visit( const TiXmlUnknown& unknown ); - - /** Set the indent characters for printing. By default 4 spaces - but tab (\t) is also useful, or null/empty string for no indentation. - */ - void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } - /// Query the indention string. - const char* Indent() { return indent.c_str(); } - /** Set the line breaking string. By default set to newline (\n). - Some operating systems prefer other characters, or can be - set to the null/empty string for no indenation. - */ - void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } - /// Query the current line breaking string. - const char* LineBreak() { return lineBreak.c_str(); } - - /** Switch over to "stream printing" which is the most dense formatting without - linebreaks. Common when the XML is needed for network transmission. - */ - void SetStreamPrinting() { indent = ""; - lineBreak = ""; - } - /// Return the result. - const char* CStr() { return buffer.c_str(); } - /// Return the length of the result string. - size_t Size() { return buffer.size(); } - - #ifdef TIXML_USE_STL - /// Return the result. - const std::string& Str() { return buffer; } - #endif - -private: - void DoIndent() { - for( int i=0; i -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Static Library" 0x0104 - -CFG=tinyxmlSTL - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "tinyxmlSTL.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "tinyxmlSTL.mak" CFG="tinyxmlSTL - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "tinyxmlSTL - Win32 Release" (based on "Win32 (x86) Static Library") -!MESSAGE "tinyxmlSTL - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "tinyxmlSTL - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "tinyxmlSTL___Win32_Release" -# PROP BASE Intermediate_Dir "tinyxmlSTL___Win32_Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release_STL" -# PROP Intermediate_Dir "Release_STL" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "TIXML_USE_STL" /FR /FD /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"Release_STL\tinyxml_STL.lib" - -!ELSEIF "$(CFG)" == "tinyxmlSTL - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "tinyxmlSTL___Win32_Debug0" -# PROP BASE Intermediate_Dir "tinyxmlSTL___Win32_Debug0" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug_STL" -# PROP Intermediate_Dir "Debug_STL" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "TIXML_USE_STL" /FR /FD /GZ /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"Debug_STL\tinyxmld_STL.lib" - -!ENDIF - -# Begin Target - -# Name "tinyxmlSTL - Win32 Release" -# Name "tinyxmlSTL - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\tinystr.cpp -# End Source File -# Begin Source File - -SOURCE=.\tinyxml.cpp -# End Source File -# Begin Source File - -SOURCE=.\tinyxmlerror.cpp -# End Source File -# Begin Source File - -SOURCE=.\tinyxmlparser.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\tinystr.h -# End Source File -# Begin Source File - -SOURCE=.\tinyxml.h -# End Source File -# End Group -# Begin Source File - -SOURCE=.\changes.txt -# End Source File -# Begin Source File - -SOURCE=.\readme.txt -# End Source File -# End Target -# End Project diff --git a/contrib/tinyxml-2.53/tinyxmlSTL.vcproj b/contrib/tinyxml-2.53/tinyxmlSTL.vcproj deleted file mode 100644 index e1e14a07b..000000000 --- a/contrib/tinyxml-2.53/tinyxmlSTL.vcproj +++ /dev/null @@ -1,278 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/contrib/tinyxml-2.53/tinyxml_lib.dsp b/contrib/tinyxml-2.53/tinyxml_lib.dsp deleted file mode 100644 index a0d29e18d..000000000 --- a/contrib/tinyxml-2.53/tinyxml_lib.dsp +++ /dev/null @@ -1,130 +0,0 @@ -# Microsoft Developer Studio Project File - Name="tinyxml" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Static Library" 0x0104 - -CFG=tinyxml - Win32 Release -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "tinyxml_lib.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "tinyxml_lib.mak" CFG="tinyxml - Win32 Release" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "tinyxml - Win32 Release" (based on "Win32 (x86) Static Library") -!MESSAGE "tinyxml - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "tinyxml - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x407 /d "NDEBUG" -# ADD RSC /l 0x407 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"Release\tinyxml.lib" - -!ELSEIF "$(CFG)" == "tinyxml - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /FD /GZ /c -# SUBTRACT CPP /YX -# ADD BASE RSC /l 0x407 /d "_DEBUG" -# ADD RSC /l 0x407 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"Debug\tinyxmld.lib" - -!ENDIF - -# Begin Target - -# Name "tinyxml - Win32 Release" -# Name "tinyxml - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\tinystr.cpp -# End Source File -# Begin Source File - -SOURCE=.\tinyxml.cpp -# End Source File -# Begin Source File - -SOURCE=.\tinyxmlerror.cpp -# End Source File -# Begin Source File - -SOURCE=.\tinyxmlparser.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=.\tinystr.h -# End Source File -# Begin Source File - -SOURCE=.\tinyxml.h -# End Source File -# End Group -# Begin Source File - -SOURCE=.\changes.txt -# End Source File -# Begin Source File - -SOURCE=.\readme.txt -# End Source File -# Begin Source File - -SOURCE=.\tutorial_gettingStarted.txt -# End Source File -# End Target -# End Project diff --git a/contrib/tinyxml-2.53/tinyxml_lib.vcproj b/contrib/tinyxml-2.53/tinyxml_lib.vcproj deleted file mode 100644 index ced31169e..000000000 --- a/contrib/tinyxml-2.53/tinyxml_lib.vcproj +++ /dev/null @@ -1,283 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/contrib/tinyxml-2.53/tinyxmlerror.cpp b/contrib/tinyxml-2.53/tinyxmlerror.cpp deleted file mode 100644 index d24f63b2e..000000000 --- a/contrib/tinyxml-2.53/tinyxmlerror.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) - -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. -*/ - -#include "tinyxml.h" - -// The goal of the seperate error file is to make the first -// step towards localization. tinyxml (currently) only supports -// english error messages, but the could now be translated. -// -// It also cleans up the code a bit. -// - -const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] = -{ - "No error", - "Error", - "Failed to open file", - "Memory allocation failed.", - "Error parsing Element.", - "Failed to read Element name", - "Error reading Element value.", - "Error reading Attributes.", - "Error: empty tag.", - "Error reading end tag.", - "Error parsing Unknown.", - "Error parsing Comment.", - "Error parsing Declaration.", - "Error document empty.", - "Error null (0) or unexpected EOF found in input stream.", - "Error parsing CDATA.", - "Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.", -}; diff --git a/contrib/tinyxml-2.53/tinyxmlparser.cpp b/contrib/tinyxml-2.53/tinyxmlparser.cpp deleted file mode 100644 index 9c91b4f94..000000000 --- a/contrib/tinyxml-2.53/tinyxmlparser.cpp +++ /dev/null @@ -1,1638 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com) - -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. -*/ - -#include -#include - -#include "tinyxml.h" - -//#define DEBUG_PARSER -#if defined( DEBUG_PARSER ) -# if defined( DEBUG ) && defined( _MSC_VER ) -# include -# define TIXML_LOG OutputDebugString -# else -# define TIXML_LOG printf -# endif -#endif - -// Note tha "PutString" hardcodes the same list. This -// is less flexible than it appears. Changing the entries -// or order will break putstring. -TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] = -{ - { "&", 5, '&' }, - { "<", 4, '<' }, - { ">", 4, '>' }, - { """, 6, '\"' }, - { "'", 6, '\'' } -}; - -// Bunch of unicode info at: -// http://www.unicode.org/faq/utf_bom.html -// Including the basic of this table, which determines the #bytes in the -// sequence from the lead byte. 1 placed for invalid sequences -- -// although the result will be junk, pass it through as much as possible. -// Beware of the non-characters in UTF-8: -// ef bb bf (Microsoft "lead bytes") -// ef bf be -// ef bf bf - -const unsigned char TIXML_UTF_LEAD_0 = 0xefU; -const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; -const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; - -const int TiXmlBase::utf8ByteTable[256] = -{ - // 0 1 2 3 4 5 6 7 8 9 a b c d e f - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 - 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte - 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid -}; - - -void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) -{ - const unsigned long BYTE_MASK = 0xBF; - const unsigned long BYTE_MARK = 0x80; - const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - - if (input < 0x80) - *length = 1; - else if ( input < 0x800 ) - *length = 2; - else if ( input < 0x10000 ) - *length = 3; - else if ( input < 0x200000 ) - *length = 4; - else - { *length = 0; return; } // This code won't covert this correctly anyway. - - output += *length; - - // Scary scary fall throughs. - switch (*length) - { - case 4: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 3: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 2: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 1: - --output; - *output = (char)(input | FIRST_BYTE_MARK[*length]); - } -} - - -/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) -{ - // This will only work for low-ascii, everything else is assumed to be a valid - // letter. I'm not sure this is the best approach, but it is quite tricky trying - // to figure out alhabetical vs. not across encoding. So take a very - // conservative approach. - -// if ( encoding == TIXML_ENCODING_UTF8 ) -// { - if ( anyByte < 127 ) - return isalpha( anyByte ); - else - return 1; // What else to do? The unicode set is huge...get the english ones right. -// } -// else -// { -// return isalpha( anyByte ); -// } -} - - -/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) -{ - // This will only work for low-ascii, everything else is assumed to be a valid - // letter. I'm not sure this is the best approach, but it is quite tricky trying - // to figure out alhabetical vs. not across encoding. So take a very - // conservative approach. - -// if ( encoding == TIXML_ENCODING_UTF8 ) -// { - if ( anyByte < 127 ) - return isalnum( anyByte ); - else - return 1; // What else to do? The unicode set is huge...get the english ones right. -// } -// else -// { -// return isalnum( anyByte ); -// } -} - - -class TiXmlParsingData -{ - friend class TiXmlDocument; - public: - void Stamp( const char* now, TiXmlEncoding encoding ); - - const TiXmlCursor& Cursor() { return cursor; } - - private: - // Only used by the document! - TiXmlParsingData( const char* start, int _tabsize, int row, int col ) - { - assert( start ); - stamp = start; - tabsize = _tabsize; - cursor.row = row; - cursor.col = col; - } - - TiXmlCursor cursor; - const char* stamp; - int tabsize; -}; - - -void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) -{ - assert( now ); - - // Do nothing if the tabsize is 0. - if ( tabsize < 1 ) - { - return; - } - - // Get the current row, column. - int row = cursor.row; - int col = cursor.col; - const char* p = stamp; - assert( p ); - - while ( p < now ) - { - // Treat p as unsigned, so we have a happy compiler. - const unsigned char* pU = (const unsigned char*)p; - - // Code contributed by Fletcher Dunn: (modified by lee) - switch (*pU) { - case 0: - // We *should* never get here, but in case we do, don't - // advance past the terminating null character, ever - return; - - case '\r': - // bump down to the next line - ++row; - col = 0; - // Eat the character - ++p; - - // Check for \r\n sequence, and treat this as a single character - if (*p == '\n') { - ++p; - } - break; - - case '\n': - // bump down to the next line - ++row; - col = 0; - - // Eat the character - ++p; - - // Check for \n\r sequence, and treat this as a single - // character. (Yes, this bizarre thing does occur still - // on some arcane platforms...) - if (*p == '\r') { - ++p; - } - break; - - case '\t': - // Eat the character - ++p; - - // Skip to next tab stop - col = (col / tabsize + 1) * tabsize; - break; - - case TIXML_UTF_LEAD_0: - if ( encoding == TIXML_ENCODING_UTF8 ) - { - if ( *(p+1) && *(p+2) ) - { - // In these cases, don't advance the column. These are - // 0-width spaces. - if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) - p += 3; - else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) - p += 3; - else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) - p += 3; - else - { p +=3; ++col; } // A normal character. - } - } - else - { - ++p; - ++col; - } - break; - - default: - if ( encoding == TIXML_ENCODING_UTF8 ) - { - // Eat the 1 to 4 byte utf8 character. - int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; - if ( step == 0 ) - step = 1; // Error case from bad encoding, but handle gracefully. - p += step; - - // Just advance one column, of course. - ++col; - } - else - { - ++p; - ++col; - } - break; - } - } - cursor.row = row; - cursor.col = col; - assert( cursor.row >= -1 ); - assert( cursor.col >= -1 ); - stamp = p; - assert( stamp ); -} - - -const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) -{ - if ( !p || !*p ) - { - return 0; - } - if ( encoding == TIXML_ENCODING_UTF8 ) - { - while ( *p ) - { - const unsigned char* pU = (const unsigned char*)p; - - // Skip the stupid Microsoft UTF-8 Byte order marks - if ( *(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==TIXML_UTF_LEAD_1 - && *(pU+2)==TIXML_UTF_LEAD_2 ) - { - p += 3; - continue; - } - else if(*(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==0xbfU - && *(pU+2)==0xbeU ) - { - p += 3; - continue; - } - else if(*(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==0xbfU - && *(pU+2)==0xbfU ) - { - p += 3; - continue; - } - - if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) // Still using old rules for white space. - ++p; - else - break; - } - } - else - { - while ( *p && IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) - ++p; - } - - return p; -} - -#ifdef TIXML_USE_STL -/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) -{ - for( ;; ) - { - if ( !in->good() ) return false; - - int c = in->peek(); - // At this scope, we can't get to a document. So fail silently. - if ( !IsWhiteSpace( c ) || c <= 0 ) - return true; - - *tag += (char) in->get(); - } -} - -/*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag ) -{ - //assert( character > 0 && character < 128 ); // else it won't work in utf-8 - while ( in->good() ) - { - int c = in->peek(); - if ( c == character ) - return true; - if ( c <= 0 ) // Silent failure: can't get document at this scope - return false; - - in->get(); - *tag += (char) c; - } - return false; -} -#endif - -// One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The -// "assign" optimization removes over 10% of the execution time. -// -const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) -{ - // Oddly, not supported on some comilers, - //name->clear(); - // So use this: - *name = ""; - assert( p ); - - // Names start with letters or underscores. - // Of course, in unicode, tinyxml has no idea what a letter *is*. The - // algorithm is generous. - // - // After that, they can be letters, underscores, numbers, - // hyphens, or colons. (Colons are valid ony for namespaces, - // but tinyxml can't tell namespaces from names.) - if ( p && *p - && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) - { - const char* start = p; - while( p && *p - && ( IsAlphaNum( (unsigned char ) *p, encoding ) - || *p == '_' - || *p == '-' - || *p == '.' - || *p == ':' ) ) - { - //(*name) += *p; // expensive - ++p; - } - if ( p-start > 0 ) { - name->assign( start, p-start ); - } - return p; - } - return 0; -} - -const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) -{ - // Presume an entity, and pull it out. - TIXML_STRING ent; - int i; - *length = 0; - - if ( *(p+1) && *(p+1) == '#' && *(p+2) ) - { - unsigned long ucs = 0; - ptrdiff_t delta = 0; - unsigned mult = 1; - - if ( *(p+2) == 'x' ) - { - // Hexadecimal. - if ( !*(p+3) ) return 0; - - const char* q = p+3; - q = strchr( q, ';' ); - - if ( !q || !*q ) return 0; - - delta = q-p; - --q; - - while ( *q != 'x' ) - { - if ( *q >= '0' && *q <= '9' ) - ucs += mult * (*q - '0'); - else if ( *q >= 'a' && *q <= 'f' ) - ucs += mult * (*q - 'a' + 10); - else if ( *q >= 'A' && *q <= 'F' ) - ucs += mult * (*q - 'A' + 10 ); - else - return 0; - mult *= 16; - --q; - } - } - else - { - // Decimal. - if ( !*(p+2) ) return 0; - - const char* q = p+2; - q = strchr( q, ';' ); - - if ( !q || !*q ) return 0; - - delta = q-p; - --q; - - while ( *q != '#' ) - { - if ( *q >= '0' && *q <= '9' ) - ucs += mult * (*q - '0'); - else - return 0; - mult *= 10; - --q; - } - } - if ( encoding == TIXML_ENCODING_UTF8 ) - { - // convert the UCS to UTF-8 - ConvertUTF32ToUTF8( ucs, value, length ); - } - else - { - *value = (char)ucs; - *length = 1; - } - return p + delta + 1; - } - - // Now try to match it. - for( i=0; iappend( cArr, len ); - } - } - else - { - bool whitespace = false; - - // Remove leading white space: - p = SkipWhiteSpace( p, encoding ); - while ( p && *p - && !StringEqual( p, endTag, caseInsensitive, encoding ) ) - { - if ( *p == '\r' || *p == '\n' ) - { - whitespace = true; - ++p; - } - else if ( IsWhiteSpace( *p ) ) - { - whitespace = true; - ++p; - } - else - { - // If we've found whitespace, add it before the - // new character. Any whitespace just becomes a space. - if ( whitespace ) - { - (*text) += ' '; - whitespace = false; - } - int len; - char cArr[4] = { 0, 0, 0, 0 }; - p = GetChar( p, cArr, &len, encoding ); - if ( len == 1 ) - (*text) += cArr[0]; // more efficient - else - text->append( cArr, len ); - } - } - } - if ( p ) - p += strlen( endTag ); - return p; -} - -#ifdef TIXML_USE_STL - -void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - // The basic issue with a document is that we don't know what we're - // streaming. Read something presumed to be a tag (and hope), then - // identify it, and call the appropriate stream method on the tag. - // - // This "pre-streaming" will never read the closing ">" so the - // sub-tag can orient itself. - - if ( !StreamTo( in, '<', tag ) ) - { - SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - - while ( in->good() ) - { - int tagIndex = (int) tag->length(); - while ( in->good() && in->peek() != '>' ) - { - int c = in->get(); - if ( c <= 0 ) - { - SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - break; - } - (*tag) += (char) c; - } - - if ( in->good() ) - { - // We now have something we presume to be a node of - // some sort. Identify it, and call the node to - // continue streaming. - TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); - - if ( node ) - { - node->StreamIn( in, tag ); - bool isElement = node->ToElement() != 0; - delete node; - node = 0; - - // If this is the root element, we're done. Parsing will be - // done by the >> operator. - if ( isElement ) - { - return; - } - } - else - { - SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - } - } - // We should have returned sooner. - SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); -} - -#endif - -const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) -{ - ClearError(); - - // Parse away, at the document level. Since a document - // contains nothing but other tags, most of what happens - // here is skipping white space. - if ( !p || !*p ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - // Note that, for a document, this needs to come - // before the while space skip, so that parsing - // starts from the pointer we are given. - location.Clear(); - if ( prevData ) - { - location.row = prevData->cursor.row; - location.col = prevData->cursor.col; - } - else - { - location.row = 0; - location.col = 0; - } - TiXmlParsingData data( p, TabSize(), location.row, location.col ); - location = data.Cursor(); - - if ( encoding == TIXML_ENCODING_UNKNOWN ) - { - // Check for the Microsoft UTF-8 lead bytes. - const unsigned char* pU = (const unsigned char*)p; - if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 - && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 - && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) - { - encoding = TIXML_ENCODING_UTF8; - useMicrosoftBOM = true; - } - } - - p = SkipWhiteSpace( p, encoding ); - if ( !p ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - while ( p && *p ) - { - TiXmlNode* node = Identify( p, encoding ); - if ( node ) - { - p = node->Parse( p, &data, encoding ); - LinkEndChild( node ); - } - else - { - break; - } - - // Did we get encoding info? - if ( encoding == TIXML_ENCODING_UNKNOWN - && node->ToDeclaration() ) - { - TiXmlDeclaration* dec = node->ToDeclaration(); - const char* enc = dec->Encoding(); - assert( enc ); - - if ( *enc == 0 ) - encoding = TIXML_ENCODING_UTF8; - else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) - encoding = TIXML_ENCODING_UTF8; - else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) - encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice - else - encoding = TIXML_ENCODING_LEGACY; - } - - p = SkipWhiteSpace( p, encoding ); - } - - // Was this empty? - if ( !firstChild ) { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); - return 0; - } - - // All is well. - return p; -} - -void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - // The first error in a chain is more accurate - don't set again! - if ( error ) - return; - - assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); - error = true; - errorId = err; - errorDesc = errorString[ errorId ]; - - errorLocation.Clear(); - if ( pError && data ) - { - data->Stamp( pError, encoding ); - errorLocation = data->Cursor(); - } -} - - -TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) -{ - TiXmlNode* returnNode = 0; - - p = SkipWhiteSpace( p, encoding ); - if( !p || !*p || *p != '<' ) - { - return 0; - } - - TiXmlDocument* doc = GetDocument(); - p = SkipWhiteSpace( p, encoding ); - - if ( !p || !*p ) - { - return 0; - } - - // What is this thing? - // - Elements start with a letter or underscore, but xml is reserved. - // - Comments: "; - - if ( !StringEqual( p, startTag, false, encoding ) ) - { - document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); - return 0; - } - p += strlen( startTag ); - - // [ 1475201 ] TinyXML parses entities in comments - // Oops - ReadText doesn't work, because we don't want to parse the entities. - // p = ReadText( p, &value, false, endTag, false, encoding ); - // - // from the XML spec: - /* - [Definition: Comments may appear anywhere in a document outside other markup; in addition, - they may appear within the document type declaration at places allowed by the grammar. - They are not part of the document's character data; an XML processor MAY, but need not, - make it possible for an application to retrieve the text of comments. For compatibility, - the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity - references MUST NOT be recognized within comments. - - An example of a comment: - - - */ - - value = ""; - // Keep all the white space. - while ( p && *p && !StringEqual( p, endTag, false, encoding ) ) - { - value.append( p, 1 ); - ++p; - } - if ( p ) - p += strlen( endTag ); - - return p; -} - - -const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p ) return 0; - -// int tabsize = 4; -// if ( document ) -// tabsize = document->TabSize(); - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - // Read the name, the '=' and the value. - const char* pErr = p; - p = ReadName( p, &name, encoding ); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); - return 0; - } - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p || *p != '=' ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - - ++p; // skip '=' - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - - const char* end; - const char SINGLE_QUOTE = '\''; - const char DOUBLE_QUOTE = '\"'; - - if ( *p == SINGLE_QUOTE ) - { - ++p; - end = "\'"; // single quote in string - p = ReadText( p, &value, false, end, false, encoding ); - } - else if ( *p == DOUBLE_QUOTE ) - { - ++p; - end = "\""; // double quote in string - p = ReadText( p, &value, false, end, false, encoding ); - } - else - { - // All attribute values should be in single or double quotes. - // But this is such a common error that the parser will try - // its best, even without them. - value = ""; - while ( p && *p // existence - && !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r' // whitespace - && *p != '/' && *p != '>' ) // tag end - { - if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { - // [ 1451649 ] Attribute values with trailing quotes not handled correctly - // We did not have an opening quote but seem to have a - // closing one. Give up and throw an error. - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - value += *p; - ++p; - } - } - return p; -} - -#ifdef TIXML_USE_STL -void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - while ( in->good() ) - { - int c = in->peek(); - if ( !cdata && (c == '<' ) ) - { - return; - } - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - - (*tag) += (char) c; - in->get(); // "commits" the peek made above - - if ( cdata && c == '>' && tag->size() >= 3 ) { - size_t len = tag->size(); - if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { - // terminator of cdata. - return; - } - } - } -} -#endif - -const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - value = ""; - TiXmlDocument* document = GetDocument(); - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - - const char* const startTag = ""; - - if ( cdata || StringEqual( p, startTag, false, encoding ) ) - { - cdata = true; - - if ( !StringEqual( p, startTag, false, encoding ) ) - { - document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); - return 0; - } - p += strlen( startTag ); - - // Keep all the white space, ignore the encoding, etc. - while ( p && *p - && !StringEqual( p, endTag, false, encoding ) - ) - { - value += *p; - ++p; - } - - TIXML_STRING dummy; - p = ReadText( p, &dummy, false, endTag, false, encoding ); - return p; - } - else - { - bool ignoreWhite = true; - - const char* end = "<"; - p = ReadText( p, &value, ignoreWhite, end, false, encoding ); - if ( p ) - return p-1; // don't truncate the '<' - return 0; - } -} - -#ifdef TIXML_USE_STL -void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - while ( in->good() ) - { - int c = in->get(); - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - (*tag) += (char) c; - - if ( c == '>' ) - { - // All is well. - return; - } - } -} -#endif - -const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) -{ - p = SkipWhiteSpace( p, _encoding ); - // Find the beginning, find the end, and look for - // the stuff in-between. - TiXmlDocument* document = GetDocument(); - if ( !p || !*p || !StringEqual( p, "SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); - return 0; - } - if ( data ) - { - data->Stamp( p, _encoding ); - location = data->Cursor(); - } - p += 5; - - version = ""; - encoding = ""; - standalone = ""; - - while ( p && *p ) - { - if ( *p == '>' ) - { - ++p; - return p; - } - - p = SkipWhiteSpace( p, _encoding ); - if ( StringEqual( p, "version", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - version = attrib.Value(); - } - else if ( StringEqual( p, "encoding", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - encoding = attrib.Value(); - } - else if ( StringEqual( p, "standalone", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - standalone = attrib.Value(); - } - else - { - // Read over whatever it is. - while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) - ++p; - } - } - return 0; -} - -bool TiXmlText::Blank() const -{ - for ( unsigned i=0; i - - The world has many languages - Мир имеет много языков - el mundo tiene muchos idiomas - 世界有很多语言 - <Русский название="name" ценность="value"><имеет> - <汉语 名字="name" 价值="value">世界有很多语言 - "Mëtæl!" - <ä>Umlaut Element - diff --git a/contrib/tinyxml-2.53/utf8testverify.xml b/contrib/tinyxml-2.53/utf8testverify.xml deleted file mode 100644 index 91a319df5..000000000 --- a/contrib/tinyxml-2.53/utf8testverify.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - The world has many languages - Мир имеет много языков - el mundo tiene muchos idiomas - 世界有很多语言 - <Русский название="name" ценность="value"><имеет> - <汉语 名字="name" 价值="value">世界有很多语言 - "Mëtæl!" - <ä>Umlaut Element - diff --git a/contrib/tinyxml-2.53/xmltest.cpp b/contrib/tinyxml-2.53/xmltest.cpp deleted file mode 100644 index 5ae3922c6..000000000 --- a/contrib/tinyxml-2.53/xmltest.cpp +++ /dev/null @@ -1,1294 +0,0 @@ -/* - Test program for TinyXML. -*/ - - -#ifdef TIXML_USE_STL - #include - #include - using namespace std; -#else - #include -#endif - -#if defined( WIN32 ) && defined( TUNE ) - #include - _CrtMemState startMemState; - _CrtMemState endMemState; -#endif - -#include "tinyxml.h" - -static int gPass = 0; -static int gFail = 0; - - -bool XmlTest (const char* testString, const char* expected, const char* found, bool noEcho = false) -{ - bool pass = !strcmp( expected, found ); - if ( pass ) - printf ("[pass]"); - else - printf ("[fail]"); - - if ( noEcho ) - printf (" %s\n", testString); - else - printf (" %s [%s][%s]\n", testString, expected, found); - - if ( pass ) - ++gPass; - else - ++gFail; - return pass; -} - - -bool XmlTest( const char* testString, int expected, int found, bool noEcho = false ) -{ - bool pass = ( expected == found ); - if ( pass ) - printf ("[pass]"); - else - printf ("[fail]"); - - if ( noEcho ) - printf (" %s\n", testString); - else - printf (" %s [%d][%d]\n", testString, expected, found); - - if ( pass ) - ++gPass; - else - ++gFail; - return pass; -} - - -// -// This file demonstrates some basic functionality of TinyXml. -// Note that the example is very contrived. It presumes you know -// what is in the XML file. But it does test the basic operations, -// and show how to add and remove nodes. -// - -int main() -{ - // - // We start with the 'demoStart' todo list. Process it. And - // should hopefully end up with the todo list as illustrated. - // - const char* demoStart = - "\n" - "" - "\n" - "\n" - " Go to the Toy store!" - " Do bills " - " Look for Evil Dinosaurs! " - ""; - - { - - #ifdef TIXML_USE_STL - /* What the todo list should look like after processing. - In stream (no formatting) representation. */ - const char* demoEnd = - "" - "" - "" - "" - "Go to the" - "Toy store!" - "" - "" - "Talk to:" - "" - "" - "" - "" - "" - "" - "Do bills" - "" - ""; - #endif - - // The example parses from the character string (above): - #if defined( WIN32 ) && defined( TUNE ) - _CrtMemCheckpoint( &startMemState ); - #endif - - { - // Write to a file and read it back, to check file I/O. - - TiXmlDocument doc( "demotest.xml" ); - doc.Parse( demoStart ); - - if ( doc.Error() ) - { - printf( "Error in %s: %s\n", doc.Value(), doc.ErrorDesc() ); - exit( 1 ); - } - doc.SaveFile(); - } - - TiXmlDocument doc( "demotest.xml" ); - bool loadOkay = doc.LoadFile(); - - if ( !loadOkay ) - { - printf( "Could not load test file 'demotest.xml'. Error='%s'. Exiting.\n", doc.ErrorDesc() ); - exit( 1 ); - } - - printf( "** Demo doc read from disk: ** \n\n" ); - printf( "** Printing via doc.Print **\n" ); - doc.Print( stdout ); - - { - printf( "** Printing via TiXmlPrinter **\n" ); - TiXmlPrinter printer; - doc.Accept( &printer ); - fprintf( stdout, "%s", printer.CStr() ); - } - #ifdef TIXML_USE_STL - { - printf( "** Printing via operator<< **\n" ); - std::cout << doc; - } - #endif - TiXmlNode* node = 0; - TiXmlElement* todoElement = 0; - TiXmlElement* itemElement = 0; - - - // -------------------------------------------------------- - // An example of changing existing attributes, and removing - // an element from the document. - // -------------------------------------------------------- - - // Get the "ToDo" element. - // It is a child of the document, and can be selected by name. - node = doc.FirstChild( "ToDo" ); - assert( node ); - todoElement = node->ToElement(); - assert( todoElement ); - - // Going to the toy store is now our second priority... - // So set the "priority" attribute of the first item in the list. - node = todoElement->FirstChildElement(); // This skips the "PDA" comment. - assert( node ); - itemElement = node->ToElement(); - assert( itemElement ); - itemElement->SetAttribute( "priority", 2 ); - - // Change the distance to "doing bills" from - // "none" to "here". It's the next sibling element. - itemElement = itemElement->NextSiblingElement(); - assert( itemElement ); - itemElement->SetAttribute( "distance", "here" ); - - // Remove the "Look for Evil Dinosaurs!" item. - // It is 1 more sibling away. We ask the parent to remove - // a particular child. - itemElement = itemElement->NextSiblingElement(); - todoElement->RemoveChild( itemElement ); - - itemElement = 0; - - // -------------------------------------------------------- - // What follows is an example of created elements and text - // nodes and adding them to the document. - // -------------------------------------------------------- - - // Add some meetings. - TiXmlElement item( "Item" ); - item.SetAttribute( "priority", "1" ); - item.SetAttribute( "distance", "far" ); - - TiXmlText text( "Talk to:" ); - - TiXmlElement meeting1( "Meeting" ); - meeting1.SetAttribute( "where", "School" ); - - TiXmlElement meeting2( "Meeting" ); - meeting2.SetAttribute( "where", "Lunch" ); - - TiXmlElement attendee1( "Attendee" ); - attendee1.SetAttribute( "name", "Marple" ); - attendee1.SetAttribute( "position", "teacher" ); - - TiXmlElement attendee2( "Attendee" ); - attendee2.SetAttribute( "name", "Voel" ); - attendee2.SetAttribute( "position", "counselor" ); - - // Assemble the nodes we've created: - meeting1.InsertEndChild( attendee1 ); - meeting1.InsertEndChild( attendee2 ); - - item.InsertEndChild( text ); - item.InsertEndChild( meeting1 ); - item.InsertEndChild( meeting2 ); - - // And add the node to the existing list after the first child. - node = todoElement->FirstChild( "Item" ); - assert( node ); - itemElement = node->ToElement(); - assert( itemElement ); - - todoElement->InsertAfterChild( itemElement, item ); - - printf( "\n** Demo doc processed: ** \n\n" ); - doc.Print( stdout ); - - - #ifdef TIXML_USE_STL - printf( "** Demo doc processed to stream: ** \n\n" ); - cout << doc << endl << endl; - #endif - - // -------------------------------------------------------- - // Different tests...do we have what we expect? - // -------------------------------------------------------- - - int count = 0; - TiXmlElement* element; - - ////////////////////////////////////////////////////// - - #ifdef TIXML_USE_STL - cout << "** Basic structure. **\n"; - ostringstream outputStream( ostringstream::out ); - outputStream << doc; - XmlTest( "Output stream correct.", string( demoEnd ).c_str(), - outputStream.str().c_str(), true ); - #endif - - node = doc.RootElement(); - assert( node ); - XmlTest( "Root element exists.", true, ( node != 0 && node->ToElement() ) ); - XmlTest ( "Root element value is 'ToDo'.", "ToDo", node->Value()); - - node = node->FirstChild(); - XmlTest( "First child exists & is a comment.", true, ( node != 0 && node->ToComment() ) ); - node = node->NextSibling(); - XmlTest( "Sibling element exists & is an element.", true, ( node != 0 && node->ToElement() ) ); - XmlTest ( "Value is 'Item'.", "Item", node->Value() ); - - node = node->FirstChild(); - XmlTest ( "First child exists.", true, ( node != 0 && node->ToText() ) ); - XmlTest ( "Value is 'Go to the'.", "Go to the", node->Value() ); - - - ////////////////////////////////////////////////////// - printf ("\n** Iterators. **\n"); - - // Walk all the top level nodes of the document. - count = 0; - for( node = doc.FirstChild(); - node; - node = node->NextSibling() ) - { - count++; - } - XmlTest( "Top level nodes, using First / Next.", 3, count ); - - count = 0; - for( node = doc.LastChild(); - node; - node = node->PreviousSibling() ) - { - count++; - } - XmlTest( "Top level nodes, using Last / Previous.", 3, count ); - - // Walk all the top level nodes of the document, - // using a different syntax. - count = 0; - for( node = doc.IterateChildren( 0 ); - node; - node = doc.IterateChildren( node ) ) - { - count++; - } - XmlTest( "Top level nodes, using IterateChildren.", 3, count ); - - // Walk all the elements in a node. - count = 0; - for( element = todoElement->FirstChildElement(); - element; - element = element->NextSiblingElement() ) - { - count++; - } - XmlTest( "Children of the 'ToDo' element, using First / Next.", - 3, count ); - - // Walk all the elements in a node by value. - count = 0; - for( node = todoElement->FirstChild( "Item" ); - node; - node = node->NextSibling( "Item" ) ) - { - count++; - } - XmlTest( "'Item' children of the 'ToDo' element, using First/Next.", 3, count ); - - count = 0; - for( node = todoElement->LastChild( "Item" ); - node; - node = node->PreviousSibling( "Item" ) ) - { - count++; - } - XmlTest( "'Item' children of the 'ToDo' element, using Last/Previous.", 3, count ); - - #ifdef TIXML_USE_STL - { - cout << "\n** Parsing. **\n"; - istringstream parse0( "" ); - TiXmlElement element0( "default" ); - parse0 >> element0; - - XmlTest ( "Element parsed, value is 'Element0'.", "Element0", element0.Value() ); - XmlTest ( "Reads attribute 'attribute0=\"foo0\"'.", "foo0", element0.Attribute( "attribute0" )); - XmlTest ( "Reads incorrectly formatted 'attribute1=noquotes'.", "noquotes", element0.Attribute( "attribute1" ) ); - XmlTest ( "Read attribute with entity value '>'.", ">", element0.Attribute( "attribute2" ) ); - } - #endif - - { - const char* error = "\n" - "\n" - " \n" - ""; - - TiXmlDocument docTest; - docTest.Parse( error ); - XmlTest( "Error row", docTest.ErrorRow(), 3 ); - XmlTest( "Error column", docTest.ErrorCol(), 17 ); - //printf( "error=%d id='%s' row %d col%d\n", (int) doc.Error(), doc.ErrorDesc(), doc.ErrorRow()+1, doc.ErrorCol() + 1 ); - - } - - #ifdef TIXML_USE_STL - { - ////////////////////////////////////////////////////// - cout << "\n** Streaming. **\n"; - - // Round trip check: stream in, then stream back out to verify. The stream - // out has already been checked, above. We use the output - - istringstream inputStringStream( outputStream.str() ); - TiXmlDocument document0; - - inputStringStream >> document0; - - ostringstream outputStream0( ostringstream::out ); - outputStream0 << document0; - - XmlTest( "Stream round trip correct.", string( demoEnd ).c_str(), - outputStream0.str().c_str(), true ); - - std::string str; - str << document0; - - XmlTest( "String printing correct.", string( demoEnd ).c_str(), - str.c_str(), true ); - } - #endif - } - - { - const char* str = ""; - - TiXmlDocument doc; - doc.Parse( str ); - - TiXmlElement* ele = doc.FirstChildElement(); - - int iVal, result; - double dVal; - - result = ele->QueryDoubleAttribute( "attr0", &dVal ); - XmlTest( "Query attribute: int as double", result, TIXML_SUCCESS ); - XmlTest( "Query attribute: int as double", (int)dVal, 1 ); - result = ele->QueryDoubleAttribute( "attr1", &dVal ); - XmlTest( "Query attribute: double as double", (int)dVal, 2 ); - result = ele->QueryIntAttribute( "attr1", &iVal ); - XmlTest( "Query attribute: double as int", result, TIXML_SUCCESS ); - XmlTest( "Query attribute: double as int", iVal, 2 ); - result = ele->QueryIntAttribute( "attr2", &iVal ); - XmlTest( "Query attribute: not a number", result, TIXML_WRONG_TYPE ); - result = ele->QueryIntAttribute( "bar", &iVal ); - XmlTest( "Query attribute: does not exist", result, TIXML_NO_ATTRIBUTE ); - } - - { - const char* str = "\t\t\n" - ""; - - TiXmlDocument doc; - doc.SetTabSize( 8 ); - doc.Parse( str ); - - TiXmlHandle docHandle( &doc ); - TiXmlHandle roomHandle = docHandle.FirstChildElement( "room" ); - - assert( docHandle.Node() ); - assert( roomHandle.Element() ); - - TiXmlElement* room = roomHandle.Element(); - assert( room ); - TiXmlAttribute* doors = room->FirstAttribute(); - assert( doors ); - - XmlTest( "Location tracking: Tab 8: room row", room->Row(), 1 ); - XmlTest( "Location tracking: Tab 8: room col", room->Column(), 49 ); - XmlTest( "Location tracking: Tab 8: doors row", doors->Row(), 1 ); - XmlTest( "Location tracking: Tab 8: doors col", doors->Column(), 55 ); - } - - { - const char* str = "\t\t\n" - " \n" - " A great door!\n" - "\t" - ""; - - TiXmlDocument doc; - doc.Parse( str ); - - TiXmlHandle docHandle( &doc ); - TiXmlHandle roomHandle = docHandle.FirstChildElement( "room" ); - TiXmlHandle commentHandle = docHandle.FirstChildElement( "room" ).FirstChild(); - TiXmlHandle textHandle = docHandle.FirstChildElement( "room" ).ChildElement( "door", 0 ).FirstChild(); - TiXmlHandle door0Handle = docHandle.FirstChildElement( "room" ).ChildElement( 0 ); - TiXmlHandle door1Handle = docHandle.FirstChildElement( "room" ).ChildElement( 1 ); - - assert( docHandle.Node() ); - assert( roomHandle.Element() ); - assert( commentHandle.Node() ); - assert( textHandle.Text() ); - assert( door0Handle.Element() ); - assert( door1Handle.Element() ); - - TiXmlDeclaration* declaration = doc.FirstChild()->ToDeclaration(); - assert( declaration ); - TiXmlElement* room = roomHandle.Element(); - assert( room ); - TiXmlAttribute* doors = room->FirstAttribute(); - assert( doors ); - TiXmlText* text = textHandle.Text(); - TiXmlComment* comment = commentHandle.Node()->ToComment(); - assert( comment ); - TiXmlElement* door0 = door0Handle.Element(); - TiXmlElement* door1 = door1Handle.Element(); - - XmlTest( "Location tracking: Declaration row", declaration->Row(), 1 ); - XmlTest( "Location tracking: Declaration col", declaration->Column(), 5 ); - XmlTest( "Location tracking: room row", room->Row(), 1 ); - XmlTest( "Location tracking: room col", room->Column(), 45 ); - XmlTest( "Location tracking: doors row", doors->Row(), 1 ); - XmlTest( "Location tracking: doors col", doors->Column(), 51 ); - XmlTest( "Location tracking: Comment row", comment->Row(), 2 ); - XmlTest( "Location tracking: Comment col", comment->Column(), 3 ); - XmlTest( "Location tracking: text row", text->Row(), 3 ); - XmlTest( "Location tracking: text col", text->Column(), 24 ); - XmlTest( "Location tracking: door0 row", door0->Row(), 3 ); - XmlTest( "Location tracking: door0 col", door0->Column(), 5 ); - XmlTest( "Location tracking: door1 row", door1->Row(), 4 ); - XmlTest( "Location tracking: door1 col", door1->Column(), 5 ); - } - - - // -------------------------------------------------------- - // UTF-8 testing. It is important to test: - // 1. Making sure name, value, and text read correctly - // 2. Row, Col functionality - // 3. Correct output - // -------------------------------------------------------- - printf ("\n** UTF-8 **\n"); - { - TiXmlDocument doc( "utf8test.xml" ); - doc.LoadFile(); - if ( doc.Error() && doc.ErrorId() == TiXmlBase::TIXML_ERROR_OPENING_FILE ) { - printf( "WARNING: File 'utf8test.xml' not found.\n" - "(Are you running the test from the wrong directory?)\n" - "Could not test UTF-8 functionality.\n" ); - } - else - { - TiXmlHandle docH( &doc ); - // Get the attribute "value" from the "Russian" element and check it. - TiXmlElement* element = docH.FirstChildElement( "document" ).FirstChildElement( "Russian" ).Element(); - const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU, - 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 }; - - XmlTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ), true ); - XmlTest( "UTF-8: Russian value row.", 4, element->Row() ); - XmlTest( "UTF-8: Russian value column.", 5, element->Column() ); - - const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U, - 0xd1U, 0x81U, 0xd1U, 0x81U, - 0xd0U, 0xbaU, 0xd0U, 0xb8U, - 0xd0U, 0xb9U, 0 }; - const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>"; - - TiXmlText* text = docH.FirstChildElement( "document" ).FirstChildElement( (const char*) russianElementName ).Child( 0 ).Text(); - XmlTest( "UTF-8: Browsing russian element name.", - russianText, - text->Value(), - true ); - XmlTest( "UTF-8: Russian element name row.", 7, text->Row() ); - XmlTest( "UTF-8: Russian element name column.", 47, text->Column() ); - - TiXmlDeclaration* dec = docH.Child( 0 ).Node()->ToDeclaration(); - XmlTest( "UTF-8: Declaration column.", 1, dec->Column() ); - XmlTest( "UTF-8: Document column.", 1, doc.Column() ); - - // Now try for a round trip. - doc.SaveFile( "utf8testout.xml" ); - - // Check the round trip. - char savedBuf[256]; - char verifyBuf[256]; - int okay = 1; - - FILE* saved = fopen( "utf8testout.xml", "r" ); - FILE* verify = fopen( "utf8testverify.xml", "r" ); - if ( saved && verify ) - { - while ( fgets( verifyBuf, 256, verify ) ) - { - fgets( savedBuf, 256, saved ); - if ( strcmp( verifyBuf, savedBuf ) ) - { - okay = 0; - break; - } - } - fclose( saved ); - fclose( verify ); - } - XmlTest( "UTF-8: Verified multi-language round trip.", 1, okay ); - - // On most Western machines, this is an element that contains - // the word "resume" with the correct accents, in a latin encoding. - // It will be something else completely on non-wester machines, - // which is why TinyXml is switching to UTF-8. - const char latin[] = "r\x82sum\x82"; - - TiXmlDocument latinDoc; - latinDoc.Parse( latin, 0, TIXML_ENCODING_LEGACY ); - - text = latinDoc.FirstChildElement()->FirstChild()->ToText(); - XmlTest( "Legacy encoding: Verify text element.", "r\x82sum\x82", text->Value() ); - } - } - - ////////////////////// - // Copy and assignment - ////////////////////// - printf ("\n** Copy and Assignment **\n"); - { - TiXmlElement element( "foo" ); - element.Parse( "", 0, TIXML_ENCODING_UNKNOWN ); - - TiXmlElement elementCopy( element ); - TiXmlElement elementAssign( "foo" ); - elementAssign.Parse( "", 0, TIXML_ENCODING_UNKNOWN ); - elementAssign = element; - - XmlTest( "Copy/Assign: element copy #1.", "element", elementCopy.Value() ); - XmlTest( "Copy/Assign: element copy #2.", "value", elementCopy.Attribute( "name" ) ); - XmlTest( "Copy/Assign: element assign #1.", "element", elementAssign.Value() ); - XmlTest( "Copy/Assign: element assign #2.", "value", elementAssign.Attribute( "name" ) ); - XmlTest( "Copy/Assign: element assign #3.", true, ( 0 == elementAssign.Attribute( "foo" )) ); - - TiXmlComment comment; - comment.Parse( "", 0, TIXML_ENCODING_UNKNOWN ); - TiXmlComment commentCopy( comment ); - TiXmlComment commentAssign; - commentAssign = commentCopy; - XmlTest( "Copy/Assign: comment copy.", "comment", commentCopy.Value() ); - XmlTest( "Copy/Assign: comment assign.", "comment", commentAssign.Value() ); - - TiXmlUnknown unknown; - unknown.Parse( "<[unknown]>", 0, TIXML_ENCODING_UNKNOWN ); - TiXmlUnknown unknownCopy( unknown ); - TiXmlUnknown unknownAssign; - unknownAssign.Parse( "incorrect", 0, TIXML_ENCODING_UNKNOWN ); - unknownAssign = unknownCopy; - XmlTest( "Copy/Assign: unknown copy.", "[unknown]", unknownCopy.Value() ); - XmlTest( "Copy/Assign: unknown assign.", "[unknown]", unknownAssign.Value() ); - - TiXmlText text( "TextNode" ); - TiXmlText textCopy( text ); - TiXmlText textAssign( "incorrect" ); - textAssign = text; - XmlTest( "Copy/Assign: text copy.", "TextNode", textCopy.Value() ); - XmlTest( "Copy/Assign: text assign.", "TextNode", textAssign.Value() ); - - TiXmlDeclaration dec; - dec.Parse( "", 0, TIXML_ENCODING_UNKNOWN ); - TiXmlDeclaration decCopy( dec ); - TiXmlDeclaration decAssign; - decAssign = dec; - - XmlTest( "Copy/Assign: declaration copy.", "UTF-8", decCopy.Encoding() ); - XmlTest( "Copy/Assign: text assign.", "UTF-8", decAssign.Encoding() ); - - TiXmlDocument doc; - elementCopy.InsertEndChild( textCopy ); - doc.InsertEndChild( decAssign ); - doc.InsertEndChild( elementCopy ); - doc.InsertEndChild( unknownAssign ); - - TiXmlDocument docCopy( doc ); - TiXmlDocument docAssign; - docAssign = docCopy; - - #ifdef TIXML_USE_STL - std::string original, copy, assign; - original << doc; - copy << docCopy; - assign << docAssign; - XmlTest( "Copy/Assign: document copy.", original.c_str(), copy.c_str(), true ); - XmlTest( "Copy/Assign: document assign.", original.c_str(), assign.c_str(), true ); - - #endif - } - - ////////////////////////////////////////////////////// -#ifdef TIXML_USE_STL - printf ("\n** Parsing, no Condense Whitespace **\n"); - TiXmlBase::SetCondenseWhiteSpace( false ); - { - istringstream parse1( "This is \ntext" ); - TiXmlElement text1( "text" ); - parse1 >> text1; - - XmlTest ( "Condense white space OFF.", "This is \ntext", - text1.FirstChild()->Value(), - true ); - } - TiXmlBase::SetCondenseWhiteSpace( true ); -#endif - - ////////////////////////////////////////////////////// - // GetText(); - { - const char* str = "This is text"; - TiXmlDocument doc; - doc.Parse( str ); - const TiXmlElement* element = doc.RootElement(); - - XmlTest( "GetText() normal use.", "This is text", element->GetText() ); - - str = "This is text"; - doc.Clear(); - doc.Parse( str ); - element = doc.RootElement(); - - XmlTest( "GetText() contained element.", element->GetText() == 0, true ); - - str = "This is text"; - doc.Clear(); - TiXmlBase::SetCondenseWhiteSpace( false ); - doc.Parse( str ); - TiXmlBase::SetCondenseWhiteSpace( true ); - element = doc.RootElement(); - - XmlTest( "GetText() partial.", "This is ", element->GetText() ); - } - - - ////////////////////////////////////////////////////// - // CDATA - { - const char* str = "" - " the rules!\n" - "...since I make symbolic puns" - "]]>" - ""; - TiXmlDocument doc; - doc.Parse( str ); - doc.Print(); - - XmlTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(), - "I am > the rules!\n...since I make symbolic puns", - true ); - - #ifdef TIXML_USE_STL - //cout << doc << '\n'; - - doc.Clear(); - - istringstream parse0( str ); - parse0 >> doc; - //cout << doc << '\n'; - - XmlTest( "CDATA stream.", doc.FirstChildElement()->FirstChild()->Value(), - "I am > the rules!\n...since I make symbolic puns", - true ); - #endif - - TiXmlDocument doc1 = doc; - //doc.Print(); - - XmlTest( "CDATA copy.", doc1.FirstChildElement()->FirstChild()->Value(), - "I am > the rules!\n...since I make symbolic puns", - true ); - } - { - // [ 1482728 ] Wrong wide char parsing - char buf[256]; - buf[255] = 0; - for( int i=0; i<255; ++i ) { - buf[i] = (char)((i>=32) ? i : 32); - } - TIXML_STRING str( ""; - - TiXmlDocument doc; - doc.Parse( str.c_str() ); - - TiXmlPrinter printer; - printer.SetStreamPrinting(); - doc.Accept( &printer ); - - XmlTest( "CDATA with all bytes #1.", str.c_str(), printer.CStr(), true ); - - #ifdef TIXML_USE_STL - doc.Clear(); - istringstream iss( printer.Str() ); - iss >> doc; - std::string out; - out << doc; - XmlTest( "CDATA with all bytes #2.", out.c_str(), printer.CStr(), true ); - #endif - } - { - // [ 1480107 ] Bug-fix for STL-streaming of CDATA that contains tags - // CDATA streaming had a couple of bugs, that this tests for. - const char* str = "" - "I am > the rules!\n" - "...since I make symbolic puns" - "]]>" - ""; - TiXmlDocument doc; - doc.Parse( str ); - doc.Print(); - - XmlTest( "CDATA parse. [ 1480107 ]", doc.FirstChildElement()->FirstChild()->Value(), - "I am > the rules!\n...since I make symbolic puns", - true ); - - #ifdef TIXML_USE_STL - - doc.Clear(); - - istringstream parse0( str ); - parse0 >> doc; - - XmlTest( "CDATA stream. [ 1480107 ]", doc.FirstChildElement()->FirstChild()->Value(), - "I am > the rules!\n...since I make symbolic puns", - true ); - #endif - - TiXmlDocument doc1 = doc; - //doc.Print(); - - XmlTest( "CDATA copy. [ 1480107 ]", doc1.FirstChildElement()->FirstChild()->Value(), - "I am > the rules!\n...since I make symbolic puns", - true ); - } - ////////////////////////////////////////////////////// - // Visit() - - - - ////////////////////////////////////////////////////// - printf( "\n** Fuzzing... **\n" ); - - const int FUZZ_ITERATION = 300; - - // The only goal is not to crash on bad input. - int len = (int) strlen( demoStart ); - for( int i=0; i" - "" - " " - ""; - - TiXmlDocument doc( "passages.xml" ); - doc.Parse( passages ); - TiXmlElement* psg = doc.RootElement()->FirstChildElement(); - const char* context = psg->Attribute( "context" ); - const char* expected = "Line 5 has \"quotation marks\" and 'apostrophe marks'. It also has <, >, and &, as well as a fake copyright \xC2\xA9."; - - XmlTest( "Entity transformation: read. ", expected, context, true ); - - FILE* textfile = fopen( "textfile.txt", "w" ); - if ( textfile ) - { - psg->Print( textfile, 0 ); - fclose( textfile ); - } - textfile = fopen( "textfile.txt", "r" ); - assert( textfile ); - if ( textfile ) - { - char buf[ 1024 ]; - fgets( buf, 1024, textfile ); - XmlTest( "Entity transformation: write. ", - "", - buf, - true ); - } - fclose( textfile ); - } - - { - FILE* textfile = fopen( "test5.xml", "w" ); - if ( textfile ) - { - fputs("", textfile); - fclose(textfile); - - TiXmlDocument doc; - doc.LoadFile( "test5.xml" ); - XmlTest( "dot in element attributes and names", doc.Error(), 0); - } - } - - { - FILE* textfile = fopen( "test6.xml", "w" ); - if ( textfile ) - { - fputs("1.1 Start easy ignore fin thickness ", textfile ); - fclose(textfile); - - TiXmlDocument doc; - bool result = doc.LoadFile( "test6.xml" ); - XmlTest( "Entity with one digit.", result, true ); - - TiXmlText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText(); - XmlTest( "Entity with one digit.", - text->Value(), "1.1 Start easy ignore fin thickness\n" ); - } - } - - { - // DOCTYPE not preserved (950171) - // - const char* doctype = - "" - "" - "" - "" - ""; - - TiXmlDocument doc; - doc.Parse( doctype ); - doc.SaveFile( "test7.xml" ); - doc.Clear(); - doc.LoadFile( "test7.xml" ); - - TiXmlHandle docH( &doc ); - TiXmlUnknown* unknown = docH.Child( 1 ).Unknown(); - XmlTest( "Correct value of unknown.", "!DOCTYPE PLAY SYSTEM 'play.dtd'", unknown->Value() ); - #ifdef TIXML_USE_STL - TiXmlNode* node = docH.Child( 2 ).Node(); - std::string str; - str << (*node); - XmlTest( "Correct streaming of unknown.", "", str.c_str() ); - #endif - } - - { - // [ 791411 ] Formatting bug - // Comments do not stream out correctly. - const char* doctype = - ""; - TiXmlDocument doc; - doc.Parse( doctype ); - - TiXmlHandle docH( &doc ); - TiXmlComment* comment = docH.Child( 0 ).Node()->ToComment(); - - XmlTest( "Comment formatting.", " Somewhat ", comment->Value() ); - #ifdef TIXML_USE_STL - std::string str; - str << (*comment); - XmlTest( "Comment streaming.", "", str.c_str() ); - #endif - } - - { - // [ 870502 ] White space issues - TiXmlDocument doc; - TiXmlText* text; - TiXmlHandle docH( &doc ); - - const char* doctype0 = " This has leading and trailing space "; - const char* doctype1 = "This has internal space"; - const char* doctype2 = " This has leading, trailing, and internal space "; - - TiXmlBase::SetCondenseWhiteSpace( false ); - doc.Clear(); - doc.Parse( doctype0 ); - text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); - XmlTest( "White space kept.", " This has leading and trailing space ", text->Value() ); - - doc.Clear(); - doc.Parse( doctype1 ); - text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); - XmlTest( "White space kept.", "This has internal space", text->Value() ); - - doc.Clear(); - doc.Parse( doctype2 ); - text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); - XmlTest( "White space kept.", " This has leading, trailing, and internal space ", text->Value() ); - - TiXmlBase::SetCondenseWhiteSpace( true ); - doc.Clear(); - doc.Parse( doctype0 ); - text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); - XmlTest( "White space condensed.", "This has leading and trailing space", text->Value() ); - - doc.Clear(); - doc.Parse( doctype1 ); - text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); - XmlTest( "White space condensed.", "This has internal space", text->Value() ); - - doc.Clear(); - doc.Parse( doctype2 ); - text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); - XmlTest( "White space condensed.", "This has leading, trailing, and internal space", text->Value() ); - } - - { - // Double attributes - const char* doctype = ""; - - TiXmlDocument doc; - doc.Parse( doctype ); - - XmlTest( "Parsing repeated attributes.", 0, (int)doc.Error() ); // not an error to tinyxml - XmlTest( "Parsing repeated attributes.", "blue", doc.FirstChildElement( "element" )->Attribute( "attr" ) ); - } - - { - // Embedded null in stream. - const char* doctype = ""; - - TiXmlDocument doc; - doc.Parse( doctype ); - XmlTest( "Embedded null throws error.", true, doc.Error() ); - - #ifdef TIXML_USE_STL - istringstream strm( doctype ); - doc.Clear(); - doc.ClearError(); - strm >> doc; - XmlTest( "Embedded null throws error.", true, doc.Error() ); - #endif - } - - { - // Legacy mode test. (This test may only pass on a western system) - const char* str = - "" - "<>" - "Cntnt" - ""; - - TiXmlDocument doc; - doc.Parse( str ); - - TiXmlHandle docHandle( &doc ); - TiXmlHandle aHandle = docHandle.FirstChildElement( "" ); - TiXmlHandle tHandle = aHandle.Child( 0 ); - assert( aHandle.Element() ); - assert( tHandle.Text() ); - XmlTest( "ISO-8859-1 Parsing.", "Cntnt", tHandle.Text()->Value() ); - } - - { - // Empty documents should return TIXML_ERROR_PARSING_EMPTY, bug 1070717 - const char* str = " "; - TiXmlDocument doc; - doc.Parse( str ); - XmlTest( "Empty document error TIXML_ERROR_DOCUMENT_EMPTY", TiXmlBase::TIXML_ERROR_DOCUMENT_EMPTY, doc.ErrorId() ); - } - #ifndef TIXML_USE_STL - { - // String equality. [ 1006409 ] string operator==/!= no worky in all cases - TiXmlString temp; - XmlTest( "Empty tinyxml string compare equal", ( temp == "" ), true ); - - TiXmlString foo; - TiXmlString bar( "" ); - XmlTest( "Empty tinyxml string compare equal", ( foo == bar ), true ); - } - - #endif - { - // Bug [ 1195696 ] from marlonism - TiXmlBase::SetCondenseWhiteSpace(false); - TiXmlDocument xml; - xml.Parse("This hangs"); - XmlTest( "Test safe error return.", xml.Error(), false ); - } - - { - // Bug [ 1243992 ] - another infinite loop - TiXmlDocument doc; - doc.SetCondenseWhiteSpace(false); - doc.Parse("

test

"); - } - { - // Low entities - TiXmlDocument xml; - xml.Parse( "" ); - const char result[] = { 0x0e, 0 }; - XmlTest( "Low entities.", xml.FirstChildElement()->GetText(), result ); - xml.Print(); - } - { - // Bug [ 1451649 ] Attribute values with trailing quotes not handled correctly - TiXmlDocument xml; - xml.Parse( "" ); - XmlTest( "Throw error with bad end quotes.", xml.Error(), true ); - } - #ifdef TIXML_USE_STL - { - // Bug [ 1449463 ] Consider generic query - TiXmlDocument xml; - xml.Parse( "" ); - - TiXmlElement* ele = xml.FirstChildElement(); - double d; - int i; - float f; - bool b; - //std::string str; - - XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &d ), TIXML_SUCCESS ); - XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &i ), TIXML_SUCCESS ); - XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &f ), TIXML_SUCCESS ); - XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &b ), TIXML_WRONG_TYPE ); - XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "nobar", &b ), TIXML_NO_ATTRIBUTE ); - //XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "barStr", &str ), TIXML_SUCCESS ); - - XmlTest( "QueryValueAttribute", (d==3.0), true ); - XmlTest( "QueryValueAttribute", (i==3), true ); - XmlTest( "QueryValueAttribute", (f==3.0f), true ); - //XmlTest( "QueryValueAttribute", (str==std::string( "a string" )), true ); - } - #endif - - #ifdef TIXML_USE_STL - { - // [ 1505267 ] redundant malloc in TiXmlElement::Attribute - TiXmlDocument xml; - xml.Parse( "" ); - TiXmlElement* ele = xml.FirstChildElement(); - double d; - int i; - - std::string bar = "bar"; - - const std::string* atrrib = ele->Attribute( bar ); - ele->Attribute( bar, &d ); - ele->Attribute( bar, &i ); - - XmlTest( "Attribute", atrrib->empty(), false ); - XmlTest( "Attribute", (d==3.0), true ); - XmlTest( "Attribute", (i==3), true ); - } - #endif - - { - // [ 1356059 ] Allow TiXMLDocument to only be at the top level - TiXmlDocument xml, xml2; - xml.InsertEndChild( xml2 ); - XmlTest( "Document only at top level.", xml.Error(), true ); - XmlTest( "Document only at top level.", xml.ErrorId(), TiXmlBase::TIXML_ERROR_DOCUMENT_TOP_ONLY ); - } - - { - // [ 1663758 ] Failure to report error on bad XML - TiXmlDocument xml; - xml.Parse(""); - XmlTest("Missing end tag at end of input", xml.Error(), true); - xml.Parse(" "); - XmlTest("Missing end tag with trailing whitespace", xml.Error(), true); - } - - { - // [ 1635701 ] fail to parse files with a tag separated into two lines - // I'm not sure this is a bug. Marked 'pending' for feedback. - TiXmlDocument xml; - xml.Parse( "<p>text</p\n><title>" ); - //xml.Print(); - //XmlTest( "Tag split by newline", xml.Error(), false ); - } - - #ifdef TIXML_USE_STL - { - // [ 1475201 ] TinyXML parses entities in comments - TiXmlDocument xml; - istringstream parse1( "<!-- declarations for <head> & <body> -->" - "<!-- far & away -->" ); - parse1 >> xml; - - TiXmlNode* e0 = xml.FirstChild(); - TiXmlNode* e1 = e0->NextSibling(); - TiXmlComment* c0 = e0->ToComment(); - TiXmlComment* c1 = e1->ToComment(); - - XmlTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true ); - XmlTest( "Comments ignore entities.", " far & away ", c1->Value(), true ); - } - #endif - - { - // [ 1475201 ] TinyXML parses entities in comments - TiXmlDocument xml; - xml.Parse("<!-- declarations for <head> & <body> -->" - "<!-- far & away -->" ); - - TiXmlNode* e0 = xml.FirstChild(); - TiXmlNode* e1 = e0->NextSibling(); - TiXmlComment* c0 = e0->ToComment(); - TiXmlComment* c1 = e1->ToComment(); - - XmlTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true ); - XmlTest( "Comments ignore entities.", " far & away ", c1->Value(), true ); - } - /* - { - TiXmlDocument xml; - xml.Parse( "<tag>/</tag>" ); - xml.Print(); - xml.FirstChild()->Print( stdout, 0 ); - xml.FirstChild()->Type(); - } - */ - - /* 1417717 experiment - { - TiXmlDocument xml; - xml.Parse("<text>Dan & Tracie</text>"); - xml.Print(stdout); - } - { - TiXmlDocument xml; - xml.Parse("<text>Dan &foo; Tracie</text>"); - xml.Print(stdout); - } - */ - #if defined( WIN32 ) && defined( TUNE ) - _CrtMemCheckpoint( &endMemState ); - //_CrtMemDumpStatistics( &endMemState ); - - _CrtMemState diffMemState; - _CrtMemDifference( &diffMemState, &startMemState, &endMemState ); - _CrtMemDumpStatistics( &diffMemState ); - #endif - - printf ("\nPass %d, Fail %d\n", gPass, gFail); - return gFail; -} - - diff --git a/tools/assimp_view/assimp_view.cpp b/tools/assimp_view/assimp_view.cpp index d6f4bb806..ef3cecd31 100644 --- a/tools/assimp_view/assimp_view.cpp +++ b/tools/assimp_view/assimp_view.cpp @@ -135,7 +135,7 @@ DWORD WINAPI LoadThreadProc(LPVOID lpParameter) aiProcess_ConvertToLeftHanded | // convert everything to D3D left handed space aiProcess_SplitLargeMeshes | // split large, unrenderable meshes into submeshes aiProcess_ValidateDataStructure | aiProcess_ImproveCacheLocality - | aiProcess_RemoveRedundantMaterials | aiProcess_SortByPType | aiProcess_FindDegenerates | + | aiProcess_RemoveRedundantMaterials | aiProcess_SortByPType | aiProcess_FindInvalidData); // validate the output data structure // get the end time of zje operation, calculate delta t diff --git a/workspaces/vc8/assimp.vcproj b/workspaces/vc8/assimp.vcproj index 593113adf..fa2d66d53 100644 --- a/workspaces/vc8/assimp.vcproj +++ b/workspaces/vc8/assimp.vcproj @@ -1354,6 +1354,18 @@ > </File> </Filter> + <Filter + Name="IRRMesh" + > + <File + RelativePath="..\..\code\IRRMeshLoader.cpp" + > + </File> + <File + RelativePath="..\..\code\IRRMeshLoader.h" + > + </File> + </Filter> </Filter> <Filter Name="PostProcess" @@ -1568,8 +1580,116 @@ </File> </Filter> <Filter - Name="TinyXML" + Name="irrXML" > + <File + RelativePath="..\..\code\irrXML\CXMLReaderImpl.h" + > + </File> + <File + RelativePath="..\..\code\irrXML\fast_atof.h" + > + </File> + <File + RelativePath="..\..\code\irrXML\heapsort.h" + > + </File> + <File + RelativePath="..\..\code\irrXML\irrArray.h" + > + </File> + <File + RelativePath="..\..\code\irrXML\irrString.h" + > + </File> + <File + RelativePath="..\..\code\irrXML\irrTypes.h" + > + </File> + <File + RelativePath="..\..\code\irrXML\irrXML.cpp" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + BasicRuntimeChecks="0" + SmallerTypeCheck="false" + UsePrecompiledHeader="0" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug|x64" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="0" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + BasicRuntimeChecks="0" + SmallerTypeCheck="false" + UsePrecompiledHeader="0" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|x64" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="0" + /> + </FileConfiguration> + <FileConfiguration + Name="Release_DLL|Win32" + > + <Tool + Name="VCCLCompilerTool" + BasicRuntimeChecks="0" + SmallerTypeCheck="false" + UsePrecompiledHeader="0" + /> + </FileConfiguration> + <FileConfiguration + Name="Release_DLL|x64" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="0" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug_DLL|Win32" + > + <Tool + Name="VCCLCompilerTool" + BasicRuntimeChecks="0" + SmallerTypeCheck="false" + UsePrecompiledHeader="0" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug_DLL|x64" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="0" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\code\irrXML\irrXML.h" + > + </File> + <File + RelativePath="..\..\code\irrXML\irrXMLWrapper.h" + > + </File> </Filter> </Filter> <Filter