RINGMesh  Version 5.0.0
A programming library for geological model meshes
zip_file.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2017, Association Scientifique pour la Geologie et ses
3  * Applications (ASGA). All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of ASGA nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ASGA BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  * http://www.ring-team.org
28  *
29  * RING Project
30  * Ecole Nationale Superieure de Geologie - GeoRessources
31  * 2 Rue du Doyen Marcel Roubault - TSA 70605
32  * 54518 VANDOEUVRE-LES-NANCY
33  * FRANCE
34  */
35 
36 #include <ringmesh/io/zip_file.h>
37 
38 #include <minizip/unzip.h>
39 #include <minizip/zip.h>
40 
41 #include <geogram/basic/file_system.h>
42 
44 
45 #define MAX_FILENAME 512
46 #define READ_SIZE 8192
47 
53 namespace RINGMesh
54 {
56  {
57  public:
58  Impl( const std::string& filename )
59  {
60  zip_file_ = zipOpen( filename.c_str(), APPEND_STATUS_CREATE );
61  if( zip_file_ == nullptr )
62  {
63  throw RINGMeshException(
64  "ZipFile", "Could not read file ", filename );
65  }
66  }
67 
69  {
70  zipClose( zip_file_, NULL );
71  }
72 
73  void add_file( const std::string& filename )
74  {
75  std::fstream file(
76  filename.c_str(), std::ios::in | std::ios::binary );
77  file.seekg( 0, std::ios::end );
78  auto size = static_cast< index_t >( file.tellg() );
79  file.seekg( 0, std::ios::beg );
80  std::vector< char > buffer( size );
81  file.read( &buffer[0], size );
82  zipOpenNewFileInZip( zip_file_, filename.c_str(), nullptr, nullptr,
83  0, nullptr, 0, nullptr, Z_DEFLATED, Z_DEFAULT_COMPRESSION );
84  zipWriteInFileInZip( zip_file_, size == 0 ? "" : &buffer[0], size );
85  zipCloseFileInZip( zip_file_ );
86  file.close();
87  }
88 
89  private:
90  zipFile zip_file_{ nullptr };
91  };
92 
93  ZipFile::ZipFile( const std::string& filename ) : impl_{ filename }
94  {
95  }
96 
98  {
99  }
100 
101  void ZipFile::add_file( const std::string& filename )
102  {
103  impl_->add_file( filename );
104  }
105 
107  {
108  public:
109  Impl( const std::string& filename )
110  {
111  zip_file_ = unzOpen( filename.c_str() );
112  if( zip_file_ == nullptr )
113  {
114  throw RINGMeshException(
115  "UnZipFile", "Could not read file ", filename );
116  }
117  }
118 
120  {
121  unzClose( zip_file_ );
122  }
123 
124  void get_file( const std::string& filename )
125  {
126  unzLocateFile( zip_file_, filename.c_str(), 0 );
127  unzip_current_file( zip_file_, filename );
128  }
129 
131  {
132  if( unzGoToFirstFile( zip_file_ ) != UNZ_OK )
133  {
134  throw RINGMeshException(
135  "UnZipFile", "Unable to uncompress the first file" );
136  }
137  }
138 
140  {
141  unzip_current_file( zip_file_, get_current_filename().c_str() );
142  }
143 
144  std::string get_current_filename()
145  {
146  char char_file_name[MAX_FILENAME];
147  if( unzGetCurrentFileInfo64( zip_file_, nullptr, char_file_name,
148  MAX_FILENAME, nullptr, 0, nullptr, 0 )
149  != UNZ_OK )
150  {
151  throw RINGMeshException(
152  "UnZipFile", "Unable to get file name" );
153  }
154  return { char_file_name };
155  }
156 
157  bool next_file()
158  {
159  return unzGoToNextFile( zip_file_ ) == UNZ_OK;
160  }
161 
162  private:
163  void unzip_current_file( unzFile uz, const std::string& filename )
164  {
165  char read_buffer[READ_SIZE];
166  if( unzOpenCurrentFile( uz ) != UNZ_OK )
167  {
168  unzClose( uz );
169  throw RINGMeshException( "UnZipFile", "Could not open file" );
170  }
171  FILE* out{ fopen( filename.c_str(), "wb" ) };
172  if( out == nullptr )
173  {
174  unzCloseCurrentFile( uz );
175  unzClose( uz );
176  throw RINGMeshException(
177  "UnZipFile", "Could not open destination file" );
178  }
179  int error{ UNZ_OK };
180  do
181  {
182  error = unzReadCurrentFile( uz, read_buffer, READ_SIZE );
183  if( error < 0 )
184  {
185  unzCloseCurrentFile( uz );
186  unzClose( uz );
187  fclose( out );
188  throw RINGMeshException(
189  "UnZipFile", "Invalid error: ", error );
190  }
191  if( error > 0 )
192  {
193  fwrite( read_buffer, static_cast< std::size_t >( error ),
194  std::size_t( 1 ), out );
195  }
196  } while( error > 0 );
197  fclose( out );
198  unzCloseCurrentFile( uz );
199  }
200 
201  private:
202  unzFile zip_file_{ nullptr };
203  };
204 
205  UnZipFile::UnZipFile( const std::string& filename ) : impl_{ filename }
206  {
207  }
208 
210  {
211  }
212 
213  void UnZipFile::get_file( const std::string& filename )
214  {
215  impl_->get_file( filename );
216  }
217 
219  {
220  impl_->start_extract();
221  }
222 
224  {
225  impl_->get_current_file();
226  }
227 
229  {
230  return impl_->get_current_filename();
231  }
232 
234  {
235  return impl_->next_file();
236  }
237 
238 } // namespace RINGMesh
void get_file(const std::string &filename)
Definition: zip_file.cpp:213
#define MAX_FILENAME
Definition: zip_file.cpp:45
void add_file(const std::string &filename)
Definition: zip_file.cpp:101
void add_file(const std::string &filename)
Definition: zip_file.cpp:73
std::string get_current_filename()
Definition: zip_file.cpp:228
std::string get_current_filename()
Definition: zip_file.cpp:144
Impl(const std::string &filename)
Definition: zip_file.cpp:58
#define READ_SIZE
Definition: zip_file.cpp:46
UnZipFile(const std::string &filename)
Definition: zip_file.cpp:205
void unzip_current_file(unzFile uz, const std::string &filename)
Definition: zip_file.cpp:163
Classes to build GeoModel from various inputs.
Definition: algorithm.h:48
void get_file(const std::string &filename)
Definition: zip_file.cpp:124
ZipFile(const std::string &filename)
Definition: zip_file.cpp:93
void error(index_t vertex_id_in_mesh_entity, index_t vertex_id_in_geomodel_mesh, const gmme_id &mesh_entity_gmme_id)
Impl(const std::string &filename)
Definition: zip_file.cpp:109