1 #ifndef _zip__hpp__included__
2 #define _zip__hpp__included__
4 #include <boost/iostreams/filtering_stream.hpp>
13 * \brief Read files from ZIP archive
15 * This class opens ZIP archive and offers methods to read members off it.
21 * \brief ZIP file iterator
23 * This iterator iterates members of ZIP archive.
25 template<typename T
, typename V
>
30 * \brief C++ iterators stuff.
32 typedef std::bidirectional_iterator_tag iterator_category
;
34 * \brief C++ iterators stuff.
38 * \brief C++ iterators stuff.
40 typedef int difference_type
;
42 * \brief C++ iterators stuff.
44 typedef const V
& reference
;
46 * \brief C++ iterators stuff.
48 typedef const V
* pointer
;
51 * \brief Construct new iterator with specified names
53 * This constructs new iteration sequence. Only the first component (keys) are taken into
54 * account, the second component (values) are ignored.
56 * \param _itr The underlying map iterator.
57 * \throws std::bad_alloc Not enough memory.
59 iterator_class(T _itr
) throw(std::bad_alloc
)
65 * \brief Get name of current member.
66 * \return Name of member.
67 * \throws std::bad_alloc Not enough memory.
69 reference
operator*() throw(std::bad_alloc
)
75 * \brief Get name of current member.
76 * \return Name of member.
77 * \throws std::bad_alloc Not enough memory.
79 pointer
operator->() throw(std::bad_alloc
)
85 * \brief Are these two iterators the same?
86 * \param i The another iterator
87 * \return True if iterators are the same, false otherwise.
89 bool operator==(const iterator_class
<T
, V
>& i
) const throw()
95 * \brief Are these two iterators diffrent?
96 * \param i The another iterator
97 * \return True if iterators are diffrent, false otherwise.
99 bool operator!=(const iterator_class
<T
, V
>& i
) const throw()
105 * \brief Advance iterator one step.
106 * \return The old value of iterator.
107 * \throws std::bad_alloc Not enough memory.
109 const iterator_class
<T
, V
> operator++(int) throw(std::bad_alloc
)
111 iterator_class
<T
, V
> c(*this);
117 * \brief Regress iterator one step.
118 * \return The old value of iterator.
119 * \throws std::bad_alloc Not enough memory.
121 const iterator_class
<T
, V
> operator--(int) throw(std::bad_alloc
)
123 iterator_class
<T
, V
> c(*this);
129 * \brief Advance iterator one step.
130 * \return Reference to this iterator.
132 iterator_class
<T
, V
>& operator++() throw()
139 * \brief Regress iterator one step.
140 * \return Reference to this iterator.
142 iterator_class
<T
, V
>& operator--() throw()
152 * \brief ZIP file forward iterator
154 * This iterator iterates members of ZIP archive in forward order.
156 typedef iterator_class
<std::map
<std::string
, unsigned long long>::iterator
, std::string
> iterator
;
159 * \brief ZIP file reverse iterator
161 * This iterator iterates members of ZIP archive in reverse order
163 typedef iterator_class
<std::map
<std::string
, unsigned long long>::reverse_iterator
, std::string
>
167 * \brief Open a ZIP archive.
169 * Opens specified ZIP archive.
170 * \param zipfile The ZIP file to open.
171 * \throws std::bad_alloc Not enough memory.
172 * \throws std::runtime_error Can't open the ZIP file.
174 zip_reader(const std::string
& zipfile
) throw(std::bad_alloc
, std::runtime_error
);
179 * Destroy the ZIP reader. Opened input streams continue to be valid.
181 ~zip_reader() throw();
184 * \brief Find the name of first member.
186 * Gives the name of the first member, or "" if empty archive.
188 * \return The member name
189 * \throws std::bad_alloc Not enough memory.
191 std::string
find_first() throw(std::bad_alloc
);
194 * \brief Find the next member.
196 * Gives the name of the next member after specified, or "" if that member is the last.
198 * \param name The name to start the search from.
199 * \return The member name
200 * \throws std::bad_alloc Not enough memory.
202 std::string
find_next(const std::string
& name
) throw(std::bad_alloc
);
205 * \brief Starting iterator
206 * \return The iterator pointing to first name.
207 * \throws std::bad_alloc Not enough memory.
209 iterator
begin() throw(std::bad_alloc
);
212 * \brief Ending iterator
213 * \return The iterator pointing to one past the last name.
214 * \throws std::bad_alloc Not enough memory.
216 iterator
end() throw(std::bad_alloc
);
219 * \brief Starting reverse iterator
220 * \return The iterator pointing to last name and acting in reverse.
221 * \throws std::bad_alloc Not enough memory.
223 riterator
rbegin() throw(std::bad_alloc
);
226 * \brief Ending reverse iterator
227 * \return The iterator pointing to one before the first name and acting in reverse.
228 * \throws std::bad_alloc Not enough memory.
230 riterator
rend() throw(std::bad_alloc
);
233 * \brief Does the member exist?
234 * \param name The name of the member.
235 * \return True if specified member exists, false otherwise.
237 bool has_member(const std::string
& name
) throw();
242 * Opens specified member. The stream is not seekable, allocated using new and continues to be valid after
243 * ZIP reader has been destroyed.
245 * \param name The name of member to open.
246 * \return The stream corresponding to member.
247 * \throws std::bad_alloc Not enough memory.
248 * \throws std::runtime_error The specified member does not exist
250 std::istream
& operator[](const std::string
& name
) throw(std::bad_alloc
, std::runtime_error
);
252 zip_reader(zip_reader
&);
253 zip_reader
& operator=(zip_reader
&);
254 std::map
<std::string
, unsigned long long> offsets
;
255 std::ifstream
* zipstream
;
260 * \brief Open file relative to another
262 * Opens the file named by name parameter, which is interpretted relative to file designated by referencing_path.
263 * The file can be inside ZIP archive. The resulting stream may or may not be seekable.
265 * If referencing_path is "", then name is traditional relative/absolute path. Otherwise if name is relative,
266 * it is relative to directory containing referencing_path, not current directory.
268 * \param name The name of file to open.
269 * \param referencing_path The path to file name is interpretted against.
270 * \return The new stream, allocated by new.
271 * \throw std::bad_alloc Not enough memory.
272 * \throw std::runtime_error The file does not exist or can't be opened.
274 std::istream
& open_file_relative(const std::string
& name
, const std::string
& referencing_path
) throw(std::bad_alloc
,
278 * \brief Read file relative to another.
280 * Reads the entiere content of file named by name parameter, which is interpretted relative to file designated by
281 * referencing_path. The file can be inside ZIP archive.
283 * If referencing_path is "", then name is traditional relative/absolute path. Otherwise if name is relative,
284 * it is relative to directory containing referencing_path, not current directory.
286 * \param name The name of file to read.
287 * \param referencing_path The path to file name is interpretted against.
288 * \return The file contents.
289 * \throw std::bad_alloc Not enough memory.
290 * \throw std::runtime_error The file does not exist or can't be opened.
292 std::vector
<char> read_file_relative(const std::string
& name
, const std::string
& referencing_path
)
293 throw(std::bad_alloc
, std::runtime_error
);
296 * \brief Resolve full path of file relative to another.
298 * Resolves the final file path that open_file_relative/read_file_relative would open.
300 * \param name The name of file to read.
301 * \param referencing_path The path to file name is interpretted against.
302 * \return The file absolute path.
303 * \throw std::bad_alloc Not enough memory.
304 * \throw std::runtime_error Bad path.
306 std::string
resolve_file_relative(const std::string
& name
, const std::string
& referencing_path
) throw(std::bad_alloc
,
310 * \brief Write a ZIP archive
312 * This class handles writing a ZIP archive.
318 * \brief Create new empty ZIP archive.
320 * Creates new empty ZIP archive. The members will be compressed according to specified compression.
322 * \param zipfile The zipfile to create.
323 * \param _compression Compression. 0 is uncompressed, 1-9 are deflate compression levels.
324 * \throws std::bad_alloc Not enough memory.
325 * \throws std::runtime_error Can't open archive or invalid argument.
327 zip_writer(const std::string
& zipfile
, unsigned _compression
) throw(std::bad_alloc
, std::runtime_error
);
330 * \brief Destroy ZIP writer.
332 * Destroys ZIP writer, aborting the transaction (unless commit() has been called).
334 ~zip_writer() throw();
337 * \brief Commit the transaction
339 * Commits the ZIP file. Does atomic replace of existing file if possible.
341 * \throws std::bad_alloc Not enough memory.
342 * \throws std::logic_error Existing file open.
343 * \throws std::runtime_error Can't commit archive (OS error or member open).
345 void commit() throw(std::bad_alloc
, std::logic_error
, std::runtime_error
);
348 * \brief Create a new member
350 * Create a new member inside ZIP file. No existing member may be open.
352 * \param name The name for new member.
353 * \return Writing stream for the file (don't free).
355 * \throws std::bad_alloc Not enough memory.
356 * \throws std::logic_error Existing file open.
357 * \throws std::runtime_error Illegal name.
359 std::ostream
& create_file(const std::string
& name
) throw(std::bad_alloc
, std::logic_error
, std::runtime_error
);
362 * \brief Close open member
364 * Closes open member and destroys stream corresponding to it.
366 * \throws std::bad_alloc Not enough memory.
367 * \throws std::logic_error No file open.
368 * \throws std::runtime_error Error from operating system.
370 void close_file() throw(std::bad_alloc
, std::logic_error
, std::runtime_error
);
375 unsigned long uncompressed_size
;
376 unsigned long compressed_size
;
377 unsigned long offset
;
380 zip_writer(zip_writer
&);
381 zip_writer
& operator=(zip_writer
&);
382 std::ofstream zipstream
;
383 std::string temp_path
;
384 std::string zipfile_path
;
385 std::string open_file
;
386 uint32_t base_offset
;
387 std::vector
<char> current_compressed_file
;
388 std::map
<std::string
, zip_file_info
> files
;
389 unsigned compression
;
390 boost::iostreams::filtering_ostream
* s
;