Mercurial > code
diff C++/modules/Zip/ZipArchive.h @ 334:0b576ee64d45
* Create brand new hierarchy
* Rename DynLib to Dynlib
* Remove some warnings
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sun, 08 Mar 2015 14:26:33 +0100 |
parents | C++/ZipArchive.h@cd490a8ab82a |
children | c293dbe181c0 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/C++/modules/Zip/ZipArchive.h Sun Mar 08 14:26:33 2015 +0100 @@ -0,0 +1,727 @@ +/* + * ZipArchive.h -- wrapper around libzip + * + * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _ZIP_ARCHIVE_H_ +#define _ZIP_ARCHIVE_H_ + +#include <iterator> +#include <memory> +#include <string> + +#include <zip.h> + +using ZipStat = struct zip_stat; +using ZipSourceCommand = enum zip_source_cmd; +using ZipCallback = zip_source_callback; + +using ZipFlags = zip_flags_t; +using ZipInt8 = zip_int8_t; +using ZipUint8 = zip_uint8_t; +using ZipInt16 = zip_int16_t; +using ZipUint16 = zip_uint16_t; +using ZipInt32 = zip_int32_t; +using ZipUint32 = zip_uint32_t; +using ZipInt64 = zip_int64_t; +using ZipUint64 = zip_uint64_t; + +/** + * @class ZipSource + * @brief Source for adding file + */ +class ZipSource { +public: + /** + * Default constructor. + */ + ZipSource() = default; + + /** + * Virtual destructor. + */ + virtual ~ZipSource() = default; + + /** + * Create a zip_source structure. Must not be null, throw an exception + * instead. + * + * @return a zip_source ready to be used + * @throw std::runtime_error on errors + * @post must not return null + */ + virtual struct zip_source *source(struct zip *zip) const = 0; +}; + +/** + * @class ZipFile + * @brief File for reading + */ +class ZipFile { +private: + std::unique_ptr<struct zip_file, int (*)(struct zip_file *)> m_handle; + + ZipFile(const ZipFile &) = delete; + ZipFile &operator=(const ZipFile &) = delete; + +public: + /** + * Create a ZipFile with a zip_file structure. + * + * @param file the file ready to be used + */ + inline ZipFile(struct zip_file *file) + : m_handle(file, zip_fclose) + { + } + + /** + * Move constructor defaulted. + * + * @param other the other ZipFile + */ + ZipFile(ZipFile &&other) noexcept = default; + + /** + * Move operator defaulted. + * + * @param other the other ZipFile + * @return *this + */ + ZipFile &operator=(ZipFile &&) noexcept = default; + + /** + * Read some data. + * + * @param data the destination buffer + * @param length the length + * @return the number of bytes written or -1 on failure + */ + inline int read(void *data, ZipUint64 length) noexcept + { + return zip_fread(m_handle.get(), data, length); + } + + /** + * Read some data to a fixed size array. + * + * @param data the array + * @return the number of bytes written or -1 on failure + */ + template <size_t Size> + inline int read(char (&data)[Size]) noexcept + { + return read(data, Size); + } + + /** + * Optimized function for reading all characters with only one allocation. + * Ideal for combining with ZipArchive::stat. + * + * @param length the length of the file + * @return the whole string + * @see ZipArchive::stat + */ + std::string read(unsigned length) + { + std::string result; + + result.resize(length); + auto count = read(&result[0], length); + + if (count < 0) + return ""; + + result.resize(count); + + return result; + } +}; + +namespace source { + +/** + * @class Buffer + * @brief Create a source from a buffer + */ +class Buffer : public ZipSource { +private: + std::string m_data; + +public: + /** + * Buffer constructor. Moves the data. + * + * @param data the data + */ + Buffer(std::string data); + + /** + * @copydoc ZipSource::source + */ + struct zip_source *source(struct zip *archive) const override; +}; + +/** + * @class File + * @brief Create a source from a file on the disk + */ +class File : public ZipSource { +private: + std::string m_path; + ZipUint64 m_start; + ZipInt64 m_length; + +public: + /** + * File constructor. + * + * @param path the path to the file + * @param start the beginning in the file + * @param length the maximum length + */ + File(std::string path, ZipUint64 start = 0, ZipInt64 length = -1); + + /** + * @copydoc ZipSource::source + */ + struct zip_source *source(struct zip *archive) const override; +}; + +} // !source + +/** + * @class ZipStatPtr + * @brief Wrapper for ZipStat as pointer + */ +class ZipStatPtr { +private: + ZipStat &m_stat; + +public: + /** + * Constructor. + * + * @param stat the file stat + */ + inline ZipStatPtr(ZipStat stat) noexcept + : m_stat(stat) + { + } + + /** + * Get the reference. + * + * @return the reference + */ + inline ZipStat &operator*() const noexcept + { + return m_stat; + } + + /** + * Access the object. + * + * @return the pointer + */ + inline ZipStat *operator->() const noexcept + { + return &m_stat; + } +}; + +/** + * @class ZipArchive + * @brief Safe wrapper on the struct zip structure + */ +class ZipArchive { +private: + using Handle = std::unique_ptr<struct zip, int (*)(struct zip *)>; + + Handle m_handle; + + ZipArchive(const ZipArchive &) = delete; + ZipArchive &operator=(const ZipArchive &) = delete; + +public: + using value_type = ZipStat; + using reference = ZipStat; + using const_refernce = ZipStat; + using pointer = ZipStatPtr; + using size_type = unsigned; + + /** + * @class iterator + * @brief Iterator + */ + class iterator : public std::iterator<std::random_access_iterator_tag, ZipArchive> { + private: + ZipArchive &m_archive; + ZipUint64 m_index; + + public: + explicit inline iterator(ZipArchive &archive, ZipUint64 index = 0) noexcept + : m_archive(archive) + , m_index(index) + { + } + + inline ZipStat operator*() const + { + return m_archive.stat(m_index); + } + + inline ZipStatPtr operator->() const + { + return ZipStatPtr(m_archive.stat(m_index)); + } + + inline iterator &operator++() noexcept + { + ++ m_index; + + return *this; + } + + inline iterator operator++(int) noexcept + { + iterator save = *this; + + ++ m_index; + + return save; + } + + inline iterator &operator--() noexcept + { + -- m_index; + + return *this; + } + + inline iterator operator--(int) noexcept + { + iterator save = *this; + + -- m_index; + + return save; + } + + inline iterator operator+(int inc) const noexcept + { + return iterator(m_archive, m_index + inc); + } + + inline iterator operator-(int dec) const noexcept + { + return iterator(m_archive, m_index - dec); + } + + inline bool operator==(const iterator &other) const noexcept + { + return m_index == other.m_index; + } + + inline bool operator!=(const iterator &other) const noexcept + { + return m_index != other.m_index; + } + + inline ZipStat operator[](int index) const + { + return m_archive.stat(index); + } + }; + + /** + * @class const_iterator + * @brief Const iterator + */ + class const_iterator : public std::iterator<std::random_access_iterator_tag, ZipArchive> { + private: + const ZipArchive &m_archive; + ZipUint64 m_index; + + public: + explicit inline const_iterator(const ZipArchive &archive, ZipUint64 index = 0) noexcept + : m_archive(archive) + , m_index(index) + { + } + + inline ZipStat operator*() const + { + return m_archive.stat(m_index); + } + + inline ZipStatPtr operator->() const + { + return ZipStatPtr(m_archive.stat(m_index)); + } + + inline const_iterator &operator++() noexcept + { + ++ m_index; + + return *this; + } + + inline const_iterator operator++(int) noexcept + { + const_iterator save = *this; + + ++ m_index; + + return save; + } + + inline const_iterator &operator--() noexcept + { + -- m_index; + + return *this; + } + + inline const_iterator operator--(int) noexcept + { + const_iterator save = *this; + + -- m_index; + + return save; + } + + inline const_iterator operator+(int inc) const noexcept + { + return const_iterator(m_archive, m_index + inc); + } + + inline const_iterator operator-(int dec) const noexcept + { + return const_iterator(m_archive, m_index - dec); + } + + inline bool operator==(const const_iterator &other) const noexcept + { + return m_index == other.m_index; + } + + inline bool operator!=(const const_iterator &other) const noexcept + { + return m_index != other.m_index; + } + + inline ZipStat operator[](int index) const + { + return m_archive.stat(index); + } + }; + +public: + /** + * Open an archive on the disk. + * + * @param path the path + * @param flags the optional flags + * @throw std::runtime_error on errors + */ + ZipArchive(const std::string &path, ZipFlags flags = 0); + + /** + * Move constructor defaulted. + * + * @param other the other ZipArchive + */ + ZipArchive(ZipArchive &&other) noexcept = default; + + /** + * Move operator defaulted. + * + * @param other the other ZipArchive + * @return *this + */ + ZipArchive &operator=(ZipArchive &&other) noexcept = default; + + /** + * Get an iterator to the beginning. + * + * @return the iterator + */ + inline iterator begin() noexcept + { + return iterator(*this); + } + + /** + * Overloaded function. + * + * @return the iterator + */ + inline const_iterator begin() const noexcept + { + return const_iterator(*this); + } + + /** + * Overloaded function. + * + * @return the iterator + */ + inline const_iterator cbegin() const noexcept + { + return const_iterator(*this); + } + + /** + * Get an iterator to the end. + * + * @return the iterator + */ + inline iterator end() noexcept + { + return iterator(*this, numEntries()); + } + + /** + * Overloaded function. + * + * @return the iterator + */ + inline const_iterator end() const noexcept + { + return const_iterator(*this, numEntries()); + } + + /** + * Overloaded function. + * + * @return the iterator + */ + inline const_iterator cend() const noexcept + { + return const_iterator(*this, numEntries()); + } + + /** + * Set a comment on a file. + * + * @param index the file index in the archive + * @param text the text or empty to remove the comment + * @param flags the optional flags + * @throw std::runtime_error on errors + */ + void setFileComment(ZipUint64 index, const std::string &text = "", ZipFlags flags = 0); + + /** + * Get a comment from a file. + * + * @param index the file index in the archive + * @param flags the optional flags + * @return the comment + * @throw std::runtime_error on errors + */ + std::string getFileComment(ZipUint64 index, ZipFlags flags = 0) const; + + /** + * Set the archive comment. + * + * @param comment the comment + * @throw std::runtime_error on errors + */ + void setComment(const std::string &comment); + + /** + * Get the archive comment. + * + * @param flags the optional flags + * @return the comment + * @throw std::runtime_error on errors + */ + std::string getComment(ZipFlags flags = 0) const; + + /** + * Locate a file on the archive. + * + * @param name the name + * @param flags the optional flags + * @return the index + * @throw std::runtime_error on errors + */ + ZipInt64 find(const std::string &name, ZipFlags flags = 0); + + /** + * Get information about a file. + * + * @param name the name + * @param flags the optional flags + * @return the structure + * @throw std::runtime_error on errors + */ + ZipStat stat(const std::string &name, ZipFlags flags = 0) const; + + /** + * Get information about a file. Overloaded function. + * + * @param index the file index in the archive + * @param flags the optional flags + * @return the structure + * @throw std::runtime_error on errors + */ + ZipStat stat(ZipUint64 index, ZipFlags flags = 0) const; + + /** + * Add a file to the archive. + * + * @param source the source + * @param name the name entry in the archive + * @param flags the optional flags + * @return the new index in the archive + * @throw std::runtime_error on errors + * @see source::File + * @see source::Buffer + */ + ZipInt64 add(const ZipSource &source, const std::string &name, ZipFlags flags = 0); + + /** + * Add a directory to the archive. Not a directory from the disk. + * + * @param directory the directory name + * @param flags the optional flags + * @return the new index in the archive + * @throw std::runtime_error on errors + */ + ZipInt64 addDirectory(const std::string &directory, ZipFlags flags = 0); + + /** + * Replace an existing file in the archive. + * + * @param source the source + * @param index the file index in the archiev + * @param flags the optional flags + * @throw std::runtime_error on errors + */ + void replace(const ZipSource &source, ZipUint64 index, ZipFlags flags = 0); + + /** + * Open a file in the archive. + * + * @param name the name + * @param flags the optional flags + * @param password the optional password + * @return the opened file + * @throw std::runtime_error on errors + */ + ZipFile open(const std::string &name, ZipFlags flags = 0, const std::string &password = ""); + + /** + * Open a file in the archive. Overloaded function. + * + * @param index the file index in the archive + * @param flags the optional flags + * @param password the optional password + * @return the opened file + * @throw std::runtime_error on errors + */ + ZipFile open(ZipUint64 index, ZipFlags flags = 0, const std::string &password = ""); + + /** + * Rename an existing entry in the archive. + * + * @param index the file index in the archive + * @param name the new name + * @param flags the optional flags + * @throw std::runtime_error on errors + */ + void rename(ZipUint64 index, const std::string &name, ZipFlags flags = 0); + + /** + * Set file compression. + * + * @param index the file index in the archive + * @param comp the compression + * @param flags the optional flags + * @throw std::runtime_error on errors + */ + void setFileCompression(ZipUint64 index, ZipInt32 comp, ZipUint32 flags = 0); + + /** + * Delete a file from the archive. + * + * @param index the file index in the archive + * @throw std::runtime_error on errors + */ + void remove(ZipUint64 index); + + /** + * Get the number of entries in the archive. + * + * @param flags the optional flags + * @return the number of entries + */ + ZipInt64 numEntries(ZipFlags flags = 0) const noexcept; + + /** + * Revert changes on the file. + * + * @param index the index + * @throw std::runtime_error on errors + */ + void unchange(ZipUint64 index); + + /** + * Revert all changes. + * + * @throw std::runtime_error on errors + */ + void unchangeAll(); + + /** + * Revert changes to archive. + * + * @throw std::runtime_error on errors + */ + void unchangeArchive(); + + /** + * Set the defaut password. + * + * @param password the password or empty to unset it + * @throw std::runtime_error on errors + */ + void setDefaultPassword(const std::string &password = ""); + + /** + * Set an archive flag. + * + * @param flag the flag to set + * @param value the value + * @throw std::runtime_error on errors + */ + void setFlag(ZipFlags flag, int value); + + /** + * Get an archive flag. + * + * @param which which flag + * @param flags the optional flags + * @return the value + * @throw std::runtime_error on errors + */ + int getFlag(ZipFlags which, ZipFlags flags = 0) const; +}; + +#endif // !_ZIP_ARCHIVE_H_