diff --git a/Readme.md b/Readme.md
index 9fecfedf5..81fd9fd9d 100644
--- a/Readme.md
+++ b/Readme.md
@@ -8,10 +8,10 @@ A library to import and export various 3d-model-formats including scene-post-pro
+[![Codacy Badge](https://app.codacy.com/project/badge/Grade/9973693b7bdd4543b07084d5d9cf4745)](https://www.codacy.com/gh/assimp/assimp/dashboard?utm_source=github.com&utm_medium=referral&utm_content=assimp/assimp&utm_campaign=Badge_Grade)
[![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master)
[![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Average time to resolve an issue")
-[![Codacy Badge](https://api.codacy.com/project/badge/Grade/5be56faac64f46fc941ac890fb4febef)](https://www.codacy.com/app/kimkulling/assimp?utm_source=github.com&utm_medium=referral&utm_content=assimp/assimp&utm_campaign=Badge_Grade)
[![Total alerts](https://img.shields.io/lgtm/alerts/g/assimp/assimp.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/assimp/assimp/alerts/)
diff --git a/code/AssetLib/3DS/3DSConverter.cpp b/code/AssetLib/3DS/3DSConverter.cpp
index 12ac7e69e..c977867c0 100644
--- a/code/AssetLib/3DS/3DSConverter.cpp
+++ b/code/AssetLib/3DS/3DSConverter.cpp
@@ -212,7 +212,7 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material &oldMat,
mat.AddProperty(&tex, AI_MATKEY_GLOBAL_BACKGROUND_IMAGE);
// Be sure this is only done for the first material
- mBackgroundImage = std::string("");
+ mBackgroundImage = std::string();
}
// At first add the base ambient color of the scene to the material
diff --git a/code/AssetLib/3DS/3DSLoader.cpp b/code/AssetLib/3DS/3DSLoader.cpp
index 3dabf9da1..a25355ccc 100644
--- a/code/AssetLib/3DS/3DSLoader.cpp
+++ b/code/AssetLib/3DS/3DSLoader.cpp
@@ -164,7 +164,7 @@ void Discreet3DSImporter::InternReadFile(const std::string &pFile,
mRootNode->mHierarchyIndex = -1;
mRootNode->mParent = nullptr;
mMasterScale = 1.0f;
- mBackgroundImage = "";
+ mBackgroundImage = std::string();
bHasBG = false;
bIsPrj = false;
diff --git a/code/AssetLib/3MF/D3MFOpcPackage.cpp b/code/AssetLib/3MF/D3MFOpcPackage.cpp
index 16e659ea3..c46b83b03 100644
--- a/code/AssetLib/3MF/D3MFOpcPackage.cpp
+++ b/code/AssetLib/3MF/D3MFOpcPackage.cpp
@@ -188,7 +188,7 @@ bool D3MFOpcPackage::validate() {
std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) {
XmlParser xmlParser;
if (!xmlParser.parse(stream)) {
- return "";
+ return std::string();
}
OpcPackageRelationshipReader reader(xmlParser);
diff --git a/code/AssetLib/AC/ACLoader.h b/code/AssetLib/AC/ACLoader.h
index 77de16b8b..5ae2e80bb 100644
--- a/code/AssetLib/AC/ACLoader.h
+++ b/code/AssetLib/AC/ACLoader.h
@@ -123,9 +123,9 @@ public:
struct Object {
Object() :
type(World),
- name(""),
+ name(),
children(),
- texture(""),
+ texture(),
texRepeat(1.f, 1.f),
texOffset(0.0f, 0.0f),
rotation(),
diff --git a/code/AssetLib/ASE/ASEParser.cpp b/code/AssetLib/ASE/ASEParser.cpp
index 21ec26593..530766730 100644
--- a/code/AssetLib/ASE/ASEParser.cpp
+++ b/code/AssetLib/ASE/ASEParser.cpp
@@ -685,7 +685,7 @@ void Parser::ParseLV3MapBlock(Texture &map) {
// Files with 'None' as map name are produced by
// an Maja to ASE exporter which name I forgot ..
ASSIMP_LOG_WARN("ASE: Skipping invalid map entry");
- map.mMapName = "";
+ map.mMapName = std::string();
}
continue;
diff --git a/code/AssetLib/Blender/BlenderLoader.cpp b/code/AssetLib/Blender/BlenderLoader.cpp
index 989e9d59a..71ab67721 100644
--- a/code/AssetLib/Blender/BlenderLoader.cpp
+++ b/code/AssetLib/Blender/BlenderLoader.cpp
@@ -88,7 +88,7 @@ using namespace Assimp::Blender;
using namespace Assimp::Formatter;
static const aiImporterDesc blenderDesc = {
- "Blender 3D Importer \nhttp://www.blender3d.org",
+ "Blender 3D Importer (http://www.blender3d.org)",
"",
"",
"No animation support yet",
diff --git a/code/AssetLib/Collada/ColladaLoader.cpp b/code/AssetLib/Collada/ColladaLoader.cpp
index 902eebc4b..faaa7cdba 100644
--- a/code/AssetLib/Collada/ColladaLoader.cpp
+++ b/code/AssetLib/Collada/ColladaLoader.cpp
@@ -1241,7 +1241,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
continue;
}
entry.mTargetId = entry.mTransformId;
- entry.mTransformId = "";
+ entry.mTransformId = std::string();
}
entry.mChannel = &(*cit);
diff --git a/code/AssetLib/FBX/FBXMeshGeometry.cpp b/code/AssetLib/FBX/FBXMeshGeometry.cpp
index fd8a0ff98..2bca8dff2 100644
--- a/code/AssetLib/FBX/FBXMeshGeometry.cpp
+++ b/code/AssetLib/FBX/FBXMeshGeometry.cpp
@@ -330,7 +330,7 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop
}
const Element* Name = source["Name"];
- m_uvNames[index] = "";
+ m_uvNames[index] = std::string();
if(Name) {
m_uvNames[index] = ParseTokenAsString(GetRequiredToken(*Name,0));
}
diff --git a/code/AssetLib/FBX/FBXParser.cpp b/code/AssetLib/FBX/FBXParser.cpp
index 046d26c95..37cf83cf9 100644
--- a/code/AssetLib/FBX/FBXParser.cpp
+++ b/code/AssetLib/FBX/FBXParser.cpp
@@ -462,7 +462,7 @@ std::string ParseTokenAsString(const Token& t, const char*& err_out)
if (t.Type() != TokenType_DATA) {
err_out = "expected TOK_DATA token";
- return "";
+ return std::string();
}
if(t.IsBinary())
@@ -470,7 +470,7 @@ std::string ParseTokenAsString(const Token& t, const char*& err_out)
const char* data = t.begin();
if (data[0] != 'S') {
err_out = "failed to parse S(tring), unexpected data type (binary)";
- return "";
+ return std::string();
}
// read string length
@@ -484,13 +484,13 @@ std::string ParseTokenAsString(const Token& t, const char*& err_out)
const size_t length = static_cast(t.end() - t.begin());
if(length < 2) {
err_out = "token is too short to hold a string";
- return "";
+ return std::string();
}
const char* s = t.begin(), *e = t.end() - 1;
if (*s != '\"' || *e != '\"') {
err_out = "expected double quoted string";
- return "";
+ return std::string();
}
return std::string(s+1,length-2);
diff --git a/code/AssetLib/FBX/FBXProperties.cpp b/code/AssetLib/FBX/FBXProperties.cpp
index 2f39fc7dc..1e4cd0ead 100644
--- a/code/AssetLib/FBX/FBXProperties.cpp
+++ b/code/AssetLib/FBX/FBXProperties.cpp
@@ -155,7 +155,7 @@ std::string PeekPropertyName(const Element& element)
ai_assert(element.KeyToken().StringContents() == "P");
const TokenList& tok = element.Tokens();
if(tok.size() < 4) {
- return "";
+ return std::string();
}
return ParseTokenAsString(*tok[0]);
diff --git a/code/AssetLib/IFC/IFCLoader.cpp b/code/AssetLib/IFC/IFCLoader.cpp
index be100df57..df1ca32de 100644
--- a/code/AssetLib/IFC/IFCLoader.cpp
+++ b/code/AssetLib/IFC/IFCLoader.cpp
@@ -567,7 +567,7 @@ typedef std::map Metadata;
// ------------------------------------------------------------------------------------------------
void ProcessMetadata(const Schema_2x3::ListOf, 1, 0> &set, ConversionData &conv, Metadata &properties,
- const std::string &prefix = "",
+ const std::string &prefix = std::string(),
unsigned int nest = 0) {
for (const Schema_2x3::IfcProperty &property : set) {
const std::string &key = prefix.length() > 0 ? (prefix + "." + property.Name) : property.Name;
@@ -618,7 +618,7 @@ void ProcessMetadata(const Schema_2x3::ListOfHasProperties, conv, properties, key, nest + 1);
}
} else {
- properties[key] = "";
+ properties[key] = std::string();
}
}
}
diff --git a/code/AssetLib/Irr/IRRLoader.cpp b/code/AssetLib/Irr/IRRLoader.cpp
index 9c1136499..ed92c93bb 100644
--- a/code/AssetLib/Irr/IRRLoader.cpp
+++ b/code/AssetLib/Irr/IRRLoader.cpp
@@ -859,7 +859,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// Check whether we can read from the file
if (file.get() == nullptr) {
- throw DeadlyImportError("Failed to open IRR file " + pFile + "");
+ throw DeadlyImportError("Failed to open IRR file " + pFile);
}
// Construct the irrXML parser
diff --git a/code/AssetLib/Irr/IRRMeshLoader.cpp b/code/AssetLib/Irr/IRRMeshLoader.cpp
index 97d74026f..edcff6c83 100644
--- a/code/AssetLib/Irr/IRRMeshLoader.cpp
+++ b/code/AssetLib/Irr/IRRMeshLoader.cpp
@@ -135,7 +135,7 @@ void IRRMeshImporter::InternReadFile(const std::string &pFile,
// Check whether we can read from the file
if (file.get() == NULL)
- throw DeadlyImportError("Failed to open IRRMESH file " + pFile + "");
+ throw DeadlyImportError("Failed to open IRRMESH file " + pFile);
// Construct the irrXML parser
XmlParser parser;
diff --git a/code/AssetLib/LWO/LWOFileData.h b/code/AssetLib/LWO/LWOFileData.h
index 70642c537..93ac1a236 100644
--- a/code/AssetLib/LWO/LWOFileData.h
+++ b/code/AssetLib/LWO/LWOFileData.h
@@ -502,7 +502,7 @@ struct Surface {
Surface() :
mColor(0.78431f, 0.78431f, 0.78431f), bDoubleSided(false), mDiffuseValue(1.f), mSpecularValue(0.f), mTransparency(0.f), mGlossiness(0.4f), mLuminosity(0.f), mColorHighlights(0.f), mMaximumSmoothAngle(0.f) // 0 == not specified, no smoothing
,
- mVCMap(""),
+ mVCMap(),
mVCMapType(AI_LWO_RGBA),
mIOR(1.f) // vakuum
,
diff --git a/code/AssetLib/LWS/LWSLoader.h b/code/AssetLib/LWS/LWSLoader.h
index 93251cd5d..cd7a0543e 100644
--- a/code/AssetLib/LWS/LWSLoader.h
+++ b/code/AssetLib/LWS/LWSLoader.h
@@ -88,7 +88,7 @@ struct NodeDesc {
id(),
number(0),
parent(0),
- name(""),
+ name(),
isPivotSet(false),
lightColor(1.f, 1.f, 1.f),
lightIntensity(1.f),
diff --git a/code/AssetLib/MD2/MD2NormalTable.h b/code/AssetLib/MD2/MD2NormalTable.h
index 3eff0d666..b2330d862 100644
--- a/code/AssetLib/MD2/MD2NormalTable.h
+++ b/code/AssetLib/MD2/MD2NormalTable.h
@@ -51,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_MDL_NORMALTABLE_H_INC
-float g_avNormals[162][3] = {
+const float g_avNormals[162][3] = {
{ -0.525731f, 0.000000f, 0.850651f },
{ -0.442863f, 0.238856f, 0.864188f },
{ -0.295242f, 0.000000f, 0.955423f },
diff --git a/code/AssetLib/MDC/MDCNormalTable.h b/code/AssetLib/MDC/MDCNormalTable.h
index f47e97f33..c96eba7bd 100644
--- a/code/AssetLib/MDC/MDCNormalTable.h
+++ b/code/AssetLib/MDC/MDCNormalTable.h
@@ -36,7 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define MDC_NORMAL_TABLE_INCLUDED
/* mdc decoding normal table */
-float mdcNormals[ 256 ][ 3 ] =
+const float mdcNormals[ 256 ][ 3 ] =
{
{ 1.000000f, 0.000000f, 0.000000f },
{ 0.980785f, 0.195090f, 0.000000f },
diff --git a/code/AssetLib/MDL/HalfLife/UniqueNameGenerator.cpp b/code/AssetLib/MDL/HalfLife/UniqueNameGenerator.cpp
index 72081ea73..dde81454b 100644
--- a/code/AssetLib/MDL/HalfLife/UniqueNameGenerator.cpp
+++ b/code/AssetLib/MDL/HalfLife/UniqueNameGenerator.cpp
@@ -95,7 +95,7 @@ void UniqueNameGenerator::make_unique(std::vector &names) {
auto generate_unique_name = [&](const std::string &base_name) -> std::string {
auto *duplicate_info = &names_to_duplicates[base_name];
- std::string new_name = "";
+ std::string new_name;
bool found_identical_name;
bool tried_with_base_name_only = false;
diff --git a/code/AssetLib/MMD/MMDImporter.cpp b/code/AssetLib/MMD/MMDImporter.cpp
index e4ecc1445..2895c3879 100644
--- a/code/AssetLib/MMD/MMDImporter.cpp
+++ b/code/AssetLib/MMD/MMDImporter.cpp
@@ -75,7 +75,7 @@ using namespace std;
// Default constructor
MMDImporter::MMDImporter() :
m_Buffer(),
- m_strAbsPath("") {
+ m_strAbsPath() {
DefaultIOSystem io;
m_strAbsPath = io.getOsSeparator();
}
diff --git a/code/AssetLib/MMD/MMDPmxParser.cpp b/code/AssetLib/MMD/MMDPmxParser.cpp
index 320182c3d..cb4787efd 100644
--- a/code/AssetLib/MMD/MMDPmxParser.cpp
+++ b/code/AssetLib/MMD/MMDPmxParser.cpp
@@ -91,7 +91,7 @@ namespace pmx
std::vector buffer;
if (size == 0)
{
- return std::string("");
+ return std::string();
}
buffer.reserve(size);
stream->read((char*) buffer.data(), size);
diff --git a/code/AssetLib/OpenGEX/OpenGEXImporter.cpp b/code/AssetLib/OpenGEX/OpenGEXImporter.cpp
index 14c9ea37f..b29aeeeb1 100644
--- a/code/AssetLib/OpenGEX/OpenGEXImporter.cpp
+++ b/code/AssetLib/OpenGEX/OpenGEXImporter.cpp
@@ -206,7 +206,7 @@ USE_ODDLPARSER_NS
//------------------------------------------------------------------------------------------------
static void propId2StdString(Property *prop, std::string &name, std::string &key) {
- name = key = "";
+ name = key = std::string();
if (nullptr == prop) {
return;
}
diff --git a/code/AssetLib/OpenGEX/OpenGEXImporter.h b/code/AssetLib/OpenGEX/OpenGEXImporter.h
index 677ef73aa..3c26a4a30 100644
--- a/code/AssetLib/OpenGEX/OpenGEXImporter.h
+++ b/code/AssetLib/OpenGEX/OpenGEXImporter.h
@@ -79,7 +79,7 @@ struct MetricInfo {
int m_intValue;
MetricInfo()
- : m_stringValue( "" )
+ : m_stringValue( )
, m_floatValue( 0.0f )
, m_intValue( -1 ) {
// empty
diff --git a/code/AssetLib/Q3BSP/Q3BSPFileData.h b/code/AssetLib/Q3BSP/Q3BSPFileData.h
index ba826d541..a121cdbcd 100644
--- a/code/AssetLib/Q3BSP/Q3BSPFileData.h
+++ b/code/AssetLib/Q3BSP/Q3BSPFileData.h
@@ -178,7 +178,7 @@ struct Q3BSPModel {
m_Textures(),
m_Lightmaps(),
m_EntityData(),
- m_ModelName( "" )
+ m_ModelName()
{
// empty
}
diff --git a/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp b/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp
index c66582fea..85e79a12c 100644
--- a/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp
+++ b/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp
@@ -113,7 +113,7 @@ static void extractIds(const std::string &key, int &id1, int &id2) {
// ------------------------------------------------------------------------------------------------
// Local helper function to normalize filenames.
static void normalizePathName(const std::string &rPath, std::string &normalizedPath) {
- normalizedPath = "";
+ normalizedPath = std::string();
if (rPath.empty()) {
return;
}
@@ -183,7 +183,7 @@ void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene *scene,
throw DeadlyImportError("Failed to open file ", rFile, ".");
}
- std::string archiveName(""), mapName("");
+ std::string archiveName, mapName;
separateMapName(rFile, archiveName, mapName);
if (mapName.empty()) {
@@ -202,8 +202,8 @@ void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene *scene,
// ------------------------------------------------------------------------------------------------
// Separates the map name from the import name.
void Q3BSPFileImporter::separateMapName(const std::string &importName, std::string &archiveName, std::string &mapName) {
- archiveName = "";
- mapName = "";
+ archiveName = std::string();
+ mapName = std::string();
if (importName.empty()) {
return;
}
@@ -221,7 +221,7 @@ void Q3BSPFileImporter::separateMapName(const std::string &importName, std::stri
// ------------------------------------------------------------------------------------------------
// Returns the first map in the map archive.
bool Q3BSPFileImporter::findFirstMapInArchive(ZipArchiveIOSystem &bspArchive, std::string &mapName) {
- mapName = "";
+ mapName = std::string();
std::vector fileList;
bspArchive.getFileListExtension(fileList, "bsp");
if (fileList.empty()) {
@@ -440,7 +440,7 @@ void Q3BSPFileImporter::createMaterials(const Q3BSP::Q3BSPModel *pModel, aiScene
if (-1 != textureId) {
sQ3BSPTexture *pTexture = pModel->m_Textures[textureId];
if (nullptr != pTexture) {
- std::string tmp("*"), texName("");
+ std::string tmp("*"), texName;
tmp += pTexture->strName;
tmp += ".jpg";
normalizePathName(tmp, texName);
@@ -512,7 +512,7 @@ size_t Q3BSPFileImporter::countTriangles(const std::vector
// ------------------------------------------------------------------------------------------------
// Creates the faces-to-material map.
void Q3BSPFileImporter::createMaterialMap(const Q3BSP::Q3BSPModel *pModel) {
- std::string key("");
+ std::string key;
std::vector *pCurFaceArray = nullptr;
for (size_t idx = 0; idx < pModel->m_Faces.size(); idx++) {
Q3BSP::sQ3BSPFace *pQ3BSPFace = pModel->m_Faces[idx];
@@ -660,7 +660,7 @@ bool Q3BSPFileImporter::expandFile(ZipArchiveIOSystem *pArchive, const std::stri
if (rExtList.empty()) {
rFile = rFilename;
- rExt = "";
+ rExt = std::string();
return true;
}
diff --git a/code/AssetLib/X/XFileHelper.h b/code/AssetLib/X/XFileHelper.h
index 8ba166350..5bdaf4d35 100644
--- a/code/AssetLib/X/XFileHelper.h
+++ b/code/AssetLib/X/XFileHelper.h
@@ -130,7 +130,7 @@ struct Mesh {
std::vector mBones;
- explicit Mesh(const std::string &pName = "") AI_NO_EXCEPT
+ explicit Mesh(const std::string &pName = std::string()) AI_NO_EXCEPT
: mName( pName )
, mPositions()
, mPosFaces()
diff --git a/code/AssetLib/XGL/XGLLoader.cpp b/code/AssetLib/XGL/XGLLoader.cpp
index 824f0c2c3..00e8bafb2 100644
--- a/code/AssetLib/XGL/XGLLoader.cpp
+++ b/code/AssetLib/XGL/XGLLoader.cpp
@@ -142,7 +142,7 @@ void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// check whether we can read from the file
if (stream.get() == NULL) {
- throw DeadlyImportError("Failed to open XGL/ZGL file " + pFile + "");
+ throw DeadlyImportError("Failed to open XGL/ZGL file " + pFile);
}
// see if its compressed, if so uncompress it
diff --git a/code/AssetLib/glTF/glTFAsset.h b/code/AssetLib/glTF/glTFAsset.h
index 623f18173..da49a1737 100644
--- a/code/AssetLib/glTF/glTFAsset.h
+++ b/code/AssetLib/glTF/glTFAsset.h
@@ -1033,7 +1033,7 @@ namespace glTF
AssetMetadata()
: premultipliedAlpha(false)
- , version("")
+ , version()
{
}
};
diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h
index fad5cba83..26a2f64c3 100644
--- a/code/AssetLib/glTF2/glTF2Asset.h
+++ b/code/AssetLib/glTF2/glTF2Asset.h
@@ -1071,7 +1071,7 @@ struct AssetMetadata {
void Read(Document &doc);
AssetMetadata() :
- version("") {}
+ version() {}
};
//
diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl
index 77537028f..8a793c144 100644
--- a/code/AssetLib/glTF2/glTF2Asset.inl
+++ b/code/AssetLib/glTF2/glTF2Asset.inl
@@ -162,6 +162,9 @@ inline static bool ReadValue(Value &val, T &out) {
template
inline static bool ReadMember(Value &obj, const char *id, T &out) {
+ if (!obj.IsObject()) {
+ return false;
+ }
Value::MemberIterator it = obj.FindMember(id);
if (it != obj.MemberEnd()) {
return ReadHelper::Read(it->value, out);
@@ -176,6 +179,9 @@ inline static T MemberOrDefault(Value &obj, const char *id, T defaultValue) {
}
inline Value *FindMember(Value &val, const char *id) {
+ if (!val.IsObject()) {
+ return nullptr;
+ }
Value::MemberIterator it = val.FindMember(id);
return (it != val.MemberEnd()) ? &it->value : nullptr;
}
@@ -193,6 +199,9 @@ inline void throwUnexpectedTypeError(const char (&expectedTypeName)[N], const ch
// Look-up functions with type checks. Context and extra context help the user identify the problem if there's an error.
inline Value *FindStringInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
+ if (!val.IsObject()) {
+ return nullptr;
+ }
Value::MemberIterator it = val.FindMember(memberId);
if (it == val.MemberEnd()) {
return nullptr;
@@ -204,6 +213,9 @@ inline Value *FindStringInContext(Value &val, const char *memberId, const char*
}
inline Value *FindNumberInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
+ if (!val.IsObject()) {
+ return nullptr;
+ }
Value::MemberIterator it = val.FindMember(memberId);
if (it == val.MemberEnd()) {
return nullptr;
@@ -215,6 +227,9 @@ inline Value *FindNumberInContext(Value &val, const char *memberId, const char*
}
inline Value *FindUIntInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
+ if (!val.IsObject()) {
+ return nullptr;
+ }
Value::MemberIterator it = val.FindMember(memberId);
if (it == val.MemberEnd()) {
return nullptr;
@@ -226,6 +241,9 @@ inline Value *FindUIntInContext(Value &val, const char *memberId, const char* co
}
inline Value *FindArrayInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
+ if (!val.IsObject()) {
+ return nullptr;
+ }
Value::MemberIterator it = val.FindMember(memberId);
if (it == val.MemberEnd()) {
return nullptr;
@@ -237,6 +255,9 @@ inline Value *FindArrayInContext(Value &val, const char *memberId, const char* c
}
inline Value *FindObjectInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
+ if (!val.IsObject()) {
+ return nullptr;
+ }
Value::MemberIterator it = val.FindMember(memberId);
if (it == val.MemberEnd()) {
return nullptr;
@@ -886,7 +907,7 @@ inline void Accessor::Read(Value &obj, Asset &r) {
componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE);
{
const Value* countValue = FindUInt(obj, "count");
- if (!countValue || countValue->GetInt() < 1)
+ if (!countValue || countValue->GetUint() < 1)
{
throw DeadlyImportError("A strictly positive count value is required, when reading ", id.c_str(), name.empty() ? "" : " (" + name + ")");
}
@@ -1105,7 +1126,9 @@ inline Accessor::Indexer::Indexer(Accessor &acc) :
template
T Accessor::Indexer::GetValue(int i) {
ai_assert(data);
- ai_assert(i * stride < accessor.GetMaxByteSize());
+ if (i * stride >= accessor.GetMaxByteSize()) {
+ throw DeadlyImportError("GLTF: Invalid index ", i, ", count out of range for buffer with stride ", stride, " and size ", accessor.GetMaxByteSize(), ".");
+ }
// Ensure that the memcpy doesn't overwrite the local.
const size_t sizeToCopy = std::min(elemSize, sizeof(T));
T value = T();
diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp
index ab1f01bf8..f34b1b451 100644
--- a/code/AssetLib/glTF2/glTF2Importer.cpp
+++ b/code/AssetLib/glTF2/glTF2Importer.cpp
@@ -1172,7 +1172,7 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler
static const float kMillisecondsFromSeconds = 1000.f;
- if (samplers.translation) {
+ if (samplers.translation && samplers.translation->input && samplers.translation->output) {
float *times = nullptr;
samplers.translation->input->ExtractData(times);
aiVector3D *values = nullptr;
@@ -1196,7 +1196,7 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler
anim->mPositionKeys->mValue.z = node.translation.value[2];
}
- if (samplers.rotation) {
+ if (samplers.rotation && samplers.rotation->input && samplers.rotation->output) {
float *times = nullptr;
samplers.rotation->input->ExtractData(times);
aiQuaternion *values = nullptr;
@@ -1224,7 +1224,7 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler
anim->mRotationKeys->mValue.w = node.rotation.value[3];
}
- if (samplers.scale) {
+ if (samplers.scale && samplers.scale->input && samplers.scale->output) {
float *times = nullptr;
samplers.scale->input->ExtractData(times);
aiVector3D *values = nullptr;
diff --git a/code/Common/BaseImporter.cpp b/code/Common/BaseImporter.cpp
index 0657216cf..7da615ac4 100644
--- a/code/Common/BaseImporter.cpp
+++ b/code/Common/BaseImporter.cpp
@@ -271,7 +271,7 @@ std::string BaseImporter::GetExtension(const std::string &file) {
// no file extension at all
if (pos == std::string::npos) {
- return "";
+ return std::string();
}
// thanks to Andy Maloney for the hint
diff --git a/code/Common/DefaultIOStream.cpp b/code/Common/DefaultIOStream.cpp
index 115fea63c..ba9b9d625 100644
--- a/code/Common/DefaultIOStream.cpp
+++ b/code/Common/DefaultIOStream.cpp
@@ -90,10 +90,12 @@ DefaultIOStream::~DefaultIOStream() {
size_t DefaultIOStream::Read(void *pvBuffer,
size_t pSize,
size_t pCount) {
+ if (0 == pCount) {
+ return 0;
+ }
ai_assert(nullptr != pvBuffer);
ai_assert(0 != pSize);
- ai_assert(0 != pCount);
-
+
return (mFile ? ::fread(pvBuffer, pSize, pCount, mFile) : 0);
}
diff --git a/code/Common/FileSystemFilter.h b/code/Common/FileSystemFilter.h
index 1440cf97d..92f199870 100644
--- a/code/Common/FileSystemFilter.h
+++ b/code/Common/FileSystemFilter.h
@@ -76,7 +76,7 @@ public:
if (std::string::npos != (ss2 = mBase.find_last_of("\\/"))) {
mBase.erase(ss2,mBase.length()-ss2);
} else {
- mBase = "";
+ mBase = std::string();
}
// make sure the directory is terminated properly
diff --git a/code/Common/Importer.cpp b/code/Common/Importer.cpp
index db7fc9e1c..8cea2cd09 100644
--- a/code/Common/Importer.cpp
+++ b/code/Common/Importer.cpp
@@ -149,7 +149,7 @@ void AllocateFromAssimpHeap::operator delete[] ( void* data) {
Importer::Importer()
: pimpl( new ImporterPimpl ) {
pimpl->mScene = nullptr;
- pimpl->mErrorString = "";
+ pimpl->mErrorString = std::string();
// Allocate a default IO handler
pimpl->mIOHandler = new DefaultIOSystem;
@@ -387,7 +387,7 @@ void Importer::FreeScene( ) {
delete pimpl->mScene;
pimpl->mScene = nullptr;
- pimpl->mErrorString = "";
+ pimpl->mErrorString = std::string();
pimpl->mException = std::exception_ptr();
ASSIMP_END_EXCEPTION_REGION(void);
}
@@ -434,7 +434,7 @@ aiScene* Importer::GetOrphanedScene() {
ASSIMP_BEGIN_EXCEPTION_REGION();
pimpl->mScene = nullptr;
- pimpl->mErrorString = ""; // reset error string
+ pimpl->mErrorString = std::string();
pimpl->mException = std::exception_ptr();
ASSIMP_END_EXCEPTION_REGION(aiScene*);
diff --git a/code/Common/SceneCombiner.cpp b/code/Common/SceneCombiner.cpp
index e39660cd6..fe00dfe1f 100644
--- a/code/Common/SceneCombiner.cpp
+++ b/code/Common/SceneCombiner.cpp
@@ -45,7 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// possible as new fields are added to assimp structures.
// ----------------------------------------------------------------------------
-/**
+/**
* @file Implements Assimp::SceneCombiner. This is a smart utility
* class that combines multiple scenes, meshes, ... into one. Currently
* these utilities are used by the IRR and LWS loaders and the
@@ -359,7 +359,7 @@ void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vectormNumTextures) {
- aiTexture **pip = dest->mTextures = new aiTexture *[dest->mNumMaterials];
+ aiTexture **pip = dest->mTextures = new aiTexture *[dest->mNumTextures];
cnt = 0;
for (unsigned int n = 0; n < src.size(); ++n) {
SceneHelper *cur = &src[n];
@@ -638,6 +638,8 @@ void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vectormMaterials = nullptr;
delete[] deleteMe->mAnimations;
deleteMe->mAnimations = nullptr;
+ delete[] deleteMe->mTextures;
+ deleteMe->mTextures = nullptr;
deleteMe->mRootNode = nullptr;
diff --git a/code/Common/scene.cpp b/code/Common/scene.cpp
index 82430f5fc..67feb7afb 100644
--- a/code/Common/scene.cpp
+++ b/code/Common/scene.cpp
@@ -43,7 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include
aiNode::aiNode()
-: mName("")
+: mName()
, mParent(nullptr)
, mNumChildren(0)
, mChildren(nullptr)
diff --git a/code/PostProcessing/RemoveRedundantMaterials.h b/code/PostProcessing/RemoveRedundantMaterials.h
index 6b4f8b1fb..4210a7fe2 100644
--- a/code/PostProcessing/RemoveRedundantMaterials.h
+++ b/code/PostProcessing/RemoveRedundantMaterials.h
@@ -81,7 +81,7 @@ public:
/** @brief Set list of fixed (inmutable) materials
* @param fixed See #AI_CONFIG_PP_RRM_EXCLUDE_LIST
*/
- void SetFixedMaterialsString(const std::string& fixed = "") {
+ void SetFixedMaterialsString(const std::string& fixed = std::string()) {
mConfigFixedMaterials = fixed;
}
diff --git a/code/PostProcessing/SortByPTypeProcess.cpp b/code/PostProcessing/SortByPTypeProcess.cpp
index dd6902692..20ab63249 100644
--- a/code/PostProcessing/SortByPTypeProcess.cpp
+++ b/code/PostProcessing/SortByPTypeProcess.cpp
@@ -135,7 +135,9 @@ void SortByPTypeProcess::Execute(aiScene *pScene) {
std::vector::iterator meshIdx = replaceMeshIndex.begin();
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
aiMesh *const mesh = pScene->mMeshes[i];
- ai_assert(0 != mesh->mPrimitiveTypes);
+ if (mesh->mPrimitiveTypes == 0) {
+ throw DeadlyImportError("Mesh with invalid primitive type: ", mesh->mName.C_Str());
+ }
// if there's just one primitive type in the mesh there's nothing to do for us
unsigned int num = 0;
diff --git a/contrib/zip/.gitignore b/contrib/zip/.gitignore
deleted file mode 100644
index 49b2cb2fd..000000000
--- a/contrib/zip/.gitignore
+++ /dev/null
@@ -1,58 +0,0 @@
-/build/
-/test/build/
-/xcodeproj/
-.vscode/
-
-# Object files
-*.o
-*.ko
-*.obj
-*.elf
-
-# Precompiled Headers
-*.gch
-*.pch
-
-# Libraries
-*.lib
-*.a
-*.la
-*.lo
-
-# Shared objects (inc. Windows DLLs)
-*.dll
-*.so
-*.so.*
-*.dylib
-*.suo
-
-# Executables
-*.exe
-*.out
-*.app
-*.i*86
-*.x86_64
-*.hex
-
-# Temporary
-*.swp
-.DS_Store
-
-# CMake
-CMakeScripts
-*.cmake
-
-# Xcode
-*.build
-*.xcodeproj
-zip.sln
-zip.vcxproj.filters
-zip.vcxproj
-ALL_BUILD.vcxproj.filters
-ALL_BUILD.vcxproj
-CMakeFiles/
-zip.dir/
-test/test.exe.vcxproj.filters
-test/test.exe.vcxproj
-test/test.exe.dir/
-
diff --git a/contrib/zip/CMakeLists.txt b/contrib/zip/CMakeLists.txt
index cdfa94b3b..bba4e7bde 100644
--- a/contrib/zip/CMakeLists.txt
+++ b/contrib/zip/CMakeLists.txt
@@ -1,26 +1,29 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.4)
project(zip
LANGUAGES C
- VERSION "0.1.18")
+ VERSION "0.1.19")
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
-
+set(CMAKE_VERBOSE_MAKEFILE ON)
option(CMAKE_DISABLE_TESTING "Disable test creation" OFF)
-if (MSVC)
- # Use secure functions by default and suppress warnings about "deprecated" functions
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1")
-elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR
- "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR
- "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall -Wextra -Werror -pedantic")
-endif (MSVC)
-
# zip
set(SRC src/miniz.h src/zip.h src/zip.c)
-add_library(${PROJECT_NAME} ${SRC})
+
+# this is the "object library" target: compiles the sources only once
+add_library(OBJLIB OBJECT ${SRC})
+# shared libraries need PIC
+set_property(TARGET OBJLIB PROPERTY POSITION_INDEPENDENT_CODE 1)
+
+# static and shared libraries built from the same object files
+if (BUILD_SHARED_LIBS)
+ add_library(${PROJECT_NAME} SHARED $)
+ include(GenerateExportHeader)
+ generate_export_header(${PROJECT_NAME})
+else()
+ add_library(${PROJECT_NAME} STATIC $)
+endif()
+
target_include_directories(${PROJECT_NAME} PUBLIC
$
$
@@ -34,6 +37,17 @@ if (NOT CMAKE_DISABLE_TESTING)
add_sanitizers(${PROJECT_NAME} ${test_out})
endif()
+if (MSVC)
+ # Use secure functions by default and suppress warnings about "deprecated" functions
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1")
+elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR
+ "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR
+ "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wall -Wextra -Werror -pedantic -Wno-deprecated")
+endif (MSVC)
+
####
# Installation (https://github.com/forexample/package-example) {
diff --git a/contrib/zip/README.md b/contrib/zip/README.md
index bdd0822b6..308327a3f 100644
--- a/contrib/zip/README.md
+++ b/contrib/zip/README.md
@@ -2,7 +2,6 @@
This is done by hacking awesome [miniz](https://code.google.com/p/miniz) library and layering functions on top of the miniz v1.15 API.
[![Build](https://github.com/kuba--/zip/workflows/build/badge.svg)](https://github.com/kuba--/zip/actions?query=workflow%3Abuild)
-[![Version](https://badge.fury.io/gh/kuba--%2Fzip.svg)](https://github.com/kuba--/zip/releases)
# The Idea
@@ -155,10 +154,52 @@ struct zip_t *zip = zip_open("foo.zip", 0, 'r');
zip_close(zip);
```
+* Create a new zip archive in memory (stream API).
+
+```c
+char *outbuf = NULL;
+size_t outbufsize = 0;
+
+const char *inbuf = "Append some data here...\0";
+struct zip_t *zip = zip_stream_open(NULL, 0, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
+{
+ zip_entry_open(zip, "foo-1.txt");
+ {
+ zip_entry_write(zip, inbuf, strlen(inbuf));
+ }
+ zip_entry_close(zip);
+
+ /* copy compressed stream into outbuf */
+ zip_stream_copy(zip, (void **)&outbuf, &outbufsize);
+}
+zip_stream_close(zip);
+
+free(outbuf);
+```
+
+* Extract a zip entry into a memory (stream API).
+
+```c
+char *buf = NULL;
+ssize_t bufsize = 0;
+
+struct zip_t *zip = zip_stream_open(zipstream, zipstreamsize, 0, 'r');
+{
+ zip_entry_open(zip, "foo-1.txt");
+ {
+ zip_entry_read(zip, (void **)&buf, &bufsize);
+ }
+ zip_entry_close(zip);
+}
+zip_stream_close(zip);
+
+free(buf);
+```
+
* List of all zip entries
```c
struct zip_t *zip = zip_open("foo.zip", 0, 'r');
-int i, n = zip_total_entries(zip);
+int i, n = zip_entries_total(zip);
for (i = 0; i < n; ++i) {
zip_entry_openbyindex(zip, i);
{
@@ -172,6 +213,49 @@ for (i = 0; i < n; ++i) {
zip_close(zip);
```
+* Compress folder (recursively)
+```c
+void zip_walk(struct zip_t *zip, const char *path) {
+ DIR *dir;
+ struct dirent *entry;
+ char fullpath[MAX_PATH];
+ struct stat s;
+
+ memset(fullpath, 0, MAX_PATH);
+ dir = opendir(path);
+ assert(dir);
+
+ while ((entry = readdir(dir))) {
+ // skip "." and ".."
+ if (!strcmp(entry->d_name, ".\0") || !strcmp(entry->d_name, "..\0"))
+ continue;
+
+ snprintf(fullpath, sizeof(fullpath), "%s/%s", path, entry->d_name);
+ stat(fullpath, &s);
+ if (S_ISDIR(s.st_mode))
+ zip_walk(zip, fullpath);
+ else {
+ zip_entry_open(zip, fullpath);
+ zip_entry_fwrite(zip, fullpath);
+ zip_entry_close(zip);
+ }
+ }
+
+ closedir(dir);
+}
+```
+
+* Deletes zip archive entries.
+```c
+char *entries[] = {"unused.txt", "remove.ini", "delete.me"};
+
+struct zip_t *zip = zip_open("foo.zip", 0, 'd');
+{
+ zip_entries_delete(zip, entries, 3);
+}
+zip_close(zip);
+```
+
# Bindings
Compile zip library as a dynamic library.
```shell
@@ -181,7 +265,7 @@ $ cmake -DBUILD_SHARED_LIBS=true ..
$ make
```
-### Go (cgo)
+### [Go](https://golang.org) (cgo)
```go
package main
@@ -211,7 +295,7 @@ func main() {
}
```
-### Rust (ffi)
+### [Rust](https://www.rust-lang.org) (ffi)
```rust
extern crate libc;
use std::ffi::CString;
@@ -236,7 +320,7 @@ extern "C" {
}
fn main() {
- let path = CString::new("/tmp/test.zip").unwrap();
+ let path = CString::new("/tmp/rust.zip").unwrap();
let mode: libc::c_char = 'w' as libc::c_char;
let entryname = CString::new("test.txt").unwrap();
@@ -258,7 +342,7 @@ fn main() {
}
```
-### Ruby (ffi)
+### [Ruby](http://www.ruby-lang.org) (ffi)
Install _ffi_ gem.
```shell
$ gem install ffi
@@ -291,7 +375,7 @@ Zip.zip_entry_close(ptr)
Zip.zip_close(ptr)
```
-### Python (cffi)
+### [Python](https://www.python.org) (cffi)
Install _cffi_ package
```shell
$ pip install cffi
@@ -325,7 +409,36 @@ Zip.zip_entry_close(ptr)
Zip.zip_close(ptr)
```
-### Ring
+### [Never](https://never-lang.readthedocs.io/) (ffi)
+```never
+extern "libzip.so" func zip_open(zipname: string, level: int, mode: char) -> c_ptr
+extern "libzip.so" func zip_close(zip: c_ptr) -> void
+
+extern "libzip.so" func zip_entry_open(zip: c_ptr, entryname: string) -> int
+extern "libzip.so" func zip_entry_close(zip: c_ptr) -> int
+extern "libzip.so" func zip_entry_write(zip: c_ptr, buf: string, bufsize: int) -> int
+extern "libzip.so" func zip_entry_fwrite(zip: c_ptr, filename: string) -> int
+
+func main() -> int
+{
+ let content = "Test content"
+
+ let zip = zip_open("/tmp/never.zip", 6, 'w');
+
+ zip_entry_open(zip, "test.file");
+ zip_entry_fwrite(zip, "/tmp/test.txt");
+ zip_entry_close(zip);
+
+ zip_entry_open(zip, "test.content");
+ zip_entry_write(zip, content, length(content));
+ zip_entry_close(zip);
+
+ zip_close(zip);
+ 0
+}
+```
+
+### [Ring](http://ring-lang.net)
The language comes with RingZip based on this library
```ring
load "ziplib.ring"
@@ -342,13 +455,15 @@ new Zip {
}
```
-# Contribution Rules/Coding Standards
-No need to throw away your coding style, just do your best to follow default clang-format style.
-Apply `clang-format` to the source files before commit:
-```sh
-for file in $(git ls-files | \grep -E '\.(c|h)$' | \grep -v -- '#')
-do
- clang-format -i $file
-done
-```
+# Check out more cool projects which use this library:
+- [Filament](https://github.com/google/filament): Filament is a real-time physically based rendering engine for Android, iOS, Linux, macOS, Windows, and WebGL. It is designed to be as small as possible and as efficient as possible on Android.
+- [Hermes JS Engine](https://github.com/facebook/hermes): Hermes is a JavaScript engine optimized for fast start-up of React Native apps on Android. It features ahead-of-time static optimization and compact bytecode.
+- [Open Asset Import Library](https://github.com/assimp/assimp): A library to import and export various 3d-model-formats including scene-post-processing to generate missing render data.
+- [PowerToys](https://github.com/microsoft/PowerToys): Set of utilities for power users to tune and streamline their Windows 10 experience for greater productivity.
+- [The Ring Programming Language](https://ring-lang.github.io): Innovative and practical general-purpose multi-paradigm language.
+- [The V Programming Language](https://github.com/vlang/v): Simple, fast, safe, compiled. For developing maintainable software.
+- [TIC-80](https://github.com/nesbox/TIC-80): TIC-80 is a FREE and OPEN SOURCE fantasy computer for making, playing and sharing tiny games.
+- [Urho3D](https://github.com/urho3d/Urho3D): Urho3D is a free lightweight, cross-platform 2D and 3D game engine implemented in C++ and released under the MIT license. Greatly inspired by OGRE and Horde3D.
+- [Vcpkg](https://github.com/microsoft/vcpkg): Vcpkg helps you manage C and C++ libraries on Windows, Linux and MacOS.
+- [and more...](https://grep.app/search?q=kuba--/zip)
diff --git a/contrib/zip/src/miniz.h b/contrib/zip/src/miniz.h
index 7570ae929..0a5560b24 100644
--- a/contrib/zip/src/miniz.h
+++ b/contrib/zip/src/miniz.h
@@ -400,7 +400,7 @@ typedef enum {
#ifndef MINIZ_NO_ZLIB_APIS
// Heap allocation callbacks.
-// Note that mz_alloc_func parameter types purpsosely differ from zlib's:
+// Note that mz_alloc_func parameter types purposely differ from zlib's:
// items/size is size_t, not unsigned long.
typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);
typedef void (*mz_free_func)(void *opaque, void *address);
@@ -2194,7 +2194,8 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r,
} else
tree_cur = pTable->m_tree[-tree_cur - 1];
}
- tree_cur -= ((rev_code >>= 1) & 1);
+ rev_code >>= 1;
+ tree_cur -= (rev_code & 1);
pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
}
if (r->m_type == 2) {
@@ -3970,6 +3971,7 @@ mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits,
#ifdef _MSC_VER
#pragma warning(push)
+#pragma warning(disable : 4121 4127 4244)
#pragma warning(disable : 4204) // nonstandard extension used : non-constant
// aggregate initializer (also supported by GNU
// C and C99, so no big deal)
@@ -4098,10 +4100,6 @@ void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h,
pLen_out, 6, MZ_FALSE);
}
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
// ------------------- .ZIP archive reading
#ifndef MINIZ_NO_ARCHIVE_APIS
@@ -4112,18 +4110,39 @@ void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h,
#include
#include
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) || defined(__MINGW32__)
+
+#include
+
+static wchar_t *str2wstr(const char *str) {
+ int len = (int) strlen(str) + 1;
+ wchar_t *wstr = malloc(len * sizeof(wchar_t));
+ MultiByteToWideChar(CP_UTF8, 0, str, len * sizeof(char), wstr, len);
+ return wstr;
+}
+
static FILE *mz_fopen(const char *pFilename, const char *pMode) {
- FILE *pFile = NULL;
- fopen_s(&pFile, pFilename, pMode);
+ wchar_t *wFilename = str2wstr(pFilename);
+ wchar_t *wMode = str2wstr(pMode);
+ FILE *pFile = _wfopen(wFilename, wMode);
+
+ free(wFilename);
+ free(wMode);
+
return pFile;
}
+
static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) {
- FILE *pFile = NULL;
- if (freopen_s(&pFile, pPath, pMode, pStream))
- return NULL;
+ wchar_t *wPath = str2wstr(pPath);
+ wchar_t *wMode = str2wstr(pMode);
+ FILE *pFile = _wfreopen(wPath, wMode, pStream);
+
+ free(wPath);
+ free(wMode);
+
return pFile;
}
+
#ifndef MINIZ_NO_TIME
#include
#endif
@@ -4144,7 +4163,7 @@ static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) {
#include
#endif
#define MZ_FILE FILE
-#define MZ_FOPEN(f, m) fopen(f, m)
+#define MZ_FOPEN(f, m) mz_fopen
#define MZ_FCLOSE fclose
#define MZ_FREAD fread
#define MZ_FWRITE fwrite
@@ -4153,7 +4172,7 @@ static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) {
#define MZ_FILE_STAT_STRUCT _stat
#define MZ_FILE_STAT _stat
#define MZ_FFLUSH fflush
-#define MZ_FREOPEN(f, m, s) freopen(f, m, s)
+#define MZ_FREOPEN(f, m, s) mz_freopen
#define MZ_DELETE_FILE remove
#elif defined(__TINYC__)
#ifndef MINIZ_NO_TIME
@@ -5361,13 +5380,9 @@ mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip,
} else {
// Temporarily allocate a read buffer.
read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
-#if defined(_MSC_VER) && !defined(__clang__)
- if (((0, sizeof(size_t) == sizeof(mz_uint32))) &&
- (read_buf_size > 0x7FFFFFFF))
-#else
if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
-#endif
return MZ_FALSE;
+
if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
(size_t)read_buf_size)))
return MZ_FALSE;
@@ -5454,11 +5469,7 @@ void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index,
uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
-#if defined(_MSC_VER) && !defined(__clang__)
- if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
-#else
if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
-#endif
return NULL;
if (NULL ==
(pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
@@ -5560,14 +5571,10 @@ mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip,
if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) {
// The file is stored or the caller has requested the compressed data.
if (pZip->m_pState->m_pMem) {
-#if defined (_MSC_VER) && !defined(__clang__)
- if (((0, sizeof(size_t) == sizeof(mz_uint32))) &&
- (file_stat.m_comp_size > 0xFFFFFFFF))
-#else
if (((sizeof(size_t) == sizeof(mz_uint32))) &&
(file_stat.m_comp_size > 0xFFFFFFFF))
-#endif
return MZ_FALSE;
+
if (pCallback(pOpaque, out_buf_ofs, pRead_buf,
(size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
status = TINFL_STATUS_FAILED;
@@ -6085,7 +6092,7 @@ mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip) {
if (!pZip->m_file_offset_alignment)
return 0;
n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
- return (mz_uint)(pZip->m_file_offset_alignment - n) &
+ return (pZip->m_file_offset_alignment - n) &
(pZip->m_file_offset_alignment - 1);
}
@@ -6289,7 +6296,10 @@ mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name,
mz_uint32 ext_attributes) {
mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
mz_uint16 method = 0, dos_time = 0, dos_date = 0;
+#ifndef MINIZ_NO_TIME
time_t file_modified_time;
+#endif
+
mz_uint64 local_dir_header_ofs, cur_archive_file_ofs, uncomp_size = 0,
comp_size = 0;
size_t archive_name_size;
@@ -6326,10 +6336,12 @@ mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name,
comment_size + archive_name_size) > 0xFFFFFFFF))
return MZ_FALSE;
+#ifndef MINIZ_NO_TIME
memset(&file_modified_time, 0, sizeof(file_modified_time));
if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time))
return MZ_FALSE;
mz_zip_time_t_to_dos_time(file_modified_time, &dos_time, &dos_date);
+#endif
pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
if (!pSrc_file)
@@ -6814,6 +6826,10 @@ void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename,
return p;
}
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
#endif // #ifndef MINIZ_NO_STDIO
#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
diff --git a/contrib/zip/src/zip.c b/contrib/zip/src/zip.c
index 83e8e2a41..1f7fa8b76 100644
--- a/contrib/zip/src/zip.c
+++ b/contrib/zip/src/zip.c
@@ -18,11 +18,6 @@
/* Win32, DOS, MSVC, MSVS */
#include
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4706)
-#endif // _MSC_VER
-
#define MKDIR(DIRNAME) _mkdir(DIRNAME)
#define STRCLONE(STR) ((STR) ? _strdup(STR) : NULL)
#define HAS_DEVICE(P) \
@@ -32,17 +27,29 @@
#else
-#include // needed for symlink() on BSD
-int symlink(const char *target, const char *linkpath); // needed on Linux
+#include // needed for symlink()
#define MKDIR(DIRNAME) mkdir(DIRNAME, 0755)
#define STRCLONE(STR) ((STR) ? strdup(STR) : NULL)
#endif
+#ifdef __MINGW32__
+#include
+#include
+#endif
+
#include "miniz.h"
#include "zip.h"
+#ifdef _MSC_VER
+#include
+#pragma warning(disable : 4706)
+
+#define ftruncate(fd, sz) (-(_chsize_s((fd), (sz)) != 0))
+#define fileno _fileno
+#endif
+
#ifndef HAS_DEVICE
#define HAS_DEVICE(P) 0
#endif
@@ -63,7 +70,84 @@ int symlink(const char *target, const char *linkpath); // needed on Linux
} \
} while (0)
-static const char *base_name(const char *name) {
+struct zip_entry_t {
+ int index;
+ char *name;
+ mz_uint64 uncomp_size;
+ mz_uint64 comp_size;
+ mz_uint32 uncomp_crc32;
+ mz_uint64 offset;
+ mz_uint8 header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
+ mz_uint64 header_offset;
+ mz_uint16 method;
+ mz_zip_writer_add_state state;
+ tdefl_compressor comp;
+ mz_uint32 external_attr;
+ time_t m_time;
+};
+
+struct zip_t {
+ mz_zip_archive archive;
+ mz_uint level;
+ struct zip_entry_t entry;
+};
+
+enum zip_modify_t {
+ MZ_KEEP = 0,
+ MZ_DELETE = 1,
+ MZ_MOVE = 2,
+};
+
+struct zip_entry_mark_t {
+ int file_index;
+ enum zip_modify_t type;
+ mz_uint64 m_local_header_ofs;
+ mz_uint64 lf_length;
+};
+
+static const char *const zip_errlist[30] = {
+ NULL,
+ "not initialized\0",
+ "invalid entry name\0",
+ "entry not found\0",
+ "invalid zip mode\0",
+ "invalid compression level\0",
+ "no zip 64 support\0",
+ "memset error\0",
+ "cannot write data to entry\0",
+ "cannot initialize tdefl compressor\0",
+ "invalid index\0",
+ "header not found\0",
+ "cannot flush tdefl buffer\0",
+ "cannot write entry header\0",
+ "cannot create entry header\0",
+ "cannot write to central dir\0",
+ "cannot open file\0",
+ "invalid entry type\0",
+ "extracting data using no memory allocation\0",
+ "file not found\0",
+ "no permission\0",
+ "out of memory\0",
+ "invalid zip archive name\0",
+ "make dir error\0"
+ "symlink error\0"
+ "close archive error\0"
+ "capacity size too small\0",
+ "fseek error\0",
+ "fread error\0",
+ "fwrite error\0",
+};
+
+const char *zip_strerror(int errnum) {
+ errnum = -errnum;
+ if (errnum <= 0 || errnum >= 30) {
+ return NULL;
+ }
+
+ return zip_errlist[errnum];
+}
+
+static const char *zip_basename(const char *name) {
char const *p;
char const *base = name += FILESYSTEM_PREFIX_LEN(name);
int all_slashes = 1;
@@ -82,7 +166,7 @@ static const char *base_name(const char *name) {
return base;
}
-static int mkpath(char *path) {
+static int zip_mkpath(char *path) {
char *p;
char npath[MAX_PATH + 1];
int len = 0;
@@ -107,7 +191,7 @@ static int mkpath(char *path) {
if (MKDIR(npath) == -1) {
if (errno != EEXIST) {
- return -1;
+ return ZIP_EMKDIR;
}
}
}
@@ -117,7 +201,7 @@ static int mkpath(char *path) {
return 0;
}
-static char *strrpl(const char *str, size_t n, char oldchar, char newchar) {
+static char *zip_strrpl(const char *str, size_t n, char oldchar, char newchar) {
char c;
size_t i;
char *rpl = (char *)calloc((1 + n), sizeof(char));
@@ -136,27 +220,562 @@ static char *strrpl(const char *str, size_t n, char oldchar, char newchar) {
return begin;
}
-struct zip_entry_t {
- int index;
- char *name;
- mz_uint64 uncomp_size;
- mz_uint64 comp_size;
- mz_uint32 uncomp_crc32;
- mz_uint64 offset;
- mz_uint8 header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
- mz_uint64 header_offset;
- mz_uint16 method;
- mz_zip_writer_add_state state;
- tdefl_compressor comp;
- mz_uint32 external_attr;
- time_t m_time;
-};
+static char *zip_name_normalize(char *name, char *const nname, size_t len) {
+ size_t offn = 0;
+ size_t offnn = 0, ncpy = 0;
-struct zip_t {
- mz_zip_archive archive;
- mz_uint level;
- struct zip_entry_t entry;
-};
+ if (name == NULL || nname == NULL || len <= 0) {
+ return NULL;
+ }
+ // skip trailing '/'
+ while (ISSLASH(*name))
+ name++;
+
+ for (; offn < len; offn++) {
+ if (ISSLASH(name[offn])) {
+ if (ncpy > 0 && strcmp(&nname[offnn], ".\0") &&
+ strcmp(&nname[offnn], "..\0")) {
+ offnn += ncpy;
+ nname[offnn++] = name[offn]; // append '/'
+ }
+ ncpy = 0;
+ } else {
+ nname[offnn + ncpy] = name[offn];
+ ncpy++;
+ }
+ }
+
+ // at the end, extra check what we've already copied
+ if (ncpy == 0 || !strcmp(&nname[offnn], ".\0") ||
+ !strcmp(&nname[offnn], "..\0")) {
+ nname[offnn] = 0;
+ }
+ return nname;
+}
+
+static mz_bool zip_name_match(const char *name1, const char *name2) {
+ int len2 = (int) strlen(name2);
+ char *nname2 = zip_strrpl(name2, len2, '\\', '/');
+ if (!nname2) {
+ return MZ_FALSE;
+ }
+
+ mz_bool res = (strcmp(name1, nname2) == 0) ? MZ_TRUE : MZ_FALSE;
+ CLEANUP(nname2);
+ return res;
+}
+
+static int zip_archive_truncate(mz_zip_archive *pzip) {
+ mz_zip_internal_state *pState = pzip->m_pState;
+ mz_uint64 file_size = pzip->m_archive_size;
+ if ((pzip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) {
+ return 0;
+ }
+ if (pzip->m_zip_mode == MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED) {
+ if (pState->m_pFile) {
+ int fd = fileno(pState->m_pFile);
+ return ftruncate(fd, file_size);
+ }
+ }
+ return 0;
+}
+
+static int zip_archive_extract(mz_zip_archive *zip_archive, const char *dir,
+ int (*on_extract)(const char *filename,
+ void *arg),
+ void *arg) {
+ int err = 0;
+ mz_uint i, n;
+ char path[MAX_PATH + 1];
+ char symlink_to[MAX_PATH + 1];
+ mz_zip_archive_file_stat info;
+ size_t dirlen = 0;
+ mz_uint32 xattr = 0;
+
+ memset(path, 0, sizeof(path));
+ memset(symlink_to, 0, sizeof(symlink_to));
+
+ dirlen = strlen(dir);
+ if (dirlen + 1 > MAX_PATH) {
+ return ZIP_EINVENTNAME;
+ }
+
+ memset((void *)&info, 0, sizeof(mz_zip_archive_file_stat));
+
+#if defined(_MSC_VER)
+ strcpy_s(path, MAX_PATH, dir);
+#else
+ strcpy(path, dir);
+#endif
+
+ if (!ISSLASH(path[dirlen - 1])) {
+#if defined(_WIN32) || defined(__WIN32__)
+ path[dirlen] = '\\';
+#else
+ path[dirlen] = '/';
+#endif
+ ++dirlen;
+ }
+
+ // Get and print information about each file in the archive.
+ n = mz_zip_reader_get_num_files(zip_archive);
+ for (i = 0; i < n; ++i) {
+ if (!mz_zip_reader_file_stat(zip_archive, i, &info)) {
+ // Cannot get information about zip archive;
+ err = ZIP_ENOENT;
+ goto out;
+ }
+
+ if (!zip_name_normalize(info.m_filename, info.m_filename,
+ strlen(info.m_filename))) {
+ // Cannot normalize file name;
+ err = ZIP_EINVENTNAME;
+ goto out;
+ }
+#if defined(_MSC_VER)
+ strncpy_s(&path[dirlen], MAX_PATH - dirlen, info.m_filename,
+ MAX_PATH - dirlen);
+#else
+ strncpy(&path[dirlen], info.m_filename, MAX_PATH - dirlen);
+#endif
+ err = zip_mkpath(path);
+ if (err < 0) {
+ // Cannot make a path
+ goto out;
+ }
+
+ if ((((info.m_version_made_by >> 8) == 3) ||
+ ((info.m_version_made_by >> 8) ==
+ 19)) // if zip is produced on Unix or macOS (3 and 19 from
+ // section 4.4.2.2 of zip standard)
+ && info.m_external_attr &
+ (0x20 << 24)) { // and has sym link attribute (0x80 is file, 0x40
+ // is directory)
+#if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || \
+ defined(__MINGW32__)
+#else
+ if (info.m_uncomp_size > MAX_PATH ||
+ !mz_zip_reader_extract_to_mem_no_alloc(zip_archive, i, symlink_to,
+ MAX_PATH, 0, NULL, 0)) {
+ err = ZIP_EMEMNOALLOC;
+ goto out;
+ }
+ symlink_to[info.m_uncomp_size] = '\0';
+ if (symlink(symlink_to, path) != 0) {
+ err = ZIP_ESYMLINK;
+ goto out;
+ }
+#endif
+ } else {
+ if (!mz_zip_reader_is_file_a_directory(zip_archive, i)) {
+ if (!mz_zip_reader_extract_to_file(zip_archive, i, path, 0)) {
+ // Cannot extract zip archive to file
+ err = ZIP_ENOFILE;
+ goto out;
+ }
+ }
+
+#if defined(_MSC_VER)
+ (void)xattr; // unused
+#else
+ xattr = (info.m_external_attr >> 16) & 0xFFFF;
+ if (xattr > 0) {
+ if (chmod(path, (mode_t)xattr) < 0) {
+ err = ZIP_ENOPERM;
+ goto out;
+ }
+ }
+#endif
+ }
+
+ if (on_extract) {
+ if (on_extract(path, arg) < 0) {
+ goto out;
+ }
+ }
+ }
+
+out:
+ // Close the archive, freeing any resources it was using
+ if (!mz_zip_reader_end(zip_archive)) {
+ // Cannot end zip reader
+ err = ZIP_ECLSZIP;
+ }
+ return err;
+}
+
+static inline void zip_archive_finalize(mz_zip_archive *pzip) {
+ mz_zip_writer_finalize_archive(pzip);
+ zip_archive_truncate(pzip);
+}
+
+static int zip_entry_mark(struct zip_t *zip,
+ struct zip_entry_mark_t *entry_mark, int n,
+ char *const entries[], const size_t len) {
+ int err = 0;
+ if (!zip || !entry_mark || !entries) {
+ return ZIP_ENOINIT;
+ }
+
+ mz_zip_archive_file_stat file_stat;
+ mz_uint64 d_pos = (mz_uint64) ~0;
+ for (int i = 0; i < n; ++i) {
+ err = zip_entry_openbyindex(zip, i);
+ if (err) {
+ return err;
+ }
+
+ mz_bool name_matches = MZ_FALSE;
+ for (int j = 0; j < (const int)len; ++j) {
+ if (zip_name_match(zip->entry.name, entries[j])) {
+ name_matches = MZ_TRUE;
+ break;
+ }
+ }
+ if (name_matches) {
+ entry_mark[i].type = MZ_DELETE;
+ } else {
+ entry_mark[i].type = MZ_KEEP;
+ }
+
+ if (!mz_zip_reader_file_stat(&zip->archive, i, &file_stat)) {
+ return ZIP_ENOENT;
+ }
+
+ zip_entry_close(zip);
+
+ entry_mark[i].m_local_header_ofs = file_stat.m_local_header_ofs;
+ entry_mark[i].file_index = -1;
+ entry_mark[i].lf_length = 0;
+ if ((entry_mark[i].type) == MZ_DELETE &&
+ (d_pos > entry_mark[i].m_local_header_ofs)) {
+ d_pos = entry_mark[i].m_local_header_ofs;
+ }
+ }
+ for (int i = 0; i < n; ++i) {
+ if ((entry_mark[i].m_local_header_ofs > d_pos) &&
+ (entry_mark[i].type != MZ_DELETE)) {
+ entry_mark[i].type = MZ_MOVE;
+ }
+ }
+ return err;
+}
+
+static int zip_index_next(mz_uint64 *local_header_ofs_array, int cur_index) {
+ int new_index = 0;
+ for (int i = cur_index - 1; i >= 0; --i) {
+ if (local_header_ofs_array[cur_index] > local_header_ofs_array[i]) {
+ new_index = i + 1;
+ return new_index;
+ }
+ }
+ return new_index;
+}
+
+static int zip_sort(mz_uint64 *local_header_ofs_array, int cur_index) {
+ int nxt_index = zip_index_next(local_header_ofs_array, cur_index);
+
+ if (nxt_index != cur_index) {
+ mz_uint64 temp = local_header_ofs_array[cur_index];
+ for (int i = cur_index; i > nxt_index; i--) {
+ local_header_ofs_array[i] = local_header_ofs_array[i - 1];
+ }
+ local_header_ofs_array[nxt_index] = temp;
+ }
+ return nxt_index;
+}
+
+static int zip_index_update(struct zip_entry_mark_t *entry_mark, int last_index,
+ int nxt_index) {
+ for (int j = 0; j < last_index; j++) {
+ if (entry_mark[j].file_index >= nxt_index) {
+ entry_mark[j].file_index += 1;
+ }
+ }
+ entry_mark[nxt_index].file_index = last_index;
+ return 0;
+}
+
+static int zip_entry_finalize(struct zip_t *zip,
+ struct zip_entry_mark_t *entry_mark,
+ const int n) {
+
+ mz_uint64 *local_header_ofs_array = (mz_uint64 *)calloc(n, sizeof(mz_uint64));
+ if (!local_header_ofs_array) {
+ return ZIP_EOOMEM;
+ }
+
+ for (int i = 0; i < n; ++i) {
+ local_header_ofs_array[i] = entry_mark[i].m_local_header_ofs;
+ int index = zip_sort(local_header_ofs_array, i);
+
+ if (index != i) {
+ zip_index_update(entry_mark, i, index);
+ }
+ entry_mark[i].file_index = index;
+ }
+
+ mz_uint64 *length = (mz_uint64 *)calloc(n, sizeof(mz_uint64));
+ if (!length) {
+ CLEANUP(local_header_ofs_array);
+ return ZIP_EOOMEM;
+ }
+ for (int i = 0; i < n - 1; i++) {
+ length[i] = local_header_ofs_array[i + 1] - local_header_ofs_array[i];
+ }
+ length[n - 1] = zip->archive.m_archive_size - local_header_ofs_array[n - 1];
+
+ for (int i = 0; i < n; i++) {
+ entry_mark[i].lf_length = length[entry_mark[i].file_index];
+ }
+
+ CLEANUP(length);
+ CLEANUP(local_header_ofs_array);
+ return 0;
+}
+
+static int zip_entry_set(struct zip_t *zip, struct zip_entry_mark_t *entry_mark,
+ int n, char *const entries[], const size_t len) {
+ int err = 0;
+
+ if ((err = zip_entry_mark(zip, entry_mark, n, entries, len)) < 0) {
+ return err;
+ }
+ if ((err = zip_entry_finalize(zip, entry_mark, n)) < 0) {
+ return err;
+ }
+ return 0;
+}
+
+static mz_int64 zip_file_move(MZ_FILE *m_pFile, const mz_uint64 to,
+ const mz_uint64 from, const mz_uint64 length,
+ mz_uint8 *move_buf,
+ const mz_int64 capacity_size) {
+ if ((mz_int64)length > capacity_size) {
+ return ZIP_ECAPSIZE;
+ }
+ if (MZ_FSEEK64(m_pFile, from, SEEK_SET)) {
+ MZ_FCLOSE(m_pFile);
+ return ZIP_EFSEEK;
+ }
+
+ if (fread(move_buf, 1, length, m_pFile) != length) {
+ MZ_FCLOSE(m_pFile);
+ return ZIP_EFREAD;
+ }
+ if (MZ_FSEEK64(m_pFile, to, SEEK_SET)) {
+ MZ_FCLOSE(m_pFile);
+ return ZIP_EFSEEK;
+ }
+ if (fwrite(move_buf, 1, length, m_pFile) != length) {
+ MZ_FCLOSE(m_pFile);
+ return ZIP_EFWRITE;
+ }
+ return (mz_int64)length;
+}
+
+static mz_int64 zip_files_move(MZ_FILE *m_pFile, mz_uint64 writen_num,
+ mz_uint64 read_num, mz_uint64 length) {
+ int n = 0;
+ const mz_int64 page_size = 1 << 12; // 4K
+ mz_uint8 *move_buf = (mz_uint8 *)calloc(1, page_size);
+ if (move_buf == NULL) {
+ return ZIP_EOOMEM;
+ }
+
+ mz_int64 moved_length = 0;
+ mz_int64 move_count = 0;
+ while ((mz_int64)length > 0) {
+ move_count = ((mz_int64)length >= page_size) ? page_size : (mz_int64)length;
+ n = (int) zip_file_move(m_pFile, writen_num, read_num, move_count, move_buf,
+ page_size);
+ if (n < 0) {
+ moved_length = n;
+ goto cleanup;
+ }
+
+ if (n != move_count) {
+ goto cleanup;
+ }
+
+ writen_num += move_count;
+ read_num += move_count;
+ length -= move_count;
+ moved_length += move_count;
+ }
+
+cleanup:
+ CLEANUP(move_buf);
+ return moved_length;
+}
+
+static int zip_central_dir_move(mz_zip_internal_state *pState, int begin,
+ int end, int entry_num) {
+ if (begin == entry_num) {
+ return 0;
+ }
+
+ mz_uint64 l_size = 0;
+ mz_uint64 r_size = 0;
+ mz_uint64 d_size = 0;
+ mz_uint8 *next = NULL;
+ mz_uint8 *deleted = &MZ_ZIP_ARRAY_ELEMENT(
+ &pState->m_central_dir, mz_uint8,
+ MZ_ZIP_ARRAY_ELEMENT(&pState->m_central_dir_offsets, mz_uint32, begin));
+ l_size = (mz_uint32)(deleted - (mz_uint8 *)(pState->m_central_dir.m_p));
+ if (end == entry_num) {
+ r_size = 0;
+ } else {
+ next = &MZ_ZIP_ARRAY_ELEMENT(
+ &pState->m_central_dir, mz_uint8,
+ MZ_ZIP_ARRAY_ELEMENT(&pState->m_central_dir_offsets, mz_uint32, end));
+ r_size = pState->m_central_dir.m_size -
+ (mz_uint32)(next - (mz_uint8 *)(pState->m_central_dir.m_p));
+ d_size = next - deleted;
+ }
+
+ if (l_size == 0) {
+ memmove(pState->m_central_dir.m_p, next, r_size);
+ pState->m_central_dir.m_p = MZ_REALLOC(pState->m_central_dir.m_p, r_size);
+ for (int i = end; i < entry_num; i++) {
+ MZ_ZIP_ARRAY_ELEMENT(&pState->m_central_dir_offsets, mz_uint64, i) -=
+ d_size;
+ }
+ }
+
+ if (l_size * r_size != 0) {
+ memmove(deleted, next, r_size);
+ for (int i = end; i < entry_num; i++) {
+ MZ_ZIP_ARRAY_ELEMENT(&pState->m_central_dir_offsets, mz_uint64, i) -=
+ d_size;
+ }
+ }
+
+ pState->m_central_dir.m_size = l_size + r_size;
+ return 0;
+}
+
+static int zip_central_dir_delete(mz_zip_internal_state *pState,
+ int *deleted_entry_index_array,
+ int entry_num) {
+ int i = 0;
+ int begin = 0;
+ int end = 0;
+ int d_num = 0;
+ while (i < entry_num) {
+ while ((!deleted_entry_index_array[i]) && (i < entry_num)) {
+ i++;
+ }
+ begin = i;
+
+ while ((deleted_entry_index_array[i]) && (i < entry_num)) {
+ i++;
+ }
+ end = i;
+ zip_central_dir_move(pState, begin, end, entry_num);
+ }
+
+ i = 0;
+ while (i < entry_num) {
+ while ((!deleted_entry_index_array[i]) && (i < entry_num)) {
+ i++;
+ }
+ begin = i;
+ if (begin == entry_num) {
+ break;
+ }
+ while ((deleted_entry_index_array[i]) && (i < entry_num)) {
+ i++;
+ }
+ end = i;
+ int k = 0;
+ for (int j = end; j < entry_num; j++) {
+ MZ_ZIP_ARRAY_ELEMENT(&pState->m_central_dir_offsets, mz_uint32,
+ begin + k) =
+ (mz_uint32)MZ_ZIP_ARRAY_ELEMENT(&pState->m_central_dir_offsets,
+ mz_uint32, j);
+ k++;
+ }
+ d_num += end - begin;
+ }
+
+ pState->m_central_dir_offsets.m_size =
+ sizeof(mz_uint32) * (entry_num - d_num);
+ return 0;
+}
+
+static int zip_entries_delete_mark(struct zip_t *zip,
+ struct zip_entry_mark_t *entry_mark,
+ int entry_num) {
+ mz_uint64 writen_num = 0;
+ mz_uint64 read_num = 0;
+ mz_uint64 deleted_length = 0;
+ mz_uint64 move_length = 0;
+ int i = 0;
+ int deleted_entry_num = 0;
+ int n = 0;
+
+ mz_bool *deleted_entry_flag_array =
+ (mz_bool *)calloc(entry_num, sizeof(mz_bool));
+ if (deleted_entry_flag_array == NULL) {
+ return ZIP_EOOMEM;
+ }
+
+ mz_zip_internal_state *pState = zip->archive.m_pState;
+ zip->archive.m_zip_mode = MZ_ZIP_MODE_WRITING;
+
+ if (MZ_FSEEK64(pState->m_pFile, 0, SEEK_SET)) {
+ CLEANUP(deleted_entry_flag_array);
+ return ZIP_ENOENT;
+ }
+
+ while (i < entry_num) {
+ while ((entry_mark[i].type == MZ_KEEP) && (i < entry_num)) {
+ writen_num += entry_mark[i].lf_length;
+ read_num = writen_num;
+ i++;
+ }
+
+ while ((entry_mark[i].type == MZ_DELETE) && (i < entry_num)) {
+ deleted_entry_flag_array[i] = MZ_TRUE;
+ read_num += entry_mark[i].lf_length;
+ deleted_length += entry_mark[i].lf_length;
+ i++;
+ deleted_entry_num++;
+ }
+
+ while ((entry_mark[i].type == MZ_MOVE) && (i < entry_num)) {
+ move_length += entry_mark[i].lf_length;
+ mz_uint8 *p = &MZ_ZIP_ARRAY_ELEMENT(
+ &pState->m_central_dir, mz_uint8,
+ MZ_ZIP_ARRAY_ELEMENT(&pState->m_central_dir_offsets, mz_uint32, i));
+ if (!p) {
+ CLEANUP(deleted_entry_flag_array);
+ return ZIP_ENOENT;
+ }
+ mz_uint32 offset = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
+ offset -= (mz_uint32)deleted_length;
+ MZ_WRITE_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS, offset);
+ i++;
+ }
+
+ n = (int) zip_files_move(pState->m_pFile, writen_num, read_num, move_length);
+ if (n != (mz_int64)move_length) {
+ CLEANUP(deleted_entry_flag_array);
+ return n;
+ }
+ writen_num += move_length;
+ read_num += move_length;
+ }
+
+ zip->archive.m_archive_size -= deleted_length;
+ zip->archive.m_total_files = entry_num - deleted_entry_num;
+
+ zip_central_dir_delete(pState, deleted_entry_flag_array, entry_num);
+ CLEANUP(deleted_entry_flag_array);
+
+ return deleted_entry_num;
+}
struct zip_t *zip_open(const char *zipname, int level, char mode) {
struct zip_t *zip = NULL;
@@ -189,6 +808,7 @@ struct zip_t *zip_open(const char *zipname, int level, char mode) {
case 'r':
case 'a':
+ case 'd':
if (!mz_zip_reader_init_file(
&(zip->archive), zipname,
zip->level | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) {
@@ -196,7 +816,7 @@ struct zip_t *zip_open(const char *zipname, int level, char mode) {
// zip_archive reader
goto cleanup;
}
- if (mode == 'a' &&
+ if ((mode == 'a' || mode == 'd') &&
!mz_zip_writer_init_from_reader(&(zip->archive), zipname)) {
mz_zip_reader_end(&(zip->archive));
goto cleanup;
@@ -219,7 +839,7 @@ void zip_close(struct zip_t *zip) {
// Always finalize, even if adding failed for some reason, so we have a
// valid central directory.
mz_zip_writer_finalize_archive(&(zip->archive));
-
+ zip_archive_truncate(&(zip->archive));
mz_zip_writer_end(&(zip->archive));
mz_zip_reader_end(&(zip->archive));
@@ -228,14 +848,9 @@ void zip_close(struct zip_t *zip) {
}
int zip_is64(struct zip_t *zip) {
- if (!zip) {
- // zip_t handler is not initialized
- return -1;
- }
-
- if (!zip->archive.m_pState) {
- // zip state is not initialized
- return -1;
+ if (!zip || !zip->archive.m_pState) {
+ // zip_t handler or zip state is not initialized
+ return ZIP_ENOINIT;
}
return (int)zip->archive.m_pState->m_zip64;
@@ -246,14 +861,19 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) {
mz_zip_archive *pzip = NULL;
mz_uint num_alignment_padding_bytes, level;
mz_zip_archive_file_stat stats;
+ int err = 0;
- if (!zip || !entryname) {
- return -1;
+ if (!zip) {
+ return ZIP_ENOINIT;
+ }
+
+ if (!entryname) {
+ return ZIP_EINVENTNAME;
}
entrylen = strlen(entryname);
- if (entrylen < 1) {
- return -1;
+ if (entrylen == 0) {
+ return ZIP_EINVENTNAME;
}
/*
@@ -267,10 +887,13 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) {
and UNIX file systems etc. If input came from standard
input, there is no file name field.
*/
- zip->entry.name = strrpl(entryname, entrylen, '\\', '/');
+ if (zip->entry.name) {
+ CLEANUP(zip->entry.name);
+ }
+ zip->entry.name = zip_strrpl(entryname, entrylen, '\\', '/');
if (!zip->entry.name) {
// Cannot parse zip entry name
- return -1;
+ return ZIP_EINVENTNAME;
}
pzip = &(zip->archive);
@@ -278,10 +901,12 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) {
zip->entry.index =
mz_zip_reader_locate_file(pzip, zip->entry.name, NULL, 0);
if (zip->entry.index < 0) {
+ err = ZIP_ENOENT;
goto cleanup;
}
if (!mz_zip_reader_file_stat(pzip, (mz_uint)zip->entry.index, &stats)) {
+ err = ZIP_ENOENT;
goto cleanup;
}
@@ -292,7 +917,9 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) {
zip->entry.header_offset = stats.m_local_header_ofs;
zip->entry.method = stats.m_method;
zip->entry.external_attr = stats.m_external_attr;
+#ifndef MINIZ_NO_TIME
zip->entry.m_time = stats.m_time;
+#endif
return 0;
}
@@ -318,11 +945,13 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) {
mz_zip_writer_compute_padding_needed_for_file_alignment(pzip);
if (!pzip->m_pState || (pzip->m_zip_mode != MZ_ZIP_MODE_WRITING)) {
- // Wrong zip mode
+ // Invalid zip mode
+ err = ZIP_EINVMODE;
goto cleanup;
}
if (zip->level & MZ_ZIP_FLAG_COMPRESSED_DATA) {
- // Wrong zip compression level
+ // Invalid zip compression level
+ err = ZIP_EINVLVL;
goto cleanup;
}
// no zip64 support yet
@@ -331,12 +960,14 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) {
MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
entrylen) > 0xFFFFFFFF)) {
// No zip64 support yet
+ err = ZIP_ENOSUP64;
goto cleanup;
}
if (!mz_zip_writer_write_zeros(pzip, zip->entry.offset,
num_alignment_padding_bytes +
sizeof(zip->entry.header))) {
// Cannot memset zip entry header
+ err = ZIP_EMEMSET;
goto cleanup;
}
@@ -350,6 +981,7 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) {
if (pzip->m_pWrite(pzip->m_pIO_opaque, zip->entry.offset, zip->entry.name,
entrylen) != entrylen) {
// Cannot write data to zip entry
+ err = ZIP_EWRTENT;
goto cleanup;
}
@@ -366,6 +998,7 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) {
(int)level, -15, MZ_DEFAULT_STRATEGY)) !=
TDEFL_STATUS_OKAY) {
// Cannot initialize the zip compressor
+ err = ZIP_ETDEFLINIT;
goto cleanup;
}
}
@@ -376,7 +1009,7 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) {
cleanup:
CLEANUP(zip->entry.name);
- return -1;
+ return err;
}
int zip_entry_openbyindex(struct zip_t *zip, int index) {
@@ -388,28 +1021,26 @@ int zip_entry_openbyindex(struct zip_t *zip, int index) {
if (!zip) {
// zip_t handler is not initialized
- return -1;
+ return ZIP_ENOINIT;
}
pZip = &(zip->archive);
if (pZip->m_zip_mode != MZ_ZIP_MODE_READING) {
// open by index requires readonly mode
- return -1;
+ return ZIP_EINVMODE;
}
if (index < 0 || (mz_uint)index >= pZip->m_total_files) {
// index out of range
- return -1;
+ return ZIP_EINVIDX;
}
-
if (!(pHeader = &MZ_ZIP_ARRAY_ELEMENT(
&pZip->m_pState->m_central_dir, mz_uint8,
MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets,
mz_uint32, index)))) {
// cannot find header in central directory
- return -1;
+ return ZIP_ENOHDR;
}
-
namelen = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
@@ -424,14 +1055,17 @@ int zip_entry_openbyindex(struct zip_t *zip, int index) {
and UNIX file systems etc. If input came from standard
input, there is no file name field.
*/
- zip->entry.name = strrpl(pFilename, namelen, '\\', '/');
+ if (zip->entry.name) {
+ CLEANUP(zip->entry.name);
+ }
+ zip->entry.name = zip_strrpl(pFilename, namelen, '\\', '/');
if (!zip->entry.name) {
// local entry name is NULL
- return -1;
+ return ZIP_EINVENTNAME;
}
if (!mz_zip_reader_file_stat(pZip, (mz_uint)index, &stats)) {
- return -1;
+ return ZIP_ENOENT;
}
zip->entry.index = index;
@@ -442,7 +1076,9 @@ int zip_entry_openbyindex(struct zip_t *zip, int index) {
zip->entry.header_offset = stats.m_local_header_ofs;
zip->entry.method = stats.m_method;
zip->entry.external_attr = stats.m_external_attr;
+#ifndef MINIZ_NO_TIME
zip->entry.m_time = stats.m_time;
+#endif
return 0;
}
@@ -452,17 +1088,17 @@ int zip_entry_close(struct zip_t *zip) {
mz_uint level;
tdefl_status done;
mz_uint16 entrylen;
- mz_uint16 dos_time, dos_date;
- int status = -1;
+ mz_uint16 dos_time = 0, dos_date = 0;
+ int err = 0;
if (!zip) {
// zip_t handler is not initialized
+ err = ZIP_ENOINIT;
goto cleanup;
}
pzip = &(zip->archive);
if (pzip->m_zip_mode == MZ_ZIP_MODE_READING) {
- status = 0;
goto cleanup;
}
@@ -471,6 +1107,7 @@ int zip_entry_close(struct zip_t *zip) {
done = tdefl_compress_buffer(&(zip->entry.comp), "", 0, TDEFL_FINISH);
if (done != TDEFL_STATUS_DONE && done != TDEFL_STATUS_OKAY) {
// Cannot flush compressed buffer
+ err = ZIP_ETDEFLBUF;
goto cleanup;
}
zip->entry.comp_size = zip->entry.state.m_comp_size;
@@ -479,18 +1116,22 @@ int zip_entry_close(struct zip_t *zip) {
}
entrylen = (mz_uint16)strlen(zip->entry.name);
- // no zip64 support yet
if ((zip->entry.comp_size > 0xFFFFFFFF) || (zip->entry.offset > 0xFFFFFFFF)) {
// No zip64 support, yet
+ err = ZIP_ENOSUP64;
goto cleanup;
}
+#ifndef MINIZ_NO_TIME
mz_zip_time_t_to_dos_time(zip->entry.m_time, &dos_time, &dos_date);
+#endif
+
if (!mz_zip_writer_create_local_dir_header(
pzip, zip->entry.header, entrylen, 0, zip->entry.uncomp_size,
zip->entry.comp_size, zip->entry.uncomp_crc32, zip->entry.method, 0,
dos_time, dos_date)) {
// Cannot create zip entry header
+ err = ZIP_ECRTHDR;
goto cleanup;
}
@@ -498,6 +1139,7 @@ int zip_entry_close(struct zip_t *zip) {
zip->entry.header,
sizeof(zip->entry.header)) != sizeof(zip->entry.header)) {
// Cannot write zip entry header
+ err = ZIP_EWRTHDR;
goto cleanup;
}
@@ -507,19 +1149,19 @@ int zip_entry_close(struct zip_t *zip) {
zip->entry.method, 0, dos_time, dos_date, zip->entry.header_offset,
zip->entry.external_attr)) {
// Cannot write to zip central dir
+ err = ZIP_EWRTDIR;
goto cleanup;
}
pzip->m_total_files++;
pzip->m_archive_size = zip->entry.offset;
- status = 0;
cleanup:
if (zip) {
zip->entry.m_time = 0;
CLEANUP(zip->entry.name);
}
- return status;
+ return err;
}
const char *zip_entry_name(struct zip_t *zip) {
@@ -534,7 +1176,7 @@ const char *zip_entry_name(struct zip_t *zip) {
int zip_entry_index(struct zip_t *zip) {
if (!zip) {
// zip_t handler is not initialized
- return -1;
+ return ZIP_ENOINIT;
}
return zip->entry.index;
@@ -543,12 +1185,12 @@ int zip_entry_index(struct zip_t *zip) {
int zip_entry_isdir(struct zip_t *zip) {
if (!zip) {
// zip_t handler is not initialized
- return -1;
+ return ZIP_ENOINIT;
}
if (zip->entry.index < 0) {
// zip entry is not opened
- return -1;
+ return ZIP_EINVIDX;
}
return (int)mz_zip_reader_is_file_a_directory(&zip->archive,
@@ -570,7 +1212,7 @@ int zip_entry_write(struct zip_t *zip, const void *buf, size_t bufsize) {
if (!zip) {
// zip_t handler is not initialized
- return -1;
+ return ZIP_ENOINIT;
}
pzip = &(zip->archive);
@@ -584,7 +1226,7 @@ int zip_entry_write(struct zip_t *zip, const void *buf, size_t bufsize) {
if ((pzip->m_pWrite(pzip->m_pIO_opaque, zip->entry.offset, buf,
bufsize) != bufsize)) {
// Cannot write buffer
- return -1;
+ return ZIP_EWRTENT;
}
zip->entry.offset += bufsize;
zip->entry.comp_size += bufsize;
@@ -593,7 +1235,7 @@ int zip_entry_write(struct zip_t *zip, const void *buf, size_t bufsize) {
TDEFL_NO_FLUSH);
if (status != TDEFL_STATUS_DONE && status != TDEFL_STATUS_OKAY) {
// Cannot compress buffer
- return -1;
+ return ZIP_ETDEFLBUF;
}
}
}
@@ -602,7 +1244,7 @@ int zip_entry_write(struct zip_t *zip, const void *buf, size_t bufsize) {
}
int zip_entry_fwrite(struct zip_t *zip, const char *filename) {
- int status = 0;
+ int err = 0;
size_t n = 0;
FILE *stream = NULL;
mz_uint8 buf[MZ_ZIP_MAX_IO_BUF_SIZE];
@@ -610,14 +1252,14 @@ int zip_entry_fwrite(struct zip_t *zip, const char *filename) {
if (!zip) {
// zip_t handler is not initialized
- return -1;
+ return ZIP_ENOINIT;
}
memset(buf, 0, MZ_ZIP_MAX_IO_BUF_SIZE);
memset((void *)&file_stat, 0, sizeof(struct MZ_FILE_STAT_STRUCT));
if (MZ_FILE_STAT(filename, &file_stat) != 0) {
// problem getting information - check errno
- return -1;
+ return ZIP_ENOENT;
}
if ((file_stat.st_mode & 0200) == 0) {
@@ -634,19 +1276,19 @@ int zip_entry_fwrite(struct zip_t *zip, const char *filename) {
#endif
{
// Cannot open filename
- return -1;
+ return ZIP_EOPNFILE;
}
while ((n = fread(buf, sizeof(mz_uint8), MZ_ZIP_MAX_IO_BUF_SIZE, stream)) >
0) {
if (zip_entry_write(zip, buf, n) < 0) {
- status = -1;
+ err = ZIP_EWRTENT;
break;
}
}
fclose(stream);
- return status;
+ return err;
}
ssize_t zip_entry_read(struct zip_t *zip, void **buf, size_t *bufsize) {
@@ -656,19 +1298,19 @@ ssize_t zip_entry_read(struct zip_t *zip, void **buf, size_t *bufsize) {
if (!zip) {
// zip_t handler is not initialized
- return -1;
+ return ZIP_ENOINIT;
}
pzip = &(zip->archive);
if (pzip->m_zip_mode != MZ_ZIP_MODE_READING || zip->entry.index < 0) {
// the entry is not found or we do not have read access
- return -1;
+ return ZIP_ENOENT;
}
idx = (mz_uint)zip->entry.index;
if (mz_zip_reader_is_file_a_directory(pzip, idx)) {
// the entry is a directory
- return -1;
+ return ZIP_EINVENTTYPE;
}
*buf = mz_zip_reader_extract_to_heap(pzip, idx, &size, 0);
@@ -683,18 +1325,18 @@ ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf, size_t bufsize) {
if (!zip) {
// zip_t handler is not initialized
- return -1;
+ return ZIP_ENOINIT;
}
pzip = &(zip->archive);
if (pzip->m_zip_mode != MZ_ZIP_MODE_READING || zip->entry.index < 0) {
// the entry is not found or we do not have read access
- return -1;
+ return ZIP_ENOENT;
}
if (!mz_zip_reader_extract_to_mem_no_alloc(pzip, (mz_uint)zip->entry.index,
buf, bufsize, 0, NULL, 0)) {
- return -1;
+ return ZIP_EMEMNOALLOC;
}
return (ssize_t)zip->entry.uncomp_size;
@@ -703,45 +1345,43 @@ ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf, size_t bufsize) {
int zip_entry_fread(struct zip_t *zip, const char *filename) {
mz_zip_archive *pzip = NULL;
mz_uint idx;
-#if defined(_MSC_VER)
-#else
mz_uint32 xattr = 0;
-#endif
mz_zip_archive_file_stat info;
if (!zip) {
// zip_t handler is not initialized
- return -1;
+ return ZIP_ENOINIT;
}
memset((void *)&info, 0, sizeof(mz_zip_archive_file_stat));
pzip = &(zip->archive);
if (pzip->m_zip_mode != MZ_ZIP_MODE_READING || zip->entry.index < 0) {
// the entry is not found or we do not have read access
- return -1;
+ return ZIP_ENOENT;
}
idx = (mz_uint)zip->entry.index;
if (mz_zip_reader_is_file_a_directory(pzip, idx)) {
// the entry is a directory
- return -1;
+ return ZIP_EINVENTTYPE;
}
if (!mz_zip_reader_extract_to_file(pzip, idx, filename, 0)) {
- return -1;
+ return ZIP_ENOFILE;
}
#if defined(_MSC_VER)
+ (void)xattr; // unused
#else
if (!mz_zip_reader_file_stat(pzip, idx, &info)) {
// Cannot get information about zip archive;
- return -1;
+ return ZIP_ENOFILE;
}
xattr = (info.m_external_attr >> 16) & 0xFFFF;
if (xattr > 0) {
if (chmod(filename, (mode_t)xattr) < 0) {
- return -1;
+ return ZIP_ENOPERM;
}
}
#endif
@@ -758,32 +1398,147 @@ int zip_entry_extract(struct zip_t *zip,
if (!zip) {
// zip_t handler is not initialized
- return -1;
+ return ZIP_ENOINIT;
}
pzip = &(zip->archive);
if (pzip->m_zip_mode != MZ_ZIP_MODE_READING || zip->entry.index < 0) {
// the entry is not found or we do not have read access
- return -1;
+ return ZIP_ENOENT;
}
idx = (mz_uint)zip->entry.index;
return (mz_zip_reader_extract_to_callback(pzip, idx, on_extract, arg, 0))
? 0
- : -1;
+ : ZIP_EINVIDX;
}
-int zip_total_entries(struct zip_t *zip) {
+int zip_entries_total(struct zip_t *zip) {
if (!zip) {
// zip_t handler is not initialized
- return -1;
+ return ZIP_ENOINIT;
}
return (int)zip->archive.m_total_files;
}
+int zip_entries_delete(struct zip_t *zip, char *const entries[],
+ const size_t len) {
+ int n = 0;
+ int err = 0;
+ struct zip_entry_mark_t *entry_mark = NULL;
+
+ if (zip == NULL || (entries == NULL && len != 0)) {
+ return ZIP_ENOINIT;
+ }
+
+ if (entries == NULL && len == 0) {
+ return 0;
+ }
+
+ n = zip_entries_total(zip);
+
+ entry_mark =
+ (struct zip_entry_mark_t *)calloc(n, sizeof(struct zip_entry_mark_t));
+ if (!entry_mark) {
+ return ZIP_EOOMEM;
+ }
+
+ zip->archive.m_zip_mode = MZ_ZIP_MODE_READING;
+
+ err = zip_entry_set(zip, entry_mark, n, entries, len);
+ if (err < 0) {
+ CLEANUP(entry_mark);
+ return err;
+ }
+
+ err = zip_entries_delete_mark(zip, entry_mark, n);
+ CLEANUP(entry_mark);
+ return err;
+}
+
+int zip_stream_extract(const char *stream, size_t size, const char *dir,
+ int (*on_extract)(const char *filename, void *arg),
+ void *arg) {
+ mz_zip_archive zip_archive;
+ if (!stream || !dir) {
+ // Cannot parse zip archive stream
+ return ZIP_ENOINIT;
+ }
+ if (!memset(&zip_archive, 0, sizeof(mz_zip_archive))) {
+ // Cannot memset zip archive
+ return ZIP_EMEMSET;
+ }
+ if (!mz_zip_reader_init_mem(&zip_archive, stream, size, 0)) {
+ // Cannot initialize zip_archive reader
+ return ZIP_ENOINIT;
+ }
+
+ return zip_archive_extract(&zip_archive, dir, on_extract, arg);
+}
+
+struct zip_t *zip_stream_open(const char *stream, size_t size, int level,
+ char mode) {
+ struct zip_t *zip = (struct zip_t *)calloc((size_t)1, sizeof(struct zip_t));
+ if (!zip) {
+ return NULL;
+ }
+
+ if (level < 0) {
+ level = MZ_DEFAULT_LEVEL;
+ }
+ if ((level & 0xF) > MZ_UBER_COMPRESSION) {
+ // Wrong compression level
+ goto cleanup;
+ }
+ zip->level = (mz_uint)level;
+
+ if ((stream != NULL) && (size > 0) && (mode == 'r')) {
+ if (!mz_zip_reader_init_mem(&(zip->archive), stream, size, 0)) {
+ goto cleanup;
+ }
+ } else if ((stream == NULL) && (size == 0) && (mode == 'w')) {
+ // Create a new archive.
+ if (!mz_zip_writer_init_heap(&(zip->archive), 0, 1024)) {
+ // Cannot initialize zip_archive writer
+ goto cleanup;
+ }
+ } else {
+ goto cleanup;
+ }
+ return zip;
+
+cleanup:
+ CLEANUP(zip);
+ return NULL;
+}
+
+ssize_t zip_stream_copy(struct zip_t *zip, void **buf, ssize_t *bufsize) {
+ if (!zip) {
+ return ZIP_ENOINIT;
+ }
+
+ zip_archive_finalize(&(zip->archive));
+
+ if (bufsize != NULL) {
+ *bufsize = zip->archive.m_archive_size;
+ }
+ *buf = calloc(sizeof(unsigned char), zip->archive.m_archive_size);
+ memcpy(*buf, zip->archive.m_pState->m_pMem, zip->archive.m_archive_size);
+
+ return zip->archive.m_archive_size;
+}
+
+void zip_stream_close(struct zip_t *zip) {
+ if (zip) {
+ mz_zip_writer_end(&(zip->archive));
+ mz_zip_reader_end(&(zip->archive));
+ CLEANUP(zip);
+ }
+}
+
int zip_create(const char *zipname, const char *filenames[], size_t len) {
- int status = 0;
+ int err = 0;
size_t i;
mz_zip_archive zip_archive;
struct MZ_FILE_STAT_STRUCT file_stat;
@@ -791,32 +1546,34 @@ int zip_create(const char *zipname, const char *filenames[], size_t len) {
if (!zipname || strlen(zipname) < 1) {
// zip_t archive name is empty or NULL
- return -1;
+ return ZIP_EINVZIPNAME;
}
// Create a new archive.
if (!memset(&(zip_archive), 0, sizeof(zip_archive))) {
// Cannot memset zip archive
- return -1;
+ return ZIP_EMEMSET;
}
if (!mz_zip_writer_init_file(&zip_archive, zipname, 0)) {
// Cannot initialize zip_archive writer
- return -1;
+ return ZIP_ENOINIT;
}
- memset((void *)&file_stat, 0, sizeof(struct MZ_FILE_STAT_STRUCT));
+ if (!memset((void *)&file_stat, 0, sizeof(struct MZ_FILE_STAT_STRUCT))) {
+ return ZIP_EMEMSET;
+ }
for (i = 0; i < len; ++i) {
const char *name = filenames[i];
if (!name) {
- status = -1;
+ err = ZIP_EINVENTNAME;
break;
}
if (MZ_FILE_STAT(name, &file_stat) != 0) {
// problem getting information - check errno
- status = -1;
+ err = ZIP_ENOFILE;
break;
}
@@ -826,150 +1583,39 @@ int zip_create(const char *zipname, const char *filenames[], size_t len) {
}
ext_attributes |= (mz_uint32)((file_stat.st_mode & 0xFFFF) << 16);
- if (!mz_zip_writer_add_file(&zip_archive, base_name(name), name, "", 0,
+ if (!mz_zip_writer_add_file(&zip_archive, zip_basename(name), name, "", 0,
ZIP_DEFAULT_COMPRESSION_LEVEL,
ext_attributes)) {
// Cannot add file to zip_archive
- status = -1;
+ err = ZIP_ENOFILE;
break;
}
}
mz_zip_writer_finalize_archive(&zip_archive);
mz_zip_writer_end(&zip_archive);
- return status;
+ return err;
}
int zip_extract(const char *zipname, const char *dir,
int (*on_extract)(const char *filename, void *arg), void *arg) {
- int status = -1;
- mz_uint i, n;
- char path[MAX_PATH + 1];
- char symlink_to[MAX_PATH + 1];
mz_zip_archive zip_archive;
- mz_zip_archive_file_stat info;
- size_t dirlen = 0;
-#if defined(_MSC_VER)
-#else
- mz_uint32 xattr = 0;
-#endif
-
-
- memset(path, 0, sizeof(path));
- memset(symlink_to, 0, sizeof(symlink_to));
- if (!memset(&(zip_archive), 0, sizeof(zip_archive))) {
- // Cannot memset zip archive
- return -1;
- }
if (!zipname || !dir) {
// Cannot parse zip archive name
- return -1;
+ return ZIP_EINVZIPNAME;
}
- dirlen = strlen(dir);
- if (dirlen + 1 > MAX_PATH) {
- return -1;
+ if (!memset(&zip_archive, 0, sizeof(mz_zip_archive))) {
+ // Cannot memset zip archive
+ return ZIP_EMEMSET;
}
// Now try to open the archive.
if (!mz_zip_reader_init_file(&zip_archive, zipname, 0)) {
// Cannot initialize zip_archive reader
- return -1;
+ return ZIP_ENOINIT;
}
- memset((void *)&info, 0, sizeof(mz_zip_archive_file_stat));
-
-#if defined(_MSC_VER)
- strcpy_s(path, MAX_PATH, dir);
-#else
- strcpy(path, dir);
-#endif
-
- if (!ISSLASH(path[dirlen - 1])) {
-#if defined(_WIN32) || defined(__WIN32__)
- path[dirlen] = '\\';
-#else
- path[dirlen] = '/';
-#endif
- ++dirlen;
- }
-
- // Get and print information about each file in the archive.
- n = mz_zip_reader_get_num_files(&zip_archive);
- for (i = 0; i < n; ++i) {
- if (!mz_zip_reader_file_stat(&zip_archive, i, &info)) {
- // Cannot get information about zip archive;
- goto out;
- }
-#if defined(_MSC_VER)
- strncpy_s(&path[dirlen], MAX_PATH - dirlen, info.m_filename,
- MAX_PATH - dirlen);
-#else
- strncpy(&path[dirlen], info.m_filename, MAX_PATH - dirlen);
-#endif
- if (mkpath(path) < 0) {
- // Cannot make a path
- goto out;
- }
-
- if ((((info.m_version_made_by >> 8) == 3) ||
- ((info.m_version_made_by >> 8) ==
- 19)) // if zip is produced on Unix or macOS (3 and 19 from
- // section 4.4.2.2 of zip standard)
- && info.m_external_attr &
- (0x20 << 24)) { // and has sym link attribute (0x80 is file, 0x40
- // is directory)
-#if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || \
- defined(__MINGW32__)
-#else
- if (info.m_uncomp_size > MAX_PATH ||
- !mz_zip_reader_extract_to_mem_no_alloc(&zip_archive, i, symlink_to,
- MAX_PATH, 0, NULL, 0)) {
- goto out;
- }
- symlink_to[info.m_uncomp_size] = '\0';
- if (symlink(symlink_to, path) != 0) {
- goto out;
- }
-#endif
- } else {
- if (!mz_zip_reader_is_file_a_directory(&zip_archive, i)) {
- if (!mz_zip_reader_extract_to_file(&zip_archive, i, path, 0)) {
- // Cannot extract zip archive to file
- goto out;
- }
- }
-
-#if defined(_MSC_VER)
-#else
- xattr = (info.m_external_attr >> 16) & 0xFFFF;
- if (xattr > 0) {
- if (chmod(path, (mode_t)xattr) < 0) {
- goto out;
- }
- }
-#endif
- }
-
- if (on_extract) {
- if (on_extract(path, arg) < 0) {
- goto out;
- }
- }
- }
- status = 0;
-
-out:
- // Close the archive, freeing any resources it was using
- if (!mz_zip_reader_end(&zip_archive)) {
- // Cannot end zip reader
- status = -1;
- }
-
- return status;
+ return zip_archive_extract(&zip_archive, dir, on_extract, arg);
}
-
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif // _MSC_VER
diff --git a/contrib/zip/src/zip.h b/contrib/zip/src/zip.h
index 87f3654f4..70ab2cee6 100644
--- a/contrib/zip/src/zip.h
+++ b/contrib/zip/src/zip.h
@@ -15,19 +15,11 @@
#include
#include
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4127 )
-#endif //_MSC_VER
-
#ifdef __cplusplus
extern "C" {
#endif
-#if !defined(_SSIZE_T_DEFINED) && !defined(_SSIZE_T_DEFINED_) && \
- !defined(__DEFINED_ssize_t) && !defined(__ssize_t_defined) && \
- !defined(_SSIZE_T) && !defined(_SSIZE_T_) && !defined(_SSIZE_T_DECLARED)
-
+#if !defined(_POSIX_C_SOURCE) && defined(_MSC_VER)
// 64-bit Windows is the only mainstream platform
// where sizeof(long) != sizeof(void*)
#ifdef _WIN64
@@ -35,15 +27,6 @@ typedef long long ssize_t; /* byte count or error */
#else
typedef long ssize_t; /* byte count or error */
#endif
-
-#define _SSIZE_T_DEFINED
-#define _SSIZE_T_DEFINED_
-#define __DEFINED_ssize_t
-#define __ssize_t_defined
-#define _SSIZE_T
-#define _SSIZE_T_
-#define _SSIZE_T_DECLARED
-
#endif
#ifndef MAX_PATH
@@ -64,9 +47,49 @@ typedef long ssize_t; /* byte count or error */
/**
* Default zip compression level.
*/
-
#define ZIP_DEFAULT_COMPRESSION_LEVEL 6
+/**
+ * Error codes
+ */
+#define ZIP_ENOINIT -1 // not initialized
+#define ZIP_EINVENTNAME -2 // invalid entry name
+#define ZIP_ENOENT -3 // entry not found
+#define ZIP_EINVMODE -4 // invalid zip mode
+#define ZIP_EINVLVL -5 // invalid compression level
+#define ZIP_ENOSUP64 -6 // no zip 64 support
+#define ZIP_EMEMSET -7 // memset error
+#define ZIP_EWRTENT -8 // cannot write data to entry
+#define ZIP_ETDEFLINIT -9 // cannot initialize tdefl compressor
+#define ZIP_EINVIDX -10 // invalid index
+#define ZIP_ENOHDR -11 // header not found
+#define ZIP_ETDEFLBUF -12 // cannot flush tdefl buffer
+#define ZIP_ECRTHDR -13 // cannot create entry header
+#define ZIP_EWRTHDR -14 // cannot write entry header
+#define ZIP_EWRTDIR -15 // cannot write to central dir
+#define ZIP_EOPNFILE -16 // cannot open file
+#define ZIP_EINVENTTYPE -17 // invalid entry type
+#define ZIP_EMEMNOALLOC -18 // extracting data using no memory allocation
+#define ZIP_ENOFILE -19 // file not found
+#define ZIP_ENOPERM -20 // no permission
+#define ZIP_EOOMEM -21 // out of memory
+#define ZIP_EINVZIPNAME -22 // invalid zip archive name
+#define ZIP_EMKDIR -23 // make dir error
+#define ZIP_ESYMLINK -24 // symlink error
+#define ZIP_ECLSZIP -25 // close archive error
+#define ZIP_ECAPSIZE -26 // capacity size too small
+#define ZIP_EFSEEK -27 // fseek error
+#define ZIP_EFREAD -28 // fread error
+#define ZIP_EFWRITE -29 // fwrite error
+
+/**
+ * Looks up the error message string coresponding to an error number.
+ * @param errnum error number
+ * @return error message string coresponding to errnum or NULL if error is not
+ * found.
+ */
+extern const char *zip_strerror(int errnum);
+
/**
* @struct zip_t
*
@@ -242,8 +265,8 @@ extern ssize_t zip_entry_read(struct zip_t *zip, void **buf, size_t *bufsize);
*
* @note ensure supplied output buffer is large enough.
* zip_entry_size function (returns uncompressed size for the current
- * entry) can be handy to estimate how big buffer is needed. for large
- * entries, please take a look at zip_entry_extract function.
+ * entry) can be handy to estimate how big buffer is needed.
+ * For large entries, please take a look at zip_entry_extract function.
*
* @return the return code - the number of bytes actually read on success.
* Otherwise a -1 on error (e.g. bufsize is not large enough).
@@ -285,7 +308,71 @@ zip_entry_extract(struct zip_t *zip,
* @return the return code - the number of entries on success, negative number
* (< 0) on error.
*/
-extern int zip_total_entries(struct zip_t *zip);
+extern int zip_entries_total(struct zip_t *zip);
+
+/**
+ * Deletes zip archive entries.
+ *
+ * @param zip zip archive handler.
+ * @param entries array of zip archive entries to be deleted.
+ * @param len the number of entries to be deleted.
+ * @return the number of deleted entries, or negative number (< 0) on error.
+ */
+extern int zip_entries_delete(struct zip_t *zip, char *const entries[],
+ size_t len);
+
+/**
+ * Extracts a zip archive stream into directory.
+ *
+ * If on_extract is not NULL, the callback will be called after
+ * successfully extracted each zip entry.
+ * Returning a negative value from the callback will cause abort and return an
+ * error. The last argument (void *arg) is optional, which you can use to pass
+ * data to the on_extract callback.
+ *
+ * @param stream zip archive stream.
+ * @param size stream size.
+ * @param dir output directory.
+ * @param on_extract on extract callback.
+ * @param arg opaque pointer.
+ *
+ * @return the return code - 0 on success, negative number (< 0) on error.
+ */
+extern int zip_stream_extract(const char *stream, size_t size, const char *dir,
+ int (*on_extract)(const char *filename,
+ void *arg),
+ void *arg);
+
+/**
+ * Opens zip archive stream into memory.
+ *
+ * @param stream zip archive stream.
+ * @param size stream size.
+ *
+ * @return the zip archive handler or NULL on error
+ */
+extern struct zip_t *zip_stream_open(const char *stream, size_t size, int level,
+ char mode);
+
+/**
+ * Copy zip archive stream output buffer.
+ *
+ * @param zip zip archive handler.
+ * @param buf output buffer. User should free buf.
+ * @param bufsize output buffer size (in bytes).
+ *
+ * @return copy size
+ */
+extern ssize_t zip_stream_copy(struct zip_t *zip, void **buf, ssize_t *bufsize);
+
+/**
+ * Close zip archive releases resources.
+ *
+ * @param zip zip archive handler.
+ *
+ * @return
+ */
+extern void zip_stream_close(struct zip_t *zip);
/**
* Creates a new archive and puts files into a single zip archive.
@@ -319,11 +406,6 @@ extern int zip_extract(const char *zipname, const char *dir,
void *arg);
/** @} */
-
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif //_MSC_VER
-
#ifdef __cplusplus
}
#endif
diff --git a/contrib/zip/test/CMakeLists.txt b/contrib/zip/test/CMakeLists.txt
index a7c3650f7..0da1684d4 100644
--- a/contrib/zip/test/CMakeLists.txt
+++ b/contrib/zip/test/CMakeLists.txt
@@ -1,11 +1,38 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.4)
-# test
-set(test_out test.out)
+# tests
+set(test_write_out test_write.out)
+add_executable(${test_write_out} test_write.c)
+target_link_libraries(${test_write_out} zip)
+add_test(NAME ${test_write_out} COMMAND ${test_write_out})
+set(test_write_out ${test_write_out} PARENT_SCOPE)
-add_executable(${test_out} test.c)
-target_link_libraries(${test_out} zip)
+set(test_append_out test_append.out)
+add_executable(${test_append_out} test_append.c)
+target_link_libraries(${test_append_out} zip)
+add_test(NAME ${test_append_out} COMMAND ${test_append_out})
+set(test_append_out ${test_append_out} PARENT_SCOPE)
-add_test(NAME ${test_out} COMMAND ${test_out})
+set(test_read_out test_read.out)
+add_executable(${test_read_out} test_read.c)
+target_link_libraries(${test_read_out} zip)
+add_test(NAME ${test_read_out} COMMAND ${test_read_out})
+set(test_read_out ${test_read_out} PARENT_SCOPE)
-set(test_out ${test_out} PARENT_SCOPE)
+set(test_extract_out test_extract.out)
+add_executable(${test_extract_out} test_extract.c)
+target_link_libraries(${test_extract_out} zip)
+add_test(NAME ${test_extract_out} COMMAND ${test_extract_out})
+set(test_extract_out ${test_extract_out} PARENT_SCOPE)
+
+set(test_entry_out test_entry.out)
+add_executable(${test_entry_out} test_entry.c)
+target_link_libraries(${test_entry_out} zip)
+add_test(NAME ${test_entry_out} COMMAND ${test_entry_out})
+set(test_entry_out ${test_entry_out} PARENT_SCOPE)
+
+set(test_permissions_out test_permissions.out)
+add_executable(${test_permissions_out} test_permissions.c)
+target_link_libraries(${test_permissions_out} zip)
+add_test(NAME ${test_permissions_out} COMMAND ${test_permissions_out})
+set(test_permissions_out ${test_permissions_out} PARENT_SCOPE)
diff --git a/doc/Fileformats.md b/doc/Fileformats.md
index c9116e2e7..89b68e17f 100644
--- a/doc/Fileformats.md
+++ b/doc/Fileformats.md
@@ -81,6 +81,7 @@ __Exporters__:
- JSON (for WebGl, via https://github.com/acgessler/assimp2json)
- ASSBIN
- STEP
+- [PBRTv4](https://github.com/mmp/pbrt-v4)
- glTF 1.0 (partial)
- glTF 2.0 (partial)
- 3MF ( experimental )
diff --git a/include/assimp/DefaultIOStream.h b/include/assimp/DefaultIOStream.h
index b1bb66902..6d0e13149 100644
--- a/include/assimp/DefaultIOStream.h
+++ b/include/assimp/DefaultIOStream.h
@@ -119,7 +119,7 @@ private:
AI_FORCE_INLINE
DefaultIOStream::DefaultIOStream() AI_NO_EXCEPT
: mFile(nullptr)
-, mFilename("")
+, mFilename()
, mCachedSize(SIZE_MAX) {
// empty
}
diff --git a/include/assimp/IOSystem.hpp b/include/assimp/IOSystem.hpp
index b05eebce6..76f876440 100644
--- a/include/assimp/IOSystem.hpp
+++ b/include/assimp/IOSystem.hpp
@@ -294,7 +294,7 @@ bool IOSystem::PushDirectory( const std::string &path ) {
AI_FORCE_INLINE
const std::string &IOSystem::CurrentDirectory() const {
if ( m_pathStack.empty() ) {
- static const std::string Dummy("");
+ static const std::string Dummy;
return Dummy;
}
return m_pathStack[ m_pathStack.size()-1 ];
diff --git a/include/assimp/Importer.hpp b/include/assimp/Importer.hpp
index 18734c302..09b5b6883 100644
--- a/include/assimp/Importer.hpp
+++ b/include/assimp/Importer.hpp
@@ -286,7 +286,7 @@ public:
* @see GetPropertyInteger()
*/
std::string GetPropertyString(const char *szName,
- const std::string &sErrorReturn = "") const;
+ const std::string &sErrorReturn = std::string()) const;
// -------------------------------------------------------------------
/** Get a matrix configuration property
diff --git a/include/assimp/XmlParser.h b/include/assimp/XmlParser.h
index 15c4ff9ff..f525d3549 100644
--- a/include/assimp/XmlParser.h
+++ b/include/assimp/XmlParser.h
@@ -239,7 +239,7 @@ public:
}
static inline bool getValueAsString( XmlNode &node, std::string &text ) {
- text = "";
+ text = std::string();
if (node.empty()) {
return false;
}
diff --git a/include/assimp/postprocess.h b/include/assimp/postprocess.h
index 01eabaef9..ca2c2c22d 100644
--- a/include/assimp/postprocess.h
+++ b/include/assimp/postprocess.h
@@ -209,9 +209,14 @@ enum aiPostProcessSteps
/**
Removes the node graph and pre-transforms all vertices with
* the local transformation matrices of their nodes.
*
- * The output scene still contains nodes, however there is only a
- * root node with children, each one referencing only one mesh,
- * and each mesh referencing one material. For rendering, you can
+ * If the resulting scene can be reduced to a single mesh, with a single
+ * material, no lights, and no cameras, then the output scene will contain
+ * only a root node (with no children) that references the single mesh.
+ * Otherwise, the output scene will be reduced to a root node with a single
+ * level of child nodes, each one referencing one mesh, and each mesh
+ * referencing one material.
+ *
+ * In either case, for rendering, you can
* simply render all meshes in order - you don't need to pay
* attention to local transformations and the node hierarchy.
* Animations are removed during this step.