diff --git a/coding/coding.pro b/coding/coding.pro index dd977258f6..00533454c1 100644 --- a/coding/coding.pro +++ b/coding/coding.pro @@ -31,6 +31,7 @@ SOURCES += \ blob_indexer.cpp \ blob_storage.cpp \ uri.cpp \ + zip_creator.cpp \ HEADERS += \ internal/xmlparser.h \ @@ -89,3 +90,4 @@ HEADERS += \ blob_indexer.hpp \ blob_storage.hpp \ uri.hpp \ + zip_creator.hpp \ diff --git a/coding/coding_tests/coding_tests.pro b/coding/coding_tests/coding_tests.pro index 2eb6cf7ffe..9a4499e7a6 100644 --- a/coding/coding_tests/coding_tests.pro +++ b/coding/coding_tests/coding_tests.pro @@ -43,6 +43,7 @@ SOURCES += ../../testing/testingmain.cpp \ reader_writer_ops_test.cpp \ blob_storage_test.cpp \ uri_test.cpp \ + zip_creator_test.cpp \ HEADERS += \ reader_test.hpp \ diff --git a/coding/coding_tests/zip_creator_test.cpp b/coding/coding_tests/zip_creator_test.cpp new file mode 100644 index 0000000000..2519b30632 --- /dev/null +++ b/coding/coding_tests/zip_creator_test.cpp @@ -0,0 +1,69 @@ +#include "../../testing/testing.hpp" + +#include "../../map/framework.hpp" + +#include "../../coding/zip_creator.hpp" +#include "../../coding/zip_reader.hpp" +#include "../../coding/internal/file_data.hpp" +#include "../../coding/writer.hpp" + +#include "../../base/scope_guard.hpp" + +#include "../../platform/platform.hpp" + +#include "../../std/string.hpp" +#include "../../std/vector.hpp" +#include "../../std/iostream.hpp" + +UNIT_TEST(Create_Zip_From_Big_File) +{ + string const name = "testfileforzip.txt"; + + { + my::FileData f(name, my::FileData::OP_WRITE_TRUNCATE); + string z(1024*512 + 1, '1'); + f.Write(z.c_str(), z.size()); + } + + string const zipName = "testzip.zip"; + + TEST(createZipFromPathDeflatedAndDefaultCompression(name, zipName), ()); + + + vector files; + ZipFileReader::FilesList(zipName, files); + string const unzippedFile = "unzipped.tmp"; + ZipFileReader::UnzipFile(zipName, files[0], unzippedFile); + + + TEST(my::IsEqualFiles(name, unzippedFile),()); + TEST(my::DeleteFileX(name), ()); + TEST(my::DeleteFileX(zipName), ()); + TEST(my::DeleteFileX(unzippedFile), ()); +} + +UNIT_TEST(Create_zip) +{ + string const name = "testfileforzip.txt"; + + { + my::FileData f(name, my::FileData::OP_WRITE_TRUNCATE); + f.Write(name.c_str(), name.size()); + } + + string const zipName = "testzip.zip"; + + TEST(createZipFromPathDeflatedAndDefaultCompression(name, zipName), ()); + + + vector files; + ZipFileReader::FilesList(zipName, files); + string const unzippedFile = "unzipped.tmp"; + ZipFileReader::UnzipFile(zipName, files[0], unzippedFile); + + + TEST(my::IsEqualFiles(name, unzippedFile),()); + TEST(my::DeleteFileX(name), ()); + TEST(my::DeleteFileX(zipName), ()); + TEST(my::DeleteFileX(unzippedFile), ()); +} diff --git a/coding/zip_creator.cpp b/coding/zip_creator.cpp new file mode 100644 index 0000000000..f761df3a2b --- /dev/null +++ b/coding/zip_creator.cpp @@ -0,0 +1,73 @@ +#include "zip_creator.hpp" + +#include "../../coding/internal/file_data.hpp" + +#include "../../std/vector.hpp" +#include "../../std/iostream.hpp" +#include "../../std/ctime.hpp" + +#include "../../3party/zlib/contrib/minizip/zip.h" + + +class ZipHandle +{ +public: + zipFile m_zipFile; + ZipHandle(string const & filePath) + { + m_zipFile = zipOpen(filePath.c_str(), 0); + } + ~ZipHandle() + { + if (m_zipFile) + zipClose(m_zipFile, NULL); + } +}; + +namespace +{ +void CreateTMZip(tm_zip & res) +{ + time_t rawtime; + struct tm * timeinfo; + time ( &rawtime ); + timeinfo = localtime ( &rawtime ); + res.tm_sec = timeinfo->tm_sec; + res.tm_min = timeinfo->tm_min; + res.tm_hour = timeinfo->tm_hour; + res.tm_mday = timeinfo->tm_mday; + res.tm_mon = timeinfo->tm_mon; + res.tm_year = timeinfo->tm_year; +} +} + +bool createZipFromPathDeflatedAndDefaultCompression(string const & filePath, string const & zipFilePath) +{ + + ZipHandle zip(zipFilePath); + if (!zip.m_zipFile) + return false; + zip_fileinfo zipInfo = { 0 }; + CreateTMZip(zipInfo.tmz_date); + if (zipOpenNewFileInZip (zip.m_zipFile, filePath.c_str(), &zipInfo, NULL, 0, NULL, 0, "ZIP from MapsWithMe", Z_DEFLATED, Z_DEFAULT_COMPRESSION) < 0) + return false; + + my::FileData f(filePath, my::FileData::OP_READ); + + size_t const bufSize = 512 * 1024; + vector buffer(bufSize); + size_t const fileSize = f.Size(); + size_t currSize = 0; + + while (currSize < fileSize) + { + size_t toRead = fileSize - currSize; + if (toRead > bufSize) + toRead = bufSize; + f.Read(currSize, &buffer[0], toRead); + if (ZIP_OK != zipWriteInFileInZip (zip.m_zipFile, &buffer[0], toRead)) + return false; + currSize += toRead; + } + return true; +} diff --git a/coding/zip_creator.hpp b/coding/zip_creator.hpp new file mode 100644 index 0000000000..083fa533cb --- /dev/null +++ b/coding/zip_creator.hpp @@ -0,0 +1,4 @@ + +#include "../../std/string.hpp" + +bool createZipFromPathDeflatedAndDefaultCompression(string const & filePath, string const & zipFilePath);