Merge branch 'master' into 5781186265350144
commit
9ef71fe231
|
@ -49,8 +49,8 @@ option(ASSIMP_HUNTER_ENABLED "Enable Hunter package manager support" OFF)
|
|||
IF(ASSIMP_HUNTER_ENABLED)
|
||||
include("cmake-modules/HunterGate.cmake")
|
||||
HunterGate(
|
||||
URL "https://github.com/cpp-pm/hunter/archive/v0.24.0.tar.gz"
|
||||
SHA1 "a3d7f4372b1dcd52faa6ff4a3bd5358e1d0e5efd"
|
||||
URL "https://github.com/cpp-pm/hunter/archive/v0.24.17.tar.gz"
|
||||
SHA1 "e6396699e414120e32557fe92db097b7655b760b"
|
||||
)
|
||||
|
||||
add_definitions(-DASSIMP_USE_HUNTER)
|
||||
|
|
|
@ -115,7 +115,9 @@ void HMPImporter::InternReadFile(const std::string &pFile,
|
|||
throw DeadlyImportError("HMP File is too small.");
|
||||
|
||||
// Allocate storage and copy the contents of the file to a memory buffer
|
||||
mBuffer = new uint8_t[fileSize];
|
||||
auto deleter=[this](uint8_t* ptr){ delete[] ptr; mBuffer = nullptr; };
|
||||
std::unique_ptr<uint8_t[], decltype(deleter)> buffer(new uint8_t[fileSize], deleter);
|
||||
mBuffer = buffer.get();
|
||||
file->Read((void *)mBuffer, 1, fileSize);
|
||||
iFileSize = (unsigned int)fileSize;
|
||||
|
||||
|
@ -143,9 +145,6 @@ void HMPImporter::InternReadFile(const std::string &pFile,
|
|||
// Print the magic word to the logger
|
||||
std::string szBuffer = ai_str_toprintable((const char *)&iMagic, sizeof(iMagic));
|
||||
|
||||
delete[] mBuffer;
|
||||
mBuffer = nullptr;
|
||||
|
||||
// We're definitely unable to load this file
|
||||
throw DeadlyImportError("Unknown HMP subformat ", pFile,
|
||||
". Magic word (", szBuffer, ") is not known");
|
||||
|
@ -153,9 +152,6 @@ void HMPImporter::InternReadFile(const std::string &pFile,
|
|||
|
||||
// Set the AI_SCENE_FLAGS_TERRAIN bit
|
||||
pScene->mFlags |= AI_SCENE_FLAGS_TERRAIN;
|
||||
|
||||
delete[] mBuffer;
|
||||
mBuffer = nullptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -445,11 +441,11 @@ void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char *szC
|
|||
szCursor += sizeof(uint32_t);
|
||||
|
||||
// allocate an output material
|
||||
aiMaterial *pcMat = new aiMaterial();
|
||||
std::unique_ptr<aiMaterial> pcMat(new aiMaterial());
|
||||
|
||||
// read the skin, this works exactly as for MDL7
|
||||
ParseSkinLump_3DGS_MDL7(szCursor, &szCursor,
|
||||
pcMat, iType, iWidth, iHeight);
|
||||
pcMat.get(), iType, iWidth, iHeight);
|
||||
|
||||
// now we need to skip any other skins ...
|
||||
for (unsigned int i = 1; i < iNumSkins; ++i) {
|
||||
|
@ -468,7 +464,7 @@ void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char *szC
|
|||
// setup the material ...
|
||||
pScene->mNumMaterials = 1;
|
||||
pScene->mMaterials = new aiMaterial *[1];
|
||||
pScene->mMaterials[0] = pcMat;
|
||||
pScene->mMaterials[0] = pcMat.release();
|
||||
|
||||
*szCursorOut = szCursor;
|
||||
}
|
||||
|
|
|
@ -228,15 +228,20 @@ bool MD5Parser::ParseSection(Section &out) {
|
|||
out.data[out.length] = '\0';
|
||||
|
||||
// parse a string, enclosed in quotation marks
|
||||
#define AI_MD5_PARSE_STRING_IN_QUOTATION(out) \
|
||||
while ('\"' != *sz) \
|
||||
++sz; \
|
||||
const char *szStart = ++sz; \
|
||||
while ('\"' != *sz) \
|
||||
++sz; \
|
||||
const char *szEnd = (sz++); \
|
||||
out.length = (ai_uint32)(szEnd - szStart); \
|
||||
::memcpy(out.data, szStart, out.length); \
|
||||
#define AI_MD5_PARSE_STRING_IN_QUOTATION(out) \
|
||||
out.length = 0; \
|
||||
while ('\"' != *sz && '\0' != *sz) \
|
||||
++sz; \
|
||||
if ('\0' != *sz) { \
|
||||
const char *szStart = ++sz; \
|
||||
while ('\"' != *sz && '\0' != *sz) \
|
||||
++sz; \
|
||||
if ('\0' != *sz) { \
|
||||
const char *szEnd = (sz++); \
|
||||
out.length = (ai_uint32)(szEnd - szStart); \
|
||||
::memcpy(out.data, szStart, out.length); \
|
||||
} \
|
||||
} \
|
||||
out.data[out.length] = '\0';
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// .MD5MESH parsing function
|
||||
|
|
|
@ -274,7 +274,7 @@ void MDLImporter::InternReadFile(const std::string &pFile,
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Check whether we're still inside the valid file range
|
||||
void MDLImporter::SizeCheck(const void *szPos) {
|
||||
if (!szPos || (const unsigned char *)szPos > this->mBuffer + this->iFileSize) {
|
||||
if (!szPos || (const unsigned char *)szPos > this->mBuffer + this->iFileSize || szPos < this->mBuffer) {
|
||||
throw DeadlyImportError("Invalid MDL file. The file is too small "
|
||||
"or contains invalid data.");
|
||||
}
|
||||
|
|
|
@ -703,7 +703,14 @@ void MDLImporter::SkipSkinLump_3DGS_MDL7(
|
|||
tex.pcData = bad_texel;
|
||||
tex.mHeight = iHeight;
|
||||
tex.mWidth = iWidth;
|
||||
ParseTextureColorData(szCurrent, iMasked, &iSkip, &tex);
|
||||
|
||||
try {
|
||||
ParseTextureColorData(szCurrent, iMasked, &iSkip, &tex);
|
||||
} catch (...) {
|
||||
// FIX: Important, otherwise the destructor will crash
|
||||
tex.pcData = nullptr;
|
||||
throw;
|
||||
}
|
||||
|
||||
// FIX: Important, otherwise the destructor will crash
|
||||
tex.pcData = nullptr;
|
||||
|
|
|
@ -100,8 +100,6 @@ glTF2Importer::glTF2Importer() :
|
|||
// empty
|
||||
}
|
||||
|
||||
glTF2Importer::~glTF2Importer() = default;
|
||||
|
||||
const aiImporterDesc *glTF2Importer::GetInfo() const {
|
||||
return &desc;
|
||||
}
|
||||
|
@ -443,10 +441,10 @@ static inline bool CheckValidFacesIndices(aiFace *faces, unsigned nFaces, unsign
|
|||
#endif // ASSIMP_BUILD_DEBUG
|
||||
|
||||
template <typename T>
|
||||
aiColor4D *GetVertexColorsForType(Ref<Accessor> input) {
|
||||
aiColor4D *GetVertexColorsForType(Ref<Accessor> input, std::vector<unsigned int> *vertexRemappingTable) {
|
||||
constexpr float max = std::numeric_limits<T>::max();
|
||||
aiColor4t<T> *colors;
|
||||
input->ExtractData(colors);
|
||||
input->ExtractData(colors, vertexRemappingTable);
|
||||
auto output = new aiColor4D[input->count];
|
||||
for (size_t i = 0; i < input->count; i++) {
|
||||
output[i] = aiColor4D(
|
||||
|
@ -461,20 +459,26 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
|||
ASSIMP_LOG_DEBUG("Importing ", r.meshes.Size(), " meshes");
|
||||
std::vector<std::unique_ptr<aiMesh>> meshes;
|
||||
|
||||
unsigned int k = 0;
|
||||
meshOffsets.clear();
|
||||
meshOffsets.reserve(r.meshes.Size() + 1);
|
||||
mVertexRemappingTables.clear();
|
||||
|
||||
// Count the number of aiMeshes
|
||||
unsigned int num_aiMeshes = 0;
|
||||
for (unsigned int m = 0; m < r.meshes.Size(); ++m) {
|
||||
meshOffsets.push_back(num_aiMeshes);
|
||||
num_aiMeshes += unsigned(r.meshes[m].primitives.size());
|
||||
}
|
||||
meshOffsets.push_back(num_aiMeshes); // add a last element so we can always do meshOffsets[n+1] - meshOffsets[n]
|
||||
|
||||
std::vector<unsigned int> usedVertexIndices;
|
||||
std::vector<unsigned int> reverseMappingIndices;
|
||||
std::vector<unsigned int> indexBuffer;
|
||||
meshes.reserve(num_aiMeshes);
|
||||
mVertexRemappingTables.resize(num_aiMeshes);
|
||||
|
||||
for (unsigned int m = 0; m < r.meshes.Size(); ++m) {
|
||||
Mesh &mesh = r.meshes[m];
|
||||
|
||||
meshOffsets.push_back(k);
|
||||
k += unsigned(mesh.primitives.size());
|
||||
|
||||
for (unsigned int p = 0; p < mesh.primitives.size(); ++p) {
|
||||
Mesh::Primitive &prim = mesh.primitives[p];
|
||||
|
||||
|
@ -488,14 +492,14 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
|||
|
||||
// Extract used vertices:
|
||||
bool useIndexBuffer = prim.indices;
|
||||
std::vector<unsigned int>* vertexRemappingTable = nullptr;
|
||||
std::vector<unsigned int> *vertexRemappingTable = nullptr;
|
||||
|
||||
if (useIndexBuffer) {
|
||||
size_t count = prim.indices->count;
|
||||
indexBuffer.resize(count);
|
||||
usedVertexIndices.clear();
|
||||
reverseMappingIndices.clear();
|
||||
usedVertexIndices.reserve(count / 3); // this is a very rough heuristic to reduce re-allocations
|
||||
vertexRemappingTable = &usedVertexIndices;
|
||||
vertexRemappingTable = &mVertexRemappingTables[meshes.size()];
|
||||
vertexRemappingTable->reserve(count / 3); // this is a very rough heuristic to reduce re-allocations
|
||||
Accessor::Indexer data = prim.indices->GetIndexer();
|
||||
if (!data.IsValid()) {
|
||||
throw DeadlyImportError("GLTF: Invalid accessor without data in mesh ", getContextForErrorMessages(mesh.id, mesh.name));
|
||||
|
@ -515,8 +519,8 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
|||
reverseMappingIndices.resize(index + 1, unusedIndex);
|
||||
}
|
||||
if (reverseMappingIndices[index] == unusedIndex) {
|
||||
reverseMappingIndices[index] = static_cast<unsigned int>(usedVertexIndices.size());
|
||||
usedVertexIndices.push_back(index);
|
||||
reverseMappingIndices[index] = static_cast<unsigned int>(vertexRemappingTable->size());
|
||||
vertexRemappingTable->push_back(index);
|
||||
}
|
||||
indexBuffer[i] = reverseMappingIndices[index];
|
||||
}
|
||||
|
@ -597,9 +601,9 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
|||
attr.color[c]->ExtractData(aim->mColors[c], vertexRemappingTable);
|
||||
} else {
|
||||
if (componentType == glTF2::ComponentType_UNSIGNED_BYTE) {
|
||||
aim->mColors[c] = GetVertexColorsForType<unsigned char>(attr.color[c]);
|
||||
aim->mColors[c] = GetVertexColorsForType<unsigned char>(attr.color[c], vertexRemappingTable);
|
||||
} else if (componentType == glTF2::ComponentType_UNSIGNED_SHORT) {
|
||||
aim->mColors[c] = GetVertexColorsForType<unsigned short>(attr.color[c]);
|
||||
aim->mColors[c] = GetVertexColorsForType<unsigned short>(attr.color[c], vertexRemappingTable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -875,8 +879,6 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
|
|||
}
|
||||
}
|
||||
|
||||
meshOffsets.push_back(k);
|
||||
|
||||
CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes);
|
||||
}
|
||||
|
||||
|
@ -1009,7 +1011,8 @@ static void GetNodeTransform(aiMatrix4x4 &matrix, const glTF2::Node &node) {
|
|||
}
|
||||
}
|
||||
|
||||
static void BuildVertexWeightMapping(Mesh::Primitive &primitive, std::vector<std::vector<aiVertexWeight>> &map) {
|
||||
static void BuildVertexWeightMapping(Mesh::Primitive &primitive, std::vector<std::vector<aiVertexWeight>> &map, std::vector<unsigned int>* vertexRemappingTablePtr) {
|
||||
|
||||
Mesh::Primitive::Attributes &attr = primitive.attributes;
|
||||
if (attr.weight.empty() || attr.joint.empty()) {
|
||||
return;
|
||||
|
@ -1018,14 +1021,14 @@ static void BuildVertexWeightMapping(Mesh::Primitive &primitive, std::vector<std
|
|||
return;
|
||||
}
|
||||
|
||||
size_t num_vertices = attr.weight[0]->count;
|
||||
size_t num_vertices = 0;
|
||||
|
||||
struct Weights {
|
||||
float values[4];
|
||||
};
|
||||
Weights **weights = new Weights*[attr.weight.size()];
|
||||
for (size_t w = 0; w < attr.weight.size(); ++w) {
|
||||
attr.weight[w]->ExtractData(weights[w]);
|
||||
num_vertices = attr.weight[w]->ExtractData(weights[w], vertexRemappingTablePtr);
|
||||
}
|
||||
|
||||
struct Indices8 {
|
||||
|
@ -1039,12 +1042,12 @@ static void BuildVertexWeightMapping(Mesh::Primitive &primitive, std::vector<std
|
|||
if (attr.joint[0]->GetElementSize() == 4) {
|
||||
indices8 = new Indices8*[attr.joint.size()];
|
||||
for (size_t j = 0; j < attr.joint.size(); ++j) {
|
||||
attr.joint[j]->ExtractData(indices8[j]);
|
||||
attr.joint[j]->ExtractData(indices8[j], vertexRemappingTablePtr);
|
||||
}
|
||||
} else {
|
||||
indices16 = new Indices16 *[attr.joint.size()];
|
||||
for (size_t j = 0; j < attr.joint.size(); ++j) {
|
||||
attr.joint[j]->ExtractData(indices16[j]);
|
||||
attr.joint[j]->ExtractData(indices16[j], vertexRemappingTablePtr);
|
||||
}
|
||||
}
|
||||
//
|
||||
|
@ -1109,7 +1112,7 @@ void ParseExtras(aiMetadata* metadata, const Extras& extras) {
|
|||
}
|
||||
}
|
||||
|
||||
aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &meshOffsets, glTF2::Ref<glTF2::Node> &ptr) {
|
||||
aiNode *glTF2Importer::ImportNode(glTF2::Asset &r, glTF2::Ref<glTF2::Node> &ptr) {
|
||||
Node &node = *ptr;
|
||||
|
||||
aiNode *ainode = new aiNode(GetNodeName(node));
|
||||
|
@ -1121,7 +1124,7 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
|
|||
std::fill(ainode->mChildren, ainode->mChildren + ainode->mNumChildren, nullptr);
|
||||
|
||||
for (unsigned int i = 0; i < ainode->mNumChildren; ++i) {
|
||||
aiNode *child = ImportNode(pScene, r, meshOffsets, node.children[i]);
|
||||
aiNode *child = ImportNode(r, node.children[i]);
|
||||
child->mParent = ainode;
|
||||
ainode->mChildren[i] = child;
|
||||
}
|
||||
|
@ -1154,11 +1157,13 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
|
|||
|
||||
if (node.skin) {
|
||||
for (int primitiveNo = 0; primitiveNo < count; ++primitiveNo) {
|
||||
aiMesh *mesh = pScene->mMeshes[meshOffsets[mesh_idx] + primitiveNo];
|
||||
unsigned int aiMeshIdx = meshOffsets[mesh_idx] + primitiveNo;
|
||||
aiMesh *mesh = mScene->mMeshes[aiMeshIdx];
|
||||
unsigned int numBones = static_cast<unsigned int>(node.skin->jointNames.size());
|
||||
std::vector<unsigned int> *vertexRemappingTablePtr = mVertexRemappingTables[aiMeshIdx].empty() ? nullptr : &mVertexRemappingTables[aiMeshIdx];
|
||||
|
||||
std::vector<std::vector<aiVertexWeight>> weighting(numBones);
|
||||
BuildVertexWeightMapping(node.meshes[0]->primitives[primitiveNo], weighting);
|
||||
BuildVertexWeightMapping(node.meshes[0]->primitives[primitiveNo], weighting, vertexRemappingTablePtr);
|
||||
|
||||
mesh->mNumBones = static_cast<unsigned int>(numBones);
|
||||
mesh->mBones = new aiBone *[mesh->mNumBones];
|
||||
|
@ -1175,7 +1180,7 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
|
|||
// mapping which makes things doubly-slow.
|
||||
|
||||
mat4 *pbindMatrices = nullptr;
|
||||
node.skin->inverseBindMatrices->ExtractData(pbindMatrices);
|
||||
node.skin->inverseBindMatrices->ExtractData(pbindMatrices, nullptr);
|
||||
|
||||
for (uint32_t i = 0; i < numBones; ++i) {
|
||||
const std::vector<aiVertexWeight> &weights = weighting[i];
|
||||
|
@ -1221,11 +1226,11 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
|
|||
}
|
||||
|
||||
if (node.camera) {
|
||||
pScene->mCameras[node.camera.GetIndex()]->mName = ainode->mName;
|
||||
mScene->mCameras[node.camera.GetIndex()]->mName = ainode->mName;
|
||||
}
|
||||
|
||||
if (node.light) {
|
||||
pScene->mLights[node.light.GetIndex()]->mName = ainode->mName;
|
||||
mScene->mLights[node.light.GetIndex()]->mName = ainode->mName;
|
||||
|
||||
// range is optional - see https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual
|
||||
// it is added to meta data of parent node, because there is no other place to put it
|
||||
|
@ -1257,7 +1262,7 @@ void glTF2Importer::ImportNodes(glTF2::Asset &r) {
|
|||
// The root nodes
|
||||
unsigned int numRootNodes = unsigned(rootNodes.size());
|
||||
if (numRootNodes == 1) { // a single root node: use it
|
||||
mScene->mRootNode = ImportNode(mScene, r, meshOffsets, rootNodes[0]);
|
||||
mScene->mRootNode = ImportNode(r, rootNodes[0]);
|
||||
} else if (numRootNodes > 1) { // more than one root node: create a fake root
|
||||
aiNode *root = mScene->mRootNode = new aiNode("ROOT");
|
||||
|
||||
|
@ -1265,7 +1270,7 @@ void glTF2Importer::ImportNodes(glTF2::Asset &r) {
|
|||
std::fill(root->mChildren, root->mChildren + numRootNodes, nullptr);
|
||||
|
||||
for (unsigned int i = 0; i < numRootNodes; ++i) {
|
||||
aiNode *node = ImportNode(mScene, r, meshOffsets, rootNodes[i]);
|
||||
aiNode *node = ImportNode(r, rootNodes[i]);
|
||||
node->mParent = root;
|
||||
root->mChildren[root->mNumChildren++] = node;
|
||||
}
|
||||
|
@ -1666,6 +1671,7 @@ void glTF2Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IO
|
|||
|
||||
// clean all member arrays
|
||||
meshOffsets.clear();
|
||||
mVertexRemappingTables.clear();
|
||||
mEmbeddedTexIdxs.clear();
|
||||
|
||||
this->mScene = pScene;
|
||||
|
|
|
@ -43,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#define AI_GLTF2IMPORTER_H_INC
|
||||
|
||||
#include <assimp/BaseImporter.h>
|
||||
#include <AssetLib/glTF2/glTF2Asset.h>
|
||||
|
||||
struct aiNode;
|
||||
|
||||
|
@ -59,7 +60,7 @@ namespace Assimp {
|
|||
class glTF2Importer : public BaseImporter {
|
||||
public:
|
||||
glTF2Importer();
|
||||
~glTF2Importer() override;
|
||||
~glTF2Importer() override = default;
|
||||
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const override;
|
||||
|
||||
protected:
|
||||
|
@ -76,10 +77,12 @@ private:
|
|||
void ImportNodes(glTF2::Asset &a);
|
||||
void ImportAnimations(glTF2::Asset &a);
|
||||
void ImportCommonMetadata(glTF2::Asset &a);
|
||||
aiNode *ImportNode(glTF2::Asset &r, glTF2::Ref<glTF2::Node> &ptr);
|
||||
|
||||
private:
|
||||
std::vector<unsigned int> meshOffsets;
|
||||
std::vector<int> mEmbeddedTexIdxs;
|
||||
std::vector<std::vector<unsigned int>> mVertexRemappingTables; // for each converted aiMesh in the scene, it stores a list of vertices that are actually used
|
||||
aiScene *mScene;
|
||||
|
||||
/// An instance of rapidjson::IRemoteSchemaDocumentProvider
|
||||
|
|
|
@ -81,6 +81,7 @@ void LimitBoneWeightsProcess::Execute( aiScene* pScene) {
|
|||
// Executes the post processing step on the given imported data.
|
||||
void LimitBoneWeightsProcess::SetupProperties(const Importer* pImp) {
|
||||
this->mMaxWeights = pImp->GetPropertyInteger(AI_CONFIG_PP_LBW_MAX_WEIGHTS,AI_LMW_MAX_WEIGHTS);
|
||||
this->mRemoveEmptyBones = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, 1) != 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -172,9 +173,9 @@ void LimitBoneWeightsProcess::ProcessMesh(aiMesh* pMesh) {
|
|||
}
|
||||
|
||||
// remove empty bones
|
||||
#ifdef AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES
|
||||
pMesh->mNumBones = removeEmptyBones(pMesh);
|
||||
#endif // AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES
|
||||
if (mRemoveEmptyBones) {
|
||||
pMesh->mNumBones = removeEmptyBones(pMesh);
|
||||
}
|
||||
|
||||
if (!DefaultLogger::isNullLogger()) {
|
||||
ASSIMP_LOG_INFO("Removed ", removed, " weights. Input bones: ", old_bones, ". Output bones: ", pMesh->mNumBones);
|
||||
|
|
|
@ -133,6 +133,7 @@ public:
|
|||
|
||||
/** Maximum number of bones influencing any single vertex. */
|
||||
unsigned int mMaxWeights;
|
||||
bool mRemoveEmptyBones;
|
||||
};
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* pugixml parser - version 1.12
|
||||
* pugixml parser - version 1.13
|
||||
* --------------------------------------------------------
|
||||
* Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
|
||||
* Report bugs and download new versions at https://pugixml.org/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* pugixml parser - version 1.12
|
||||
* pugixml parser - version 1.13
|
||||
* --------------------------------------------------------
|
||||
* Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
|
||||
* Report bugs and download new versions at https://pugixml.org/
|
||||
|
@ -1276,12 +1276,14 @@ PUGI__NS_BEGIN
|
|||
|
||||
child->parent = parent;
|
||||
|
||||
if (node->next_sibling)
|
||||
node->next_sibling->prev_sibling_c = child;
|
||||
xml_node_struct* next = node->next_sibling;
|
||||
|
||||
if (next)
|
||||
next->prev_sibling_c = child;
|
||||
else
|
||||
parent->first_child->prev_sibling_c = child;
|
||||
|
||||
child->next_sibling = node->next_sibling;
|
||||
child->next_sibling = next;
|
||||
child->prev_sibling_c = node;
|
||||
|
||||
node->next_sibling = child;
|
||||
|
@ -1293,12 +1295,14 @@ PUGI__NS_BEGIN
|
|||
|
||||
child->parent = parent;
|
||||
|
||||
if (node->prev_sibling_c->next_sibling)
|
||||
node->prev_sibling_c->next_sibling = child;
|
||||
xml_node_struct* prev = node->prev_sibling_c;
|
||||
|
||||
if (prev->next_sibling)
|
||||
prev->next_sibling = child;
|
||||
else
|
||||
parent->first_child = child;
|
||||
|
||||
child->prev_sibling_c = node->prev_sibling_c;
|
||||
child->prev_sibling_c = prev;
|
||||
child->next_sibling = node;
|
||||
|
||||
node->prev_sibling_c = child;
|
||||
|
@ -1308,15 +1312,18 @@ PUGI__NS_BEGIN
|
|||
{
|
||||
xml_node_struct* parent = node->parent;
|
||||
|
||||
if (node->next_sibling)
|
||||
node->next_sibling->prev_sibling_c = node->prev_sibling_c;
|
||||
else
|
||||
parent->first_child->prev_sibling_c = node->prev_sibling_c;
|
||||
xml_node_struct* next = node->next_sibling;
|
||||
xml_node_struct* prev = node->prev_sibling_c;
|
||||
|
||||
if (node->prev_sibling_c->next_sibling)
|
||||
node->prev_sibling_c->next_sibling = node->next_sibling;
|
||||
if (next)
|
||||
next->prev_sibling_c = prev;
|
||||
else
|
||||
parent->first_child = node->next_sibling;
|
||||
parent->first_child->prev_sibling_c = prev;
|
||||
|
||||
if (prev->next_sibling)
|
||||
prev->next_sibling = next;
|
||||
else
|
||||
parent->first_child = next;
|
||||
|
||||
node->parent = 0;
|
||||
node->prev_sibling_c = 0;
|
||||
|
@ -1360,39 +1367,46 @@ PUGI__NS_BEGIN
|
|||
|
||||
inline void insert_attribute_after(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node)
|
||||
{
|
||||
if (place->next_attribute)
|
||||
place->next_attribute->prev_attribute_c = attr;
|
||||
xml_attribute_struct* next = place->next_attribute;
|
||||
|
||||
if (next)
|
||||
next->prev_attribute_c = attr;
|
||||
else
|
||||
node->first_attribute->prev_attribute_c = attr;
|
||||
|
||||
attr->next_attribute = place->next_attribute;
|
||||
attr->next_attribute = next;
|
||||
attr->prev_attribute_c = place;
|
||||
place->next_attribute = attr;
|
||||
}
|
||||
|
||||
inline void insert_attribute_before(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node)
|
||||
{
|
||||
if (place->prev_attribute_c->next_attribute)
|
||||
place->prev_attribute_c->next_attribute = attr;
|
||||
xml_attribute_struct* prev = place->prev_attribute_c;
|
||||
|
||||
if (prev->next_attribute)
|
||||
prev->next_attribute = attr;
|
||||
else
|
||||
node->first_attribute = attr;
|
||||
|
||||
attr->prev_attribute_c = place->prev_attribute_c;
|
||||
attr->prev_attribute_c = prev;
|
||||
attr->next_attribute = place;
|
||||
place->prev_attribute_c = attr;
|
||||
}
|
||||
|
||||
inline void remove_attribute(xml_attribute_struct* attr, xml_node_struct* node)
|
||||
{
|
||||
if (attr->next_attribute)
|
||||
attr->next_attribute->prev_attribute_c = attr->prev_attribute_c;
|
||||
else
|
||||
node->first_attribute->prev_attribute_c = attr->prev_attribute_c;
|
||||
xml_attribute_struct* next = attr->next_attribute;
|
||||
xml_attribute_struct* prev = attr->prev_attribute_c;
|
||||
|
||||
if (attr->prev_attribute_c->next_attribute)
|
||||
attr->prev_attribute_c->next_attribute = attr->next_attribute;
|
||||
if (next)
|
||||
next->prev_attribute_c = prev;
|
||||
else
|
||||
node->first_attribute = attr->next_attribute;
|
||||
node->first_attribute->prev_attribute_c = prev;
|
||||
|
||||
if (prev->next_attribute)
|
||||
prev->next_attribute = next;
|
||||
else
|
||||
node->first_attribute = next;
|
||||
|
||||
attr->prev_attribute_c = 0;
|
||||
attr->next_attribute = 0;
|
||||
|
@ -4707,6 +4721,9 @@ PUGI__NS_BEGIN
|
|||
// get actual encoding
|
||||
xml_encoding buffer_encoding = impl::get_buffer_encoding(encoding, contents, size);
|
||||
|
||||
// if convert_buffer below throws bad_alloc, we still need to deallocate contents if we own it
|
||||
auto_deleter<void> contents_guard(own ? contents : 0, xml_memory::deallocate);
|
||||
|
||||
// get private buffer
|
||||
char_t* buffer = 0;
|
||||
size_t length = 0;
|
||||
|
@ -4714,6 +4731,9 @@ PUGI__NS_BEGIN
|
|||
// coverity[var_deref_model]
|
||||
if (!impl::convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable)) return impl::make_parse_result(status_out_of_memory);
|
||||
|
||||
// after this we either deallocate contents (below) or hold on to it via doc->buffer, so we don't need to guard it
|
||||
contents_guard.release();
|
||||
|
||||
// delete original buffer if we performed a conversion
|
||||
if (own && buffer != contents && contents) impl::xml_memory::deallocate(contents);
|
||||
|
||||
|
@ -5050,7 +5070,7 @@ PUGI__NS_BEGIN
|
|||
xml_writer_file writer(file);
|
||||
doc.save(writer, indent, flags, encoding);
|
||||
|
||||
return ferror(file) == 0;
|
||||
return fflush(file) == 0 && ferror(file) == 0;
|
||||
}
|
||||
|
||||
struct name_null_sentry
|
||||
|
@ -5185,53 +5205,72 @@ namespace pugi
|
|||
|
||||
PUGI__FN xml_attribute xml_attribute::next_attribute() const
|
||||
{
|
||||
return _attr ? xml_attribute(_attr->next_attribute) : xml_attribute();
|
||||
if (!_attr) return xml_attribute();
|
||||
return xml_attribute(_attr->next_attribute);
|
||||
}
|
||||
|
||||
PUGI__FN xml_attribute xml_attribute::previous_attribute() const
|
||||
{
|
||||
return _attr && _attr->prev_attribute_c->next_attribute ? xml_attribute(_attr->prev_attribute_c) : xml_attribute();
|
||||
if (!_attr) return xml_attribute();
|
||||
xml_attribute_struct* prev = _attr->prev_attribute_c;
|
||||
return prev->next_attribute ? xml_attribute(prev) : xml_attribute();
|
||||
}
|
||||
|
||||
PUGI__FN const char_t* xml_attribute::as_string(const char_t* def) const
|
||||
{
|
||||
return (_attr && _attr->value) ? _attr->value + 0 : def;
|
||||
if (!_attr) return def;
|
||||
const char_t* value = _attr->value;
|
||||
return value ? value : def;
|
||||
}
|
||||
|
||||
PUGI__FN int xml_attribute::as_int(int def) const
|
||||
{
|
||||
return (_attr && _attr->value) ? impl::get_value_int(_attr->value) : def;
|
||||
if (!_attr) return def;
|
||||
const char_t* value = _attr->value;
|
||||
return value ? impl::get_value_int(value) : def;
|
||||
}
|
||||
|
||||
PUGI__FN unsigned int xml_attribute::as_uint(unsigned int def) const
|
||||
{
|
||||
return (_attr && _attr->value) ? impl::get_value_uint(_attr->value) : def;
|
||||
if (!_attr) return def;
|
||||
const char_t* value = _attr->value;
|
||||
return value ? impl::get_value_uint(value) : def;
|
||||
}
|
||||
|
||||
PUGI__FN double xml_attribute::as_double(double def) const
|
||||
{
|
||||
return (_attr && _attr->value) ? impl::get_value_double(_attr->value) : def;
|
||||
if (!_attr) return def;
|
||||
const char_t* value = _attr->value;
|
||||
return value ? impl::get_value_double(value) : def;
|
||||
}
|
||||
|
||||
PUGI__FN float xml_attribute::as_float(float def) const
|
||||
{
|
||||
return (_attr && _attr->value) ? impl::get_value_float(_attr->value) : def;
|
||||
if (!_attr) return def;
|
||||
const char_t* value = _attr->value;
|
||||
return value ? impl::get_value_float(value) : def;
|
||||
}
|
||||
|
||||
PUGI__FN bool xml_attribute::as_bool(bool def) const
|
||||
{
|
||||
return (_attr && _attr->value) ? impl::get_value_bool(_attr->value) : def;
|
||||
if (!_attr) return def;
|
||||
const char_t* value = _attr->value;
|
||||
return value ? impl::get_value_bool(value) : def;
|
||||
}
|
||||
|
||||
#ifdef PUGIXML_HAS_LONG_LONG
|
||||
PUGI__FN long long xml_attribute::as_llong(long long def) const
|
||||
{
|
||||
return (_attr && _attr->value) ? impl::get_value_llong(_attr->value) : def;
|
||||
if (!_attr) return def;
|
||||
const char_t* value = _attr->value;
|
||||
return value ? impl::get_value_llong(value) : def;
|
||||
}
|
||||
|
||||
PUGI__FN unsigned long long xml_attribute::as_ullong(unsigned long long def) const
|
||||
{
|
||||
return (_attr && _attr->value) ? impl::get_value_ullong(_attr->value) : def;
|
||||
if (!_attr) return def;
|
||||
const char_t* value = _attr->value;
|
||||
return value ? impl::get_value_ullong(value) : def;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -5242,12 +5281,16 @@ namespace pugi
|
|||
|
||||
PUGI__FN const char_t* xml_attribute::name() const
|
||||
{
|
||||
return (_attr && _attr->name) ? _attr->name + 0 : PUGIXML_TEXT("");
|
||||
if (!_attr) return PUGIXML_TEXT("");
|
||||
const char_t* name = _attr->name;
|
||||
return name ? name : PUGIXML_TEXT("");
|
||||
}
|
||||
|
||||
PUGI__FN const char_t* xml_attribute::value() const
|
||||
{
|
||||
return (_attr && _attr->value) ? _attr->value + 0 : PUGIXML_TEXT("");
|
||||
if (!_attr) return PUGIXML_TEXT("");
|
||||
const char_t* value = _attr->value;
|
||||
return value ? value : PUGIXML_TEXT("");
|
||||
}
|
||||
|
||||
PUGI__FN size_t xml_attribute::hash_value() const
|
||||
|
@ -5329,6 +5372,13 @@ namespace pugi
|
|||
return impl::strcpy_insitu(_attr->name, _attr->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs));
|
||||
}
|
||||
|
||||
PUGI__FN bool xml_attribute::set_value(const char_t* rhs, size_t sz)
|
||||
{
|
||||
if (!_attr) return false;
|
||||
|
||||
return impl::strcpy_insitu(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, sz);
|
||||
}
|
||||
|
||||
PUGI__FN bool xml_attribute::set_value(const char_t* rhs)
|
||||
{
|
||||
if (!_attr) return false;
|
||||
|
@ -5521,7 +5571,9 @@ namespace pugi
|
|||
|
||||
PUGI__FN const char_t* xml_node::name() const
|
||||
{
|
||||
return (_root && _root->name) ? _root->name + 0 : PUGIXML_TEXT("");
|
||||
if (!_root) return PUGIXML_TEXT("");
|
||||
const char_t* name = _root->name;
|
||||
return name ? name : PUGIXML_TEXT("");
|
||||
}
|
||||
|
||||
PUGI__FN xml_node_type xml_node::type() const
|
||||
|
@ -5531,7 +5583,9 @@ namespace pugi
|
|||
|
||||
PUGI__FN const char_t* xml_node::value() const
|
||||
{
|
||||
return (_root && _root->value) ? _root->value + 0 : PUGIXML_TEXT("");
|
||||
if (!_root) return PUGIXML_TEXT("");
|
||||
const char_t* value = _root->value;
|
||||
return value ? value : PUGIXML_TEXT("");
|
||||
}
|
||||
|
||||
PUGI__FN xml_node xml_node::child(const char_t* name_) const
|
||||
|
@ -5539,7 +5593,11 @@ namespace pugi
|
|||
if (!_root) return xml_node();
|
||||
|
||||
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
|
||||
if (i->name && impl::strequal(name_, i->name)) return xml_node(i);
|
||||
{
|
||||
const char_t* iname = i->name;
|
||||
if (iname && impl::strequal(name_, iname))
|
||||
return xml_node(i);
|
||||
}
|
||||
|
||||
return xml_node();
|
||||
}
|
||||
|
@ -5549,8 +5607,11 @@ namespace pugi
|
|||
if (!_root) return xml_attribute();
|
||||
|
||||
for (xml_attribute_struct* i = _root->first_attribute; i; i = i->next_attribute)
|
||||
if (i->name && impl::strequal(name_, i->name))
|
||||
{
|
||||
const char_t* iname = i->name;
|
||||
if (iname && impl::strequal(name_, iname))
|
||||
return xml_attribute(i);
|
||||
}
|
||||
|
||||
return xml_attribute();
|
||||
}
|
||||
|
@ -5560,7 +5621,11 @@ namespace pugi
|
|||
if (!_root) return xml_node();
|
||||
|
||||
for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling)
|
||||
if (i->name && impl::strequal(name_, i->name)) return xml_node(i);
|
||||
{
|
||||
const char_t* iname = i->name;
|
||||
if (iname && impl::strequal(name_, iname))
|
||||
return xml_node(i);
|
||||
}
|
||||
|
||||
return xml_node();
|
||||
}
|
||||
|
@ -5575,7 +5640,11 @@ namespace pugi
|
|||
if (!_root) return xml_node();
|
||||
|
||||
for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c)
|
||||
if (i->name && impl::strequal(name_, i->name)) return xml_node(i);
|
||||
{
|
||||
const char_t* iname = i->name;
|
||||
if (iname && impl::strequal(name_, iname))
|
||||
return xml_node(i);
|
||||
}
|
||||
|
||||
return xml_node();
|
||||
}
|
||||
|
@ -5591,24 +5660,30 @@ namespace pugi
|
|||
|
||||
// optimistically search from hint up until the end
|
||||
for (xml_attribute_struct* i = hint; i; i = i->next_attribute)
|
||||
if (i->name && impl::strequal(name_, i->name))
|
||||
{
|
||||
const char_t* iname = i->name;
|
||||
if (iname && impl::strequal(name_, iname))
|
||||
{
|
||||
// update hint to maximize efficiency of searching for consecutive attributes
|
||||
hint_._attr = i->next_attribute;
|
||||
|
||||
return xml_attribute(i);
|
||||
}
|
||||
}
|
||||
|
||||
// wrap around and search from the first attribute until the hint
|
||||
// 'j' null pointer check is technically redundant, but it prevents a crash in case the assertion above fails
|
||||
for (xml_attribute_struct* j = _root->first_attribute; j && j != hint; j = j->next_attribute)
|
||||
if (j->name && impl::strequal(name_, j->name))
|
||||
{
|
||||
const char_t* jname = j->name;
|
||||
if (jname && impl::strequal(name_, jname))
|
||||
{
|
||||
// update hint to maximize efficiency of searching for consecutive attributes
|
||||
hint_._attr = j->next_attribute;
|
||||
|
||||
return xml_attribute(j);
|
||||
}
|
||||
}
|
||||
|
||||
return xml_attribute();
|
||||
}
|
||||
|
@ -5616,9 +5691,8 @@ namespace pugi
|
|||
PUGI__FN xml_node xml_node::previous_sibling() const
|
||||
{
|
||||
if (!_root) return xml_node();
|
||||
|
||||
if (_root->prev_sibling_c->next_sibling) return xml_node(_root->prev_sibling_c);
|
||||
else return xml_node();
|
||||
xml_node_struct* prev = _root->prev_sibling_c;
|
||||
return prev->next_sibling ? xml_node(prev) : xml_node();
|
||||
}
|
||||
|
||||
PUGI__FN xml_node xml_node::parent() const
|
||||
|
@ -5645,8 +5719,11 @@ namespace pugi
|
|||
return _root->value;
|
||||
|
||||
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
|
||||
if (impl::is_text_node(i) && i->value)
|
||||
return i->value;
|
||||
{
|
||||
const char_t* ivalue = i->value;
|
||||
if (impl::is_text_node(i) && ivalue)
|
||||
return ivalue;
|
||||
}
|
||||
|
||||
return PUGIXML_TEXT("");
|
||||
}
|
||||
|
@ -5658,22 +5735,28 @@ namespace pugi
|
|||
|
||||
PUGI__FN xml_attribute xml_node::first_attribute() const
|
||||
{
|
||||
return _root ? xml_attribute(_root->first_attribute) : xml_attribute();
|
||||
if (!_root) return xml_attribute();
|
||||
return xml_attribute(_root->first_attribute);
|
||||
}
|
||||
|
||||
PUGI__FN xml_attribute xml_node::last_attribute() const
|
||||
{
|
||||
return _root && _root->first_attribute ? xml_attribute(_root->first_attribute->prev_attribute_c) : xml_attribute();
|
||||
if (!_root) return xml_attribute();
|
||||
xml_attribute_struct* first = _root->first_attribute;
|
||||
return first ? xml_attribute(first->prev_attribute_c) : xml_attribute();
|
||||
}
|
||||
|
||||
PUGI__FN xml_node xml_node::first_child() const
|
||||
{
|
||||
return _root ? xml_node(_root->first_child) : xml_node();
|
||||
if (!_root) return xml_node();
|
||||
return xml_node(_root->first_child);
|
||||
}
|
||||
|
||||
PUGI__FN xml_node xml_node::last_child() const
|
||||
{
|
||||
return _root && _root->first_child ? xml_node(_root->first_child->prev_sibling_c) : xml_node();
|
||||
if (!_root) return xml_node();
|
||||
xml_node_struct* first = _root->first_child;
|
||||
return first ? xml_node(first->prev_sibling_c) : xml_node();
|
||||
}
|
||||
|
||||
PUGI__FN bool xml_node::set_name(const char_t* rhs)
|
||||
|
@ -5686,6 +5769,16 @@ namespace pugi
|
|||
return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs));
|
||||
}
|
||||
|
||||
PUGI__FN bool xml_node::set_value(const char_t* rhs, size_t sz)
|
||||
{
|
||||
xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null;
|
||||
|
||||
if (type_ != node_pcdata && type_ != node_cdata && type_ != node_comment && type_ != node_pi && type_ != node_doctype)
|
||||
return false;
|
||||
|
||||
return impl::strcpy_insitu(_root->value, _root->header, impl::xml_memory_page_value_allocated_mask, rhs, sz);
|
||||
}
|
||||
|
||||
PUGI__FN bool xml_node::set_value(const char_t* rhs)
|
||||
{
|
||||
xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null;
|
||||
|
@ -6199,12 +6292,22 @@ namespace pugi
|
|||
if (!_root) return xml_node();
|
||||
|
||||
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
|
||||
if (i->name && impl::strequal(name_, i->name))
|
||||
{
|
||||
const char_t* iname = i->name;
|
||||
if (iname && impl::strequal(name_, iname))
|
||||
{
|
||||
for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute)
|
||||
if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 : PUGIXML_TEXT("")))
|
||||
return xml_node(i);
|
||||
{
|
||||
const char_t* aname = a->name;
|
||||
if (aname && impl::strequal(attr_name, aname))
|
||||
{
|
||||
const char_t* avalue = a->value;
|
||||
if (impl::strequal(attr_value, avalue ? avalue : PUGIXML_TEXT("")))
|
||||
return xml_node(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return xml_node();
|
||||
}
|
||||
|
@ -6215,8 +6318,15 @@ namespace pugi
|
|||
|
||||
for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
|
||||
for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute)
|
||||
if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 : PUGIXML_TEXT("")))
|
||||
return xml_node(i);
|
||||
{
|
||||
const char_t* aname = a->name;
|
||||
if (aname && impl::strequal(attr_name, aname))
|
||||
{
|
||||
const char_t* avalue = a->value;
|
||||
if (impl::strequal(attr_value, avalue ? avalue : PUGIXML_TEXT("")))
|
||||
return xml_node(i);
|
||||
}
|
||||
}
|
||||
|
||||
return xml_node();
|
||||
}
|
||||
|
@ -6230,8 +6340,9 @@ namespace pugi
|
|||
|
||||
for (xml_node_struct* i = _root; i; i = i->parent)
|
||||
{
|
||||
const char_t* iname = i->name;
|
||||
offset += (i != _root);
|
||||
offset += i->name ? impl::strlength(i->name) : 0;
|
||||
offset += iname ? impl::strlength(iname) : 0;
|
||||
}
|
||||
|
||||
string_t result;
|
||||
|
@ -6242,12 +6353,13 @@ namespace pugi
|
|||
if (j != _root)
|
||||
result[--offset] = delimiter;
|
||||
|
||||
if (j->name)
|
||||
const char_t* jname = j->name;
|
||||
if (jname)
|
||||
{
|
||||
size_t length = impl::strlength(j->name);
|
||||
size_t length = impl::strlength(jname);
|
||||
|
||||
offset -= length;
|
||||
memcpy(&result[offset], j->name, length * sizeof(char_t));
|
||||
memcpy(&result[offset], jname, length * sizeof(char_t));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6285,7 +6397,8 @@ namespace pugi
|
|||
{
|
||||
for (xml_node_struct* j = context._root->first_child; j; j = j->next_sibling)
|
||||
{
|
||||
if (j->name && impl::strequalrange(j->name, path_segment, static_cast<size_t>(path_segment_end - path_segment)))
|
||||
const char_t* jname = j->name;
|
||||
if (jname && impl::strequalrange(jname, path_segment, static_cast<size_t>(path_segment_end - path_segment)))
|
||||
{
|
||||
xml_node subsearch = xml_node(j).first_element_by_path(next_segment, delimiter);
|
||||
|
||||
|
@ -6477,68 +6590,84 @@ namespace pugi
|
|||
PUGI__FN const char_t* xml_text::get() const
|
||||
{
|
||||
xml_node_struct* d = _data();
|
||||
|
||||
return (d && d->value) ? d->value + 0 : PUGIXML_TEXT("");
|
||||
if (!d) return PUGIXML_TEXT("");
|
||||
const char_t* value = d->value;
|
||||
return value ? value : PUGIXML_TEXT("");
|
||||
}
|
||||
|
||||
PUGI__FN const char_t* xml_text::as_string(const char_t* def) const
|
||||
{
|
||||
xml_node_struct* d = _data();
|
||||
|
||||
return (d && d->value) ? d->value + 0 : def;
|
||||
if (!d) return def;
|
||||
const char_t* value = d->value;
|
||||
return value ? value : def;
|
||||
}
|
||||
|
||||
PUGI__FN int xml_text::as_int(int def) const
|
||||
{
|
||||
xml_node_struct* d = _data();
|
||||
|
||||
return (d && d->value) ? impl::get_value_int(d->value) : def;
|
||||
if (!d) return def;
|
||||
const char_t* value = d->value;
|
||||
return value ? impl::get_value_int(value) : def;
|
||||
}
|
||||
|
||||
PUGI__FN unsigned int xml_text::as_uint(unsigned int def) const
|
||||
{
|
||||
xml_node_struct* d = _data();
|
||||
|
||||
return (d && d->value) ? impl::get_value_uint(d->value) : def;
|
||||
if (!d) return def;
|
||||
const char_t* value = d->value;
|
||||
return value ? impl::get_value_uint(value) : def;
|
||||
}
|
||||
|
||||
PUGI__FN double xml_text::as_double(double def) const
|
||||
{
|
||||
xml_node_struct* d = _data();
|
||||
|
||||
return (d && d->value) ? impl::get_value_double(d->value) : def;
|
||||
if (!d) return def;
|
||||
const char_t* value = d->value;
|
||||
return value ? impl::get_value_double(value) : def;
|
||||
}
|
||||
|
||||
PUGI__FN float xml_text::as_float(float def) const
|
||||
{
|
||||
xml_node_struct* d = _data();
|
||||
|
||||
return (d && d->value) ? impl::get_value_float(d->value) : def;
|
||||
if (!d) return def;
|
||||
const char_t* value = d->value;
|
||||
return value ? impl::get_value_float(value) : def;
|
||||
}
|
||||
|
||||
PUGI__FN bool xml_text::as_bool(bool def) const
|
||||
{
|
||||
xml_node_struct* d = _data();
|
||||
|
||||
return (d && d->value) ? impl::get_value_bool(d->value) : def;
|
||||
if (!d) return def;
|
||||
const char_t* value = d->value;
|
||||
return value ? impl::get_value_bool(value) : def;
|
||||
}
|
||||
|
||||
#ifdef PUGIXML_HAS_LONG_LONG
|
||||
PUGI__FN long long xml_text::as_llong(long long def) const
|
||||
{
|
||||
xml_node_struct* d = _data();
|
||||
|
||||
return (d && d->value) ? impl::get_value_llong(d->value) : def;
|
||||
if (!d) return def;
|
||||
const char_t* value = d->value;
|
||||
return value ? impl::get_value_llong(value) : def;
|
||||
}
|
||||
|
||||
PUGI__FN unsigned long long xml_text::as_ullong(unsigned long long def) const
|
||||
{
|
||||
xml_node_struct* d = _data();
|
||||
|
||||
return (d && d->value) ? impl::get_value_ullong(d->value) : def;
|
||||
if (!d) return def;
|
||||
const char_t* value = d->value;
|
||||
return value ? impl::get_value_ullong(value) : def;
|
||||
}
|
||||
#endif
|
||||
|
||||
PUGI__FN bool xml_text::set(const char_t* rhs, size_t sz)
|
||||
{
|
||||
xml_node_struct* dn = _data_new();
|
||||
|
||||
return dn ? impl::strcpy_insitu(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, sz) : false;
|
||||
}
|
||||
|
||||
PUGI__FN bool xml_text::set(const char_t* rhs)
|
||||
{
|
||||
xml_node_struct* dn = _data_new();
|
||||
|
@ -7294,7 +7423,7 @@ namespace pugi
|
|||
using impl::auto_deleter; // MSVC7 workaround
|
||||
auto_deleter<FILE> file(impl::open_file(path_, (flags & format_save_file_text) ? "w" : "wb"), impl::close_file);
|
||||
|
||||
return impl::save_file_impl(*this, file.data, indent, flags, encoding);
|
||||
return impl::save_file_impl(*this, file.data, indent, flags, encoding) && fclose(file.release()) == 0;
|
||||
}
|
||||
|
||||
PUGI__FN bool xml_document::save_file(const wchar_t* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const
|
||||
|
@ -7302,7 +7431,7 @@ namespace pugi
|
|||
using impl::auto_deleter; // MSVC7 workaround
|
||||
auto_deleter<FILE> file(impl::open_file_wide(path_, (flags & format_save_file_text) ? L"w" : L"wb"), impl::close_file);
|
||||
|
||||
return impl::save_file_impl(*this, file.data, indent, flags, encoding);
|
||||
return impl::save_file_impl(*this, file.data, indent, flags, encoding) && fclose(file.release()) == 0;
|
||||
}
|
||||
|
||||
PUGI__FN xml_node xml_document::document_element() const
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* pugixml parser - version 1.12
|
||||
* pugixml parser - version 1.13
|
||||
* --------------------------------------------------------
|
||||
* Copyright (C) 2006-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
|
||||
* Report bugs and download new versions at https://pugixml.org/
|
||||
|
@ -14,7 +14,7 @@
|
|||
// Define version macro; evaluates to major * 1000 + minor * 10 + patch so that it's safe to use in less-than comparisons
|
||||
// Note: pugixml used major * 100 + minor * 10 + patch format up until 1.9 (which had version identifier 190); starting from pugixml 1.10, the minor version number is two digits
|
||||
#ifndef PUGIXML_VERSION
|
||||
# define PUGIXML_VERSION 1120 // 1.12
|
||||
# define PUGIXML_VERSION 1130 // 1.13
|
||||
#endif
|
||||
|
||||
// Include user configuration file (this can define various configuration macros)
|
||||
|
@ -115,6 +115,8 @@
|
|||
#ifndef PUGIXML_NULL
|
||||
# if __cplusplus >= 201103
|
||||
# define PUGIXML_NULL nullptr
|
||||
# elif defined(_MSC_VER) && _MSC_VER >= 1600
|
||||
# define PUGIXML_NULL nullptr
|
||||
# else
|
||||
# define PUGIXML_NULL 0
|
||||
# endif
|
||||
|
@ -416,6 +418,7 @@ namespace pugi
|
|||
|
||||
// Set attribute name/value (returns false if attribute is empty or there is not enough memory)
|
||||
bool set_name(const char_t* rhs);
|
||||
bool set_value(const char_t* rhs, size_t sz);
|
||||
bool set_value(const char_t* rhs);
|
||||
|
||||
// Set attribute value with type conversion (numbers are converted to strings, boolean is converted to "true"/"false")
|
||||
|
@ -550,6 +553,7 @@ namespace pugi
|
|||
|
||||
// Set node name/value (returns false if node is empty, there is not enough memory, or node can not have name/value)
|
||||
bool set_name(const char_t* rhs);
|
||||
bool set_value(const char_t* rhs, size_t sz);
|
||||
bool set_value(const char_t* rhs);
|
||||
|
||||
// Add attribute with specified name. Returns added attribute, or empty attribute on errors.
|
||||
|
@ -775,6 +779,7 @@ namespace pugi
|
|||
bool as_bool(bool def = false) const;
|
||||
|
||||
// Set text (returns false if object is empty or there is not enough memory)
|
||||
bool set(const char_t* rhs, size_t sz);
|
||||
bool set(const char_t* rhs);
|
||||
|
||||
// Set text with type conversion (numbers are converted to strings, boolean is converted to "true"/"false")
|
||||
|
|
Loading…
Reference in New Issue