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
) throw(std::bad_alloc
)
51 * Get name of current member.
53 * returns: Name of member.
54 * throws std::bad_alloc: Not enough memory.
56 reference
operator*() throw(std::bad_alloc
)
62 * Get name of current member.
64 * returns: Name of member.
65 * throws std::bad_alloc: Not enough memory.
67 pointer
operator->() throw(std::bad_alloc
)
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) throw(std::bad_alloc
)
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) throw(std::bad_alloc
)
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
) throw(std::bad_alloc
, std::runtime_error
);
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() throw(std::bad_alloc
);
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
) throw(std::bad_alloc
);
190 * returns: The iterator pointing to first name.
191 * throws std::bad_alloc: Not enough memory.
193 iterator
begin() throw(std::bad_alloc
);
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.
201 iterator
end() throw(std::bad_alloc
);
204 * Starting reverse iterator
206 * returns: The iterator pointing to last name and acting in reverse.
207 * throws std::bad_alloc: Not enough memory.
209 riterator
rbegin() throw(std::bad_alloc
);
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.
216 riterator
rend() throw(std::bad_alloc
);
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
) throw(std::bad_alloc
, std::runtime_error
);
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)
247 throw(std::bad_alloc
, std::runtime_error
);
251 * Parameter member: Name of the member to read.
252 * Parameter out: Buffer to write the output to.
253 * Throws std::bad_alloc: Not enough memory.
254 * Throws std::runtime_error: Error reading file.
256 void read_raw_file(const std::string
& member
, std::vector
<char>& out
) throw(std::bad_alloc
,
259 * Reads a file consisting of single numeric constant.
261 * Parameter member: Name of the member to read.
262 * Parameter out: The output value.
263 * Parameter conditional: If true and the file does not exist, return false instead of throwing.
264 * Returns: True on success, false on failure.
265 * Throws std::bad_alloc: Not enough memory.
266 * Throws std::runtime_error: Error reading file.
269 bool read_numeric_file(const std::string
& member
, T
& out
, bool conditional
= false)
270 throw(std::bad_alloc
, std::runtime_error
)
273 if(!read_linefile(member
, _out
, conditional
))
275 out
= parse_value
<T
>(_out
);
280 reader
& operator=(reader
&);
281 std::map
<std::string
, uint64_t> offsets
;
282 std::ifstream
* zipstream
;
287 * Opens the file named by name parameter, which is interpretted relative to file designated by referencing_path.
288 * The file can be inside ZIP archive. The resulting stream may or may not be seekable.
290 * If referencing_path is "", then name is traditional relative/absolute path. Otherwise if name is relative,
291 * it is relative to directory containing referencing_path, not current directory.
293 * parameter name: The name of file to open.
294 * parameter referencing_path: The path to file name is interpretted against.
295 * returns: The new stream, allocated by new.
296 * throw std::bad_alloc: Not enough memory.
297 * throw std::runtime_error: The file does not exist or can't be opened.
299 std::istream
& openrel(const std::string
& name
, const std::string
& referencing_path
) throw(std::bad_alloc
,
303 * As zip::openrel, but instead of returning handle to file, reads the entiere contents of the file and returns
306 * parameter name: As in zip::openrel
307 * parameter referencing_path: As in zip::openrel.
308 * returns: The file contents.
309 * throws std::bad_alloc: Not enough memory.
310 * throws std::runtime_error: The file does not exist or can't be opened.
312 std::vector
<char> readrel(const std::string
& name
, const std::string
& referencing_path
)
313 throw(std::bad_alloc
, std::runtime_error
);
316 * Resolves the final file path that zip::openrel/zip::readrel would open.
318 * parameter name: As in zip::openrel
319 * parameter referencing_path: As in zip::openrel
320 * returns: The file absolute path.
321 * throws std::bad_alloc: Not enough memory.
322 * throws std::runtime_error: Bad path.
324 std::string
resolverel(const std::string
& name
, const std::string
& referencing_path
) throw(std::bad_alloc
,
328 * Does the specified file (maybe inside .zip) exist?
330 * parameter name: The name of file.
331 * returns: True if file exists, false if not.
332 * throws std::bad_alloc: Not enough memory.
334 bool file_exists(const std::string
& name
) throw(std::bad_alloc
);
337 * This class handles writing a ZIP archives.
343 * Creates new empty ZIP archive. The members will be compressed according to specified compression.
345 * parameter zipfile: The zipfile to create.
346 * parameter stream: The stream to write the ZIP to.
347 * parameter _compression: Compression. 0 is uncompressed, 1-9 are deflate compression levels.
348 * throws std::bad_alloc: Not enough memory.
349 * throws std::runtime_error: Can't open archive or invalid argument.
351 writer(const std::string
& zipfile
, unsigned _compression
) throw(std::bad_alloc
, std::runtime_error
);
352 writer(std::ostream
& stream
, unsigned _compression
) throw(std::bad_alloc
, std::runtime_error
);
354 * Destroys ZIP writer, aborting the transaction (unless commit() has been called).
359 * Commits the ZIP file. Does atomic replace of existing file if possible.
361 * throws std::bad_alloc: Not enough memory.
362 * throws std::logic_error: Existing file open.
363 * throws std::runtime_error: Can't commit archive (OS error or member open).
365 void commit() throw(std::bad_alloc
, std::logic_error
, std::runtime_error
);
368 * Create a new member inside ZIP file. No existing member may be open.
370 * parameter name: The name for new member.
371 * returns: Writing stream for the file (don't free).
372 * throws std::bad_alloc: Not enough memory.
373 * throws std::logic_error: Existing file open.
374 * throws std::runtime_error: Illegal name.
376 std::ostream
& create_file(const std::string
& name
) throw(std::bad_alloc
, std::logic_error
,
380 * Closes open member and destroys stream corresponding to it.
382 * throws std::bad_alloc: Not enough memory.
383 * throws std::logic_error: No file open.
384 * throws std::runtime_error: Error from operating system.
386 void close_file() throw(std::bad_alloc
, std::logic_error
, std::runtime_error
);
388 * Write a file consisting of single line. No existing member may be open.
390 * Parameter member: The name of the member.
391 * Parameter value: The value to write.
392 * Parameter conditional: If true and the value is empty, skip the write.
393 * throws std::bad_alloc: Not enough memory.
394 * throws std::runtime_error: Error from operating system.
396 void write_linefile(const std::string
& member
, const std::string
& value
, bool conditional
= false)
397 throw(std::bad_alloc
, std::runtime_error
);
399 * Write a raw file. No existing member may be open.
401 * Parameter member: The name of the member.
402 * Parameter content: The contents for the file.
403 * throws std::bad_alloc: Not enough memory.
404 * throws std::runtime_error: Error from operating system.
406 void write_raw_file(const std::string
& member
, const std::vector
<char>& content
)
407 throw(std::bad_alloc
, std::runtime_error
);
409 * Write a file consisting of a single number. No existing member may be open.
411 * Parameter member: The name of the member.
412 * Parameter value: The value to write.
413 * throws std::bad_alloc: Not enough memory.
414 * throws std::runtime_error: Error from operating system.
417 void write_numeric_file(const std::string
& member
, T value
) throw(std::bad_alloc
, std::runtime_error
)
419 write_linefile(member
, (stringfmt() << value
).str());
425 uint32_t uncompressed_size
;
426 uint32_t compressed_size
;
431 writer
& operator=(writer
&);
432 std::ostream
* zipstream
;
434 std::string temp_path
;
435 std::string zipfile_path
;
436 std::string open_file
;
437 uint32_t base_offset
;
438 std::vector
<char> current_compressed_file
;
439 std::map
<std::string
, file_info
> files
;
440 unsigned compression
;
441 boost::iostreams::filtering_ostream
* s
;