1 #ifndef _library__zip__hpp__included__
2 #define _library__zip__hpp__included__
4 #include <boost/iostreams/filtering_stream.hpp>
17 * This class opens ZIP archive and offers methods to read members off it.
23 * This iterator iterates members of ZIP archive.
25 template<typename T
, typename V
>
30 * C++ iterators stuff.
32 typedef std::bidirectional_iterator_tag iterator_category
;
34 typedef int difference_type
;
35 typedef const V
& reference
;
36 typedef const V
* pointer
;
39 * This constructs new iteration sequence. Only the first component (keys) are taken into
40 * account, the second component (values) are ignored.
42 * parameter _itr: The underlying map iterator.
43 * throws std::bad_alloc: Not enough memory.
45 iterator_class(T _itr
)
51 * Get name of current member.
53 * returns: Name of member.
54 * throws std::bad_alloc: Not enough memory.
62 * Get name of current member.
64 * returns: Name of member.
65 * throws std::bad_alloc: Not enough memory.
73 * Are these two iterators the same?
75 * parameter i: The another iterator
76 * returns: True if iterators are the same, false otherwise.
78 bool operator==(const iterator_class
<T
, V
>& i
) const throw()
84 * Are these two iterators diffrent?
86 * paramer i: The another iterator
87 * returns: True if iterators are diffrent, false otherwise.
89 bool operator!=(const iterator_class
<T
, V
>& i
) const throw()
95 * Advance iterator one step.
97 * returns: The old value of iterator.
98 * throws std::bad_alloc: Not enough memory.
100 const iterator_class
<T
, V
> operator++(int)
102 iterator_class
<T
, V
> c(*this);
108 * Regress iterator one step.
110 * returns: The old value of iterator.
111 * throws std::bad_alloc: Not enough memory.
113 const iterator_class
<T
, V
> operator--(int)
115 iterator_class
<T
, V
> c(*this);
121 * Advance iterator one step.
123 * returns: Reference to this iterator.
125 iterator_class
<T
, V
>& operator++() throw()
132 * Regress iterator one step.
134 * returns: Reference to this iterator.
136 iterator_class
<T
, V
>& operator--() throw()
146 * This iterator iterates members of ZIP archive in forward order.
148 typedef iterator_class
<std::map
<std::string
, uint64_t>::iterator
, std::string
> iterator
;
151 * This iterator iterates members of ZIP archive in reverse order
153 typedef iterator_class
<std::map
<std::string
, uint64_t>::reverse_iterator
, std::string
>
157 * Opens specified ZIP archive for reading.
159 * parameter zipfile: The name of ZIP file to open.
160 * throws std::bad_alloc: Not enough memory.
161 * throws std::runtime_error: Can't open the ZIP file.
163 reader(const std::string
& zipfile
);
166 * Destroy the ZIP reader. Opened input streams continue to be valid.
171 * Gives the name of the first member, or "" if empty archive.
173 * returns: The member name
174 * throws std::bad_alloc: Not enough memory.
176 std::string
find_first();
179 * Gives the name of the next member after specified, or "" if that member is the last.
181 * parameter name: The name to start the search from.
182 * returns: The member name
183 * throws std::bad_alloc: Not enough memory.
185 std::string
find_next(const std::string
& name
);
190 * returns: The iterator pointing to first name.
191 * throws std::bad_alloc: Not enough memory.
196 * Ending iterator (one past the end).
198 * returns: The iterator pointing to one past the last name.
199 * throws std::bad_alloc: Not enough memory.
204 * Starting reverse iterator
206 * returns: The iterator pointing to last name and acting in reverse.
207 * throws std::bad_alloc: Not enough memory.
212 * Ending reverse iterator (one past the start).
213 * returrns: The iterator pointing to one before the first name and acting in reverse.
214 * throws std::bad_alloc: Not enough memory.
219 * Check if member with specified name exists.
221 * parameter name: The name of the member to check
222 * returns: True if specified member exists, false otherwise.
224 bool has_member(const std::string
& name
) throw();
227 * Opens specified member. The resulting stream is not seekable, allocated using new and continues to be valid
228 * after ZIP reader has been destroyed.
230 * parameter name: The name of member to open.
231 * returns: The stream corresponding to member.
232 * throws std::bad_alloc: Not enough memory.
233 * throws std::runtime_error: The specified member does not exist
235 std::istream
& operator[](const std::string
& name
);
237 * Reads a file consisting of single line.
239 * Parameter member: Name of the member to read.
240 * Parameter out: String to write the output to.
241 * Parameter conditional: If true and the file does not exist, return false instead of throwing.
242 * Returns: True on success, false on failure.
243 * Throws std::bad_alloc: Not enough memory.
244 * Throws std::runtime_error: Error reading file.
246 bool read_linefile(const std::string
& member
, std::string
& out
, bool conditional
= false);
250 * Parameter member: Name of the member to read.
251 * Parameter out: Buffer to write the output to.
252 * Throws std::bad_alloc: Not enough memory.
253 * Throws std::runtime_error: Error reading file.
255 void read_raw_file(const std::string
& member
, std::vector
<char>& out
);
257 * Reads a file consisting of single numeric constant.
259 * Parameter member: Name of the member to read.
260 * Parameter out: The output value.
261 * Parameter conditional: If true and the file does not exist, return false instead of throwing.
262 * Returns: True on success, false on failure.
263 * Throws std::bad_alloc: Not enough memory.
264 * Throws std::runtime_error: Error reading file.
267 bool read_numeric_file(const std::string
& member
, T
& out
, bool conditional
= false)
270 if(!read_linefile(member
, _out
, conditional
))
272 out
= parse_value
<T
>(_out
);
277 reader
& operator=(reader
&);
278 std::map
<std::string
, uint64_t> offsets
;
279 std::ifstream
* zipstream
;
284 * Opens the file named by name parameter, which is interpretted relative to file designated by referencing_path.
285 * The file can be inside ZIP archive. The resulting stream may or may not be seekable.
287 * If referencing_path is "", then name is traditional relative/absolute path. Otherwise if name is relative,
288 * it is relative to directory containing referencing_path, not current directory.
290 * parameter name: The name of file to open.
291 * parameter referencing_path: The path to file name is interpretted against.
292 * returns: The new stream, allocated by new.
293 * throw std::bad_alloc: Not enough memory.
294 * throw std::runtime_error: The file does not exist or can't be opened.
296 std::istream
& openrel(const std::string
& name
, const std::string
& referencing_path
);
299 * As zip::openrel, but instead of returning handle to file, reads the entiere contents of the file and returns
302 * parameter name: As in zip::openrel
303 * parameter referencing_path: As in zip::openrel.
304 * returns: The file contents.
305 * throws std::bad_alloc: Not enough memory.
306 * throws std::runtime_error: The file does not exist or can't be opened.
308 std::vector
<char> readrel(const std::string
& name
, const std::string
& referencing_path
);
311 * Resolves the final file path that zip::openrel/zip::readrel would open.
313 * parameter name: As in zip::openrel
314 * parameter referencing_path: As in zip::openrel
315 * returns: The file absolute path.
316 * throws std::bad_alloc: Not enough memory.
317 * throws std::runtime_error: Bad path.
319 std::string
resolverel(const std::string
& name
, const std::string
& referencing_path
);
322 * Does the specified file (maybe inside .zip) exist?
324 * parameter name: The name of file.
325 * returns: True if file exists, false if not.
326 * throws std::bad_alloc: Not enough memory.
328 bool file_exists(const std::string
& name
);
331 * This class handles writing a ZIP archives.
337 * Creates new empty ZIP archive. The members will be compressed according to specified compression.
339 * parameter zipfile: The zipfile to create.
340 * parameter stream: The stream to write the ZIP to.
341 * parameter _compression: Compression. 0 is uncompressed, 1-9 are deflate compression levels.
342 * throws std::bad_alloc: Not enough memory.
343 * throws std::runtime_error: Can't open archive or invalid argument.
345 writer(const std::string
& zipfile
, unsigned _compression
);
346 writer(std::ostream
& stream
, unsigned _compression
);
348 * Destroys ZIP writer, aborting the transaction (unless commit() has been called).
353 * Commits the ZIP file. Does atomic replace of existing file if possible.
355 * throws std::bad_alloc: Not enough memory.
356 * throws std::logic_error: Existing file open.
357 * throws std::runtime_error: Can't commit archive (OS error or member open).
362 * Create a new member inside ZIP file. No existing member may be open.
364 * parameter name: The name for new member.
365 * returns: Writing stream for the file (don't free).
366 * throws std::bad_alloc: Not enough memory.
367 * throws std::logic_error: Existing file open.
368 * throws std::runtime_error: Illegal name.
370 std::ostream
& create_file(const std::string
& name
);
373 * Closes open member and destroys stream corresponding to it.
375 * throws std::bad_alloc: Not enough memory.
376 * throws std::logic_error: No file open.
377 * throws std::runtime_error: Error from operating system.
381 * Write a file consisting of single line. No existing member may be open.
383 * Parameter member: The name of the member.
384 * Parameter value: The value to write.
385 * Parameter conditional: If true and the value is empty, skip the write.
386 * throws std::bad_alloc: Not enough memory.
387 * throws std::runtime_error: Error from operating system.
389 void write_linefile(const std::string
& member
, const std::string
& value
, bool conditional
= false);
391 * Write a raw file. No existing member may be open.
393 * Parameter member: The name of the member.
394 * Parameter content: The contents for the file.
395 * throws std::bad_alloc: Not enough memory.
396 * throws std::runtime_error: Error from operating system.
398 void write_raw_file(const std::string
& member
, const std::vector
<char>& content
);
400 * Write a file consisting of a single number. No existing member may be open.
402 * Parameter member: The name of the member.
403 * Parameter value: The value to write.
404 * throws std::bad_alloc: Not enough memory.
405 * throws std::runtime_error: Error from operating system.
408 void write_numeric_file(const std::string
& member
, T value
)
410 write_linefile(member
, (stringfmt() << value
).str());
416 uint32_t uncompressed_size
;
417 uint32_t compressed_size
;
422 writer
& operator=(writer
&);
423 std::ostream
* zipstream
;
425 std::string temp_path
;
426 std::string zipfile_path
;
427 std::string open_file
;
428 uint32_t base_offset
;
429 std::vector
<char> current_compressed_file
;
430 std::map
<std::string
, file_info
> files
;
431 unsigned compression
;
432 boost::iostreams::filtering_ostream
* s
;