From 64a6968973dff20ed9bca485eaa2f5321861453a Mon Sep 17 00:00:00 2001 From: vng Date: Tue, 7 Oct 2014 14:06:33 +0300 Subject: [PATCH] [iOS] Avoid clang 3.5 optimization bug (import/export kmz). Need to review in future. --- coding/constants.hpp | 1 + coding/zip_creator.cpp | 51 ++++++++++++++++++++-------- coding/zip_reader.cpp | 12 ++++--- iphone/Maps/Bookmarks/BookmarksVC.mm | 9 +++-- 4 files changed, 51 insertions(+), 22 deletions(-) diff --git a/coding/constants.hpp b/coding/constants.hpp index 3c60abd7b9..cbf0d41964 100644 --- a/coding/constants.hpp +++ b/coding/constants.hpp @@ -1,3 +1,4 @@ #pragma once static const size_t READ_FILE_BUFFER_SIZE = 512 * 1024; +static const size_t ZIP_FILE_BUFFER_SIZE = 64 * 1024; diff --git a/coding/zip_creator.cpp b/coding/zip_creator.cpp index 648bb0a840..05121112bf 100644 --- a/coding/zip_creator.cpp +++ b/coding/zip_creator.cpp @@ -4,8 +4,12 @@ #include "../../coding/file_name_utils.hpp" #include "../../coding/internal/file_data.hpp" +#include "../../coding/reader.hpp" #include "../../coding/constants.hpp" +#include "../../base/logging.hpp" +#include "../../base/scope_guard.hpp" + #include "../../std/vector.hpp" #include "../../std/ctime.hpp" #include "../../std/algorithm.hpp" @@ -53,6 +57,14 @@ void CreateTMZip(tm_zip & res) bool CreateZipFromPathDeflatedAndDefaultCompression(string const & filePath, string const & zipFilePath) { + /// Prepare buffer at the very beginning to avoid clang 3.5, loop optimization. + /// @todo Need to check with the new XCode (and clang) update. + + size_t const bufSize = ZIP_FILE_BUFFER_SIZE; + vector buffer(bufSize); + + // 2. Open zip file for writing. + MY_SCOPE_GUARD(outFileGuard, bind(&my::DeleteFileX, cref(zipFilePath))); ZipHandle zip(zipFilePath); if (!zip.Handle()) return false; @@ -60,34 +72,43 @@ bool CreateZipFromPathDeflatedAndDefaultCompression(string const & filePath, str // Special syntax to initialize struct with zeroes zip_fileinfo zipInfo = zip_fileinfo(); CreateTMZip(zipInfo.tmz_date); + string fileName = filePath; my::GetNameFromFullPath(fileName); if (!strings::IsASCIIString(fileName)) - fileName = "MapsWithMe.kml"; + fileName = "MapsMe.kml"; - if (::zipOpenNewFileInZip(zip.Handle(), fileName.c_str(), &zipInfo, + if (zipOpenNewFileInZip(zip.Handle(), fileName.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 = READ_FILE_BUFFER_SIZE; - vector buffer(bufSize); - size_t const fileSize = f.Size(); - size_t currSize = 0; - - while (currSize < fileSize) + // Write source file into zip file. + try { - size_t const toRead = min(bufSize, fileSize - currSize); - f.Read(currSize, &buffer[0], toRead); + my::FileData file(filePath, my::FileData::OP_READ); + size_t const fileSize = file.Size(); - if (ZIP_OK != ::zipWriteInFileInZip(zip.Handle(), &buffer[0], toRead)) - return false; + size_t currSize = 0; + while (currSize < fileSize) + { + size_t const toRead = min(bufSize, fileSize - currSize); + file.Read(currSize, &buffer[0], toRead); - currSize += toRead; + if (ZIP_OK != zipWriteInFileInZip(zip.Handle(), &buffer[0], toRead)) + return false; + + currSize += toRead; + } + } + catch (Reader::Exception const & ex) + { + LOG(LERROR, ("Error reading file:", filePath, ex.Msg())); + return false; } + // Success. + outFileGuard.release(); return true; } diff --git a/coding/zip_reader.cpp b/coding/zip_reader.cpp index ffcca33951..76c733626e 100644 --- a/coding/zip_reader.cpp +++ b/coding/zip_reader.cpp @@ -4,6 +4,7 @@ #include "../base/logging.hpp" #include "../coding/file_writer.hpp" +#include "../coding/constants.hpp" #include "../std/bind.hpp" @@ -75,6 +76,12 @@ bool ZipFileReader::IsZip(string const & zipContainer) void ZipFileReader::UnzipFile(string const & zipContainer, string const & fileInZip, string const & outFilePath, ProgressFn progressFn) { + /// Prepare buffer at the very beginning to avoid clang 3.5, loop optimization. + /// @todo Need to check with the new XCode (and clang) update. + + size_t const bufSize = ZIP_FILE_BUFFER_SIZE; + vector buf(bufSize); + unzFile zip = unzOpen64(zipContainer.c_str()); if (!zip) MYTHROW(OpenZipException, ("Can't get zip file handle", zipContainer)); @@ -91,9 +98,6 @@ void ZipFileReader::UnzipFile(string const & zipContainer, string const & fileIn if (UNZ_OK != unzGetCurrentFileInfo64(zip, &fileInfo, NULL, 0, NULL, 0, NULL, 0)) MYTHROW(LocateZipException, ("Can't get uncompressed file size inside zip", fileInZip)); - size_t const BUF_SIZE = 1024 * 50; - vector buf(BUF_SIZE); - // First outFile should be closed, then FileWriter::DeleteFileX is called, // so make correct order of guards. MY_SCOPE_GUARD(outFileGuard, bind(&FileWriter::DeleteFileX, cref(outFilePath))); @@ -102,7 +106,7 @@ void ZipFileReader::UnzipFile(string const & zipContainer, string const & fileIn uint64_t pos = 0; while (true) { - int const readBytes = unzReadCurrentFile(zip, &buf[0], BUF_SIZE); + int const readBytes = unzReadCurrentFile(zip, &buf[0], bufSize); if (readBytes > 0) outFile.Write(&buf[0], static_cast(readBytes)); else if (readBytes < 0) diff --git a/iphone/Maps/Bookmarks/BookmarksVC.mm b/iphone/Maps/Bookmarks/BookmarksVC.mm index 698704922b..6a3308b712 100644 --- a/iphone/Maps/Bookmarks/BookmarksVC.mm +++ b/iphone/Maps/Bookmarks/BookmarksVC.mm @@ -261,17 +261,20 @@ BookmarkCategory const * cat = GetFramework().GetBmCategory(m_categoryIndex); if (cat) { - NSString * filePath = [NSString stringWithUTF8String:cat->GetFileName().c_str()]; NSMutableString * catName = [NSMutableString stringWithUTF8String:cat->GetName().c_str()]; if (![catName length]) - [catName setString:@"maps.me"]; + [catName setString:@"MapsMe"]; + + NSString * filePath = [NSString stringWithUTF8String:cat->GetFileName().c_str()]; NSMutableString * kmzFile = [NSMutableString stringWithString:filePath]; [kmzFile replaceCharactersInRange:NSMakeRange([filePath length] - 1, 1) withString:@"z"]; + if (CreateZipFromPathDeflatedAndDefaultCompression([filePath UTF8String], [kmzFile UTF8String])) [self sendBookmarksWithExtension:@".kmz" andType:@"application/vnd.google-earth.kmz" andFile:kmzFile andCategory:catName]; else [self sendBookmarksWithExtension:@".kml" andType:@"application/vnd.google-earth.kml+xml" andFile:filePath andCategory:catName]; - my::DeleteFileX([kmzFile UTF8String]); + + (void)my::DeleteFileX([kmzFile UTF8String]); } } }