Skip to content

Commit

Permalink
3.2.2
Browse files Browse the repository at this point in the history
- Fixed miniz-cpp not creating folders
- Improved generall error handling and added caching for string operations
  • Loading branch information
ChrisBase committed Jul 19, 2021
1 parent ab6d43b commit 7661d40
Show file tree
Hide file tree
Showing 17 changed files with 77 additions and 43 deletions.
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,19 @@ Possible options are:
* 'andyzip' (Native Windows 10 C/C++ UWP implementation slightly faster than miniz-cpp)

If unzipAlgorithm is undefined, the plugin will default to 'miniz-cpp'.
The 'miniz-cpp' implementation is more robust and tends to be faster for archives with many files.
The 'miniz-cpp' implementation is more robust and handles various zip formats more reliable.
The 'andyzip' implementation offsers only basic zip format support with 'deflate' and 'uncompressed'
as the only supported decoding formats for archive contents, but tends to be faster for very large files.
as the only supported decoding formats for archive contents, but tends to be slightly faster.
Both native implementations are more than 10 times faster than the jszip implementation.


## Release Notes

### 3.2.1 (Jun 25, 2021)
### 3.2.2 (Jul 19, 2021)
* Fixed miniz-cpp not creating folders
* Improved caching for string operations and generall error handling

### 3.2.1 (Jul 15, 2021)
* Changed default zip algorithm to miniz-cpp (more reliable and faster for many small files)
* Improved error catching and handling in ZipComponentUWP and ZipProxy.js
* Added version number to ZipComponentUWP and pre-build script that updates it
Expand Down
2 changes: 1 addition & 1 deletion plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<plugin xmlns="http://phonegap.com/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="cordova-plugin-zip"
version="3.2.1">
version="3.2.2">
<engines>
<engine name="cordova" version=">=3.3.0"/>
</engines>
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
27 changes: 9 additions & 18 deletions src/windows/ZipComponentUWP/Source/ZipAlgorithm.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <vector>
#include <iostream>
#include <sstream>
#include <direct.h>
#include "ZipAlgorithm.h"
#include "ZipAlgorithm_andyzip.h"
Expand All @@ -23,6 +24,10 @@ ZipAlgorithm* ZipAlgorithm::Create(const char* pchAlgorithmName)
else if( ::strcmp(pchAlgorithmName, NameMinizCpp) == 0 )
return new ZipAlgorithm_miniz_cpp();

std::ostringstream stringStream;
stringStream << "ZipAlgorithm::Create(): unsupported algorithm name: " << pchAlgorithmName;
throw std::runtime_error(stringStream.str());

return nullptr;
}

Expand All @@ -48,30 +53,16 @@ void ZipAlgorithm::SetOutputDirWithTrailingSlash(const char* pchOutputDir)
m_strOutputDir += '/';
}

bool ZipAlgorithm::CreateEntryDir(const std::string& strEntryDir) const
{
const size_t szEntryDirLength = strEntryDir.length();
if( szEntryDirLength < 1 )
throw std::runtime_error("ZipAlgorithm::CreateEntryDir(): invalid/empty entry dir");

const char& chLastChar = strEntryDir[szEntryDirLength - 1];
if( chLastChar != '/' && chLastChar != '\\' )
return false;

const std::string strDir(m_strOutputDir + strEntryDir);
_mkdir(strDir.c_str());
return true;
}

void ZipAlgorithm::CreateEntrySubDirs(const std::string& strEntryName) const
void ZipAlgorithm::CreateEntrySubDirs(const std::string& strEntryName)
{
// If strEntryName is a filename in a sub folder, we create all required folders first
// e.g. For strEntryName = "path/to/filename" we create the folders "path" and "path/to".
size_t szPos = strEntryName.find('/');
while( szPos != std::string::npos )
{
const std::string strFolder(m_strOutputDir + strEntryName.substr(0, szPos));
_mkdir(strFolder.c_str());
m_strCache = m_strOutputDir; // Reuse m_strCache to reduce string allocations
m_strCache.append(strEntryName, 0, szPos);
_mkdir(m_strCache.c_str());
szPos = strEntryName.find('/', szPos + 1);
}
}
6 changes: 3 additions & 3 deletions src/windows/ZipComponentUWP/Source/ZipAlgorithm.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ class ZipAlgorithm

virtual size_t GetEntryCount() const = 0;
virtual const std::string& GetEntryName(const size_t szEntryIndex) const = 0;
virtual bool UnzipEntry(const size_t szEntryIndex) const = 0;
virtual bool UnzipEntry(const size_t szEntryIndex) = 0;

protected:
ZipAlgorithm() = default;

void SetOutputDirWithTrailingSlash(const char* pchOutputDir);
bool CreateEntryDir(const std::string& strEntryDir) const;
void CreateEntrySubDirs(const std::string& strEntryName) const;
void CreateEntrySubDirs(const std::string& strEntryName);

std::string m_strOutputDir;
std::string m_strCache;
};
31 changes: 27 additions & 4 deletions src/windows/ZipComponentUWP/Source/ZipAlgorithm_andyzip.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once
#include <fstream>
#include <sstream>
#include <vector>
#include <stdexcept>
#include <direct.h>
Expand Down Expand Up @@ -125,6 +126,13 @@ class ZipAlgorithm_andyzip::Reader

const std::string& GetEntryName(const size_t szEntryIndex) const
{
if( szEntryIndex >= m_vFiles.size() )
{
std::ostringstream stringStream;
stringStream << "ZipAlgorithm_andyzip::Reader::GetEntryName(): invalid index " << szEntryIndex;
throw std::runtime_error(stringStream.str());
}

return m_vFiles[szEntryIndex];
}

Expand Down Expand Up @@ -236,22 +244,37 @@ void ZipAlgorithm_andyzip::Close()

size_t ZipAlgorithm_andyzip::GetEntryCount() const
{
return m_pReader->GetEntryCount();
return m_pReader ? m_pReader->GetEntryCount() : 0u;
}

const std::string& ZipAlgorithm_andyzip::GetEntryName(const size_t szEntryIndex) const
{
if( m_pReader == nullptr )
throw std::runtime_error("ZipAlgorithm_andyzip::GetEntryName(): reader not initialized");

return m_pReader->GetEntryName(szEntryIndex);
}

bool ZipAlgorithm_andyzip::UnzipEntry(const size_t szEntryIndex) const
bool ZipAlgorithm_andyzip::UnzipEntry(const size_t szEntryIndex)
{
if( m_pReader == nullptr )
throw std::runtime_error("ZipAlgorithm_andyzip::GetEntryName(): reader not initialized");

const std::string& strEntryName = GetEntryName(szEntryIndex);
CreateEntrySubDirs(strEntryName);

const std::vector<uint8_t>& filedata(m_pReader->GetEntryData(strEntryName));
std::ofstream ofFile(m_strOutputDir + strEntryName, std::ios::binary | std::ios::out);
// If entry is a directory, stop here, since CreateEntrySubDirs() already created it
const char chLastChar = strEntryName[strEntryName.length() - 1];
if( chLastChar == '\\' || chLastChar == '/' )
return true;

m_strCache = m_strOutputDir;
m_strCache += strEntryName;
std::ofstream ofFile(m_strCache, std::ios::binary | std::ios::out);
if( ofFile.rdstate() != 0 )
return false;

const std::vector<uint8_t>& filedata(m_pReader->GetEntryData(strEntryName));
ofFile.write(reinterpret_cast<const char*>(filedata.data()), filedata.size());

return ofFile.rdstate() == 0;
Expand Down
5 changes: 3 additions & 2 deletions src/windows/ZipComponentUWP/Source/ZipAlgorithm_andyzip.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ class ZipAlgorithm_andyzip : public ZipAlgorithm

size_t GetEntryCount() const;
const std::string& GetEntryName(const size_t szEntryIndex) const;
bool UnzipEntry(const size_t szEntryIndex) const;
bool UnzipEntry(const size_t szEntryIndex);

private:
class Reader;

std::vector<char> m_vBuffer;
Reader* m_pReader;
std::string m_strFile;
Reader* m_pReader = nullptr;
};
33 changes: 24 additions & 9 deletions src/windows/ZipComponentUWP/Source/ZipAlgorithm_miniz-cpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,35 @@ size_t ZipAlgorithm_miniz_cpp::GetEntryCount() const

const std::string& ZipAlgorithm_miniz_cpp::GetEntryName(const size_t szEntryIndex) const
{
if( szEntryIndex >= m_vEntries.size() )
{
std::ostringstream stringStream;
stringStream << "ZipAlgorithm_miniz_cpp::GetEntryName(): invalid index " << szEntryIndex;
throw std::runtime_error(stringStream.str());
}

return m_vEntries[szEntryIndex];
}

bool ZipAlgorithm_miniz_cpp::UnzipEntry(const size_t szEntryIndex) const
bool ZipAlgorithm_miniz_cpp::UnzipEntry(const size_t szEntryIndex)
{
if( m_pZipFile )
{
const std::string strEntry = GetEntryName(szEntryIndex);
if( CreateEntryDir(strEntry) )
return true;
if( m_pZipFile == nullptr )
return false;

const std::string strEntryName = GetEntryName(szEntryIndex);
CreateEntrySubDirs(strEntryName);

m_pZipFile->extract(strEntry, m_strOutputDir);
// If entry is a directory, stop here, since CreateEntrySubDirs() already created it
const char chLastChar = strEntryName[strEntryName.length() - 1];
if( chLastChar == '\\' || chLastChar == '/' )
return true;
}

return false;
m_strCache = m_strOutputDir;
m_strCache += strEntryName;
std::ofstream ofFile(m_strCache, std::ios::binary | std::ios::out);
if( ofFile.rdstate() != 0 )
return false;

ofFile << m_pZipFile->open(strEntryName).rdbuf();
return ofFile.rdstate() == 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class ZipAlgorithm_miniz_cpp : public ZipAlgorithm

size_t GetEntryCount() const;
const std::string& GetEntryName(const size_t szEntryIndex) const;
bool UnzipEntry(const size_t szEntryIndex) const;
bool UnzipEntry(const size_t szEntryIndex);

private:
std::vector<std::string> m_vEntries;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ using namespace ZipComponentUWP;

String^ ZipComponent::GetVersion()
{
return "1.0.1.0";
return "1.0.2.0";
}
2 changes: 1 addition & 1 deletion src/windows/ZipComponentUWP/Source/ZipTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ int main(int argc, const char* argv[])
ZipAlgorithm::Destroy(pAlgorithm);

std::cout << "Duration: " << std::chrono::duration_cast<std::chrono::milliseconds>(timeEnd - timeBegin).count() << " ms";
if (iResult != EXIT_SUCCESS)
if( iResult != EXIT_SUCCESS )
std::cout << "Error: " << iResult << std::endl;

return iResult;
Expand Down
Binary file modified src/windows/ZipComponentUWP/ZipComponentUWP.rc
Binary file not shown.

0 comments on commit 7661d40

Please sign in to comment.