Mercurial > code
changeset 313:cd490a8ab82a
Zip: add iterators to ZipArchive
Task: #331
author | David Demelier <markand@malikania.fr> |
---|---|
date | Wed, 25 Feb 2015 12:42:06 +0100 |
parents | ea1a73a7d468 |
children | 4c3019385769 |
files | C++/Tests/Zip/data/stats.zip C++/Tests/Zip/main.cpp C++/ZipArchive.cpp C++/ZipArchive.h |
diffstat | 4 files changed, 440 insertions(+), 50 deletions(-) [+] |
line wrap: on
line diff
--- a/C++/Tests/Zip/main.cpp Fri Feb 13 18:02:07 2015 +0100 +++ b/C++/Tests/Zip/main.cpp Wed Feb 25 12:42:06 2015 +0100 @@ -23,7 +23,7 @@ using namespace source; /* -------------------------------------------------------- - * File source + * Sources * -------------------------------------------------------- */ TEST(Source, file) @@ -77,49 +77,10 @@ } /* -------------------------------------------------------- - * Basic + * Write * -------------------------------------------------------- */ -TEST(Basic, numEntries) -{ - try { - ZipArchive archive{SOURCE "/data/stats.zip"}; - - ASSERT_EQ(static_cast<ZipInt64>(1), archive.numEntries()); - } catch (const std::exception &ex) { - std::cerr << ex.what() << std::endl; - } -} - -TEST(Basic, stat) -{ - try { - ZipArchive archive{SOURCE "/data/stats.zip"}; - ZipStat stats = archive.stat("README"); - - ASSERT_EQ(static_cast<decltype(stats.size)>(15), stats.size); - ASSERT_STREQ("README", stats.name); - } catch (const std::exception &ex) { - std::cerr << ex.what() << std::endl; - } -} - -TEST(Basic, read) -{ - try { - ZipArchive archive{SOURCE "/data/stats.zip"}; - - auto file = archive.open("README"); - auto stats = archive.stat("README"); - auto text = file.read(stats.size); - - ASSERT_EQ("This is a test\n", text); - } catch (const std::exception &ex) { - std::cerr << "warning: " << ex.what() << std::endl; - } -} - -TEST(Basic, write) +TEST(Write, simple) { remove(BINARY "/output.zip"); @@ -146,6 +107,161 @@ } } +/* -------------------------------------------------------- + * Reading + * -------------------------------------------------------- */ + +class ReadingTest : public testing::Test { +protected: + ZipArchive m_archive; + +public: + ReadingTest() + : m_archive(SOURCE "/data/stats.zip") + { + } +}; + +TEST_F(ReadingTest, numEntries) +{ + ASSERT_EQ(static_cast<ZipInt64>(4), m_archive.numEntries()); +} + +TEST_F(ReadingTest, stat) +{ + try { + ZipStat stats = m_archive.stat("README"); + + ASSERT_EQ(static_cast<decltype(stats.size)>(15), stats.size); + ASSERT_STREQ("README", stats.name); + } catch (const std::exception &ex) { + std::cerr << ex.what() << std::endl; + } +} + +TEST_F(ReadingTest, read) +{ + try { + auto file = m_archive.open("README"); + auto stats = m_archive.stat("README"); + auto text = file.read(stats.size); + + ASSERT_EQ("This is a test\n", text); + } catch (const std::exception &ex) { + std::cerr << "warning: " << ex.what() << std::endl; + } +} + +TEST_F(ReadingTest, increment) +{ + { + ZipArchive::iterator it = m_archive.begin(); + + ASSERT_STREQ("README", (*it++).name); + } + + { + ZipArchive::iterator it = m_archive.begin(); + + ASSERT_STREQ("INSTALL", (*++it).name); + } + + { + ZipArchive::iterator it = m_archive.begin() + 1; + + ASSERT_STREQ("INSTALL", (*it).name); + } +} + +TEST_F(ReadingTest, decrement) +{ + { + ZipArchive::iterator it = m_archive.begin() + 1; + + ASSERT_STREQ("INSTALL", (*it--).name); + } + + { + ZipArchive::iterator it = m_archive.begin() + 1; + + ASSERT_STREQ("README", (*--it).name); + } + + { + ZipArchive::iterator it = m_archive.end() - 1; + + ASSERT_STREQ("doc/REFMAN", (*it).name); + } +} + +TEST_F(ReadingTest, constIncrement) +{ + { + ZipArchive::const_iterator it = m_archive.cbegin(); + + ASSERT_STREQ("README", (*it++).name); + } + + { + ZipArchive::const_iterator it = m_archive.cbegin(); + + ASSERT_STREQ("INSTALL", (*++it).name); + } + + { + ZipArchive::const_iterator it = m_archive.cbegin() + 1; + + ASSERT_STREQ("INSTALL", (*it).name); + } +} + +TEST_F(ReadingTest, constDecrement) +{ + { + ZipArchive::const_iterator it = m_archive.cbegin() + 1; + + ASSERT_STREQ("INSTALL", (*it--).name); + } + + { + ZipArchive::const_iterator it = m_archive.cbegin() + 1; + + ASSERT_STREQ("README", (*--it).name); + } + + { + ZipArchive::const_iterator it = m_archive.cend() - 1; + + ASSERT_STREQ("doc/REFMAN", (*it).name); + } +} + +TEST_F(ReadingTest, access) +{ + { + ZipArchive::iterator it = m_archive.begin(); + + ASSERT_STREQ("README", it->name); + ASSERT_STREQ("INSTALL", it[1].name); + } + + { + ZipArchive::const_iterator it = m_archive.cbegin(); + + ASSERT_STREQ("README", it->name); + ASSERT_STREQ("INSTALL", it[1].name); + } +} + +TEST_F(ReadingTest, loop) +{ + std::vector<std::string> names{"README", "INSTALL", "doc/", "doc/REFMAN"}; + int i = 0; + + for (const ZipStat &s : m_archive) + ASSERT_STREQ(names[i++].c_str(), s.name); +} + int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv);
--- a/C++/ZipArchive.cpp Fri Feb 13 18:02:07 2015 +0100 +++ b/C++/ZipArchive.cpp Wed Feb 25 12:42:06 2015 +0100 @@ -146,7 +146,7 @@ return index; } -ZipStat ZipArchive::stat(const std::string &name, ZipFlags flags) +ZipStat ZipArchive::stat(const std::string &name, ZipFlags flags) const { ZipStat st; @@ -156,7 +156,7 @@ return st; } -ZipStat ZipArchive::stat(ZipUint64 index, ZipFlags flags) +ZipStat ZipArchive::stat(ZipUint64 index, ZipFlags flags) const { ZipStat st; @@ -247,7 +247,7 @@ throw std::runtime_error(zip_strerror(m_handle.get())); } -ZipInt64 ZipArchive::numEntries(ZipFlags flags) const +ZipInt64 ZipArchive::numEntries(ZipFlags flags) const noexcept { return zip_get_num_entries(m_handle.get(), flags); }
--- a/C++/ZipArchive.h Fri Feb 13 18:02:07 2015 +0100 +++ b/C++/ZipArchive.h Wed Feb 25 12:42:06 2015 +0100 @@ -19,6 +19,7 @@ #ifndef _ZIP_ARCHIVE_H_ #define _ZIP_ARCHIVE_H_ +#include <iterator> #include <memory> #include <string> @@ -203,6 +204,46 @@ } // !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 */ @@ -216,6 +257,181 @@ 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. * @@ -241,6 +457,66 @@ 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 @@ -295,7 +571,7 @@ * @return the structure * @throw std::runtime_error on errors */ - ZipStat stat(const std::string &name, ZipFlags flags = 0); + ZipStat stat(const std::string &name, ZipFlags flags = 0) const; /** * Get information about a file. Overloaded function. @@ -305,7 +581,7 @@ * @return the structure * @throw std::runtime_error on errors */ - ZipStat stat(ZipUint64 index, ZipFlags flags = 0); + ZipStat stat(ZipUint64 index, ZipFlags flags = 0) const; /** * Add a file to the archive. @@ -395,9 +671,8 @@ * * @param flags the optional flags * @return the number of entries - * @throw std::runtime_error on errors */ - ZipInt64 numEntries(ZipFlags flags = 0) const; + ZipInt64 numEntries(ZipFlags flags = 0) const noexcept; /** * Revert changes on the file. @@ -447,7 +722,6 @@ * @throw std::runtime_error on errors */ int getFlag(ZipFlags which, ZipFlags flags = 0) const; - }; #endif // !_ZIP_ARCHIVE_H_