Mercurial > code
view 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 source
/* * 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_