Skip to content

Commit 3680739

Browse files
authored
Implement archive files (#379)
1 parent 3260cb0 commit 3680739

23 files changed

Lines changed: 771 additions & 791 deletions

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ set(ODR_SOURCE_FILES
7272
"src/odr/internal/resource_data.cpp"
7373

7474
"src/odr/internal/cfb/cfb_archive.cpp"
75+
"src/odr/internal/cfb/cfb_file.cpp"
7576
"src/odr/internal/cfb/cfb_impl.cpp"
7677
"src/odr/internal/cfb/cfb_util.cpp"
7778

@@ -164,6 +165,7 @@ set(ODR_SOURCE_FILES
164165

165166
"src/odr/internal/zip/zip_archive.cpp"
166167
"src/odr/internal/zip/zip_exceptions.cpp"
168+
"src/odr/internal/zip/zip_file.cpp"
167169
"src/odr/internal/zip/zip_util.cpp"
168170
)
169171

src/odr/archive.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ Filesystem Archive::filesystem() const {
1919
m_impl->filesystem()));
2020
}
2121

22-
void Archive::save(const std::string &path) const { m_impl->save(path); }
22+
void Archive::save(std::ostream &out) const { m_impl->save(out); }
2323

2424
} // namespace odr

src/odr/archive.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class Archive {
2020

2121
[[nodiscard]] Filesystem filesystem() const;
2222

23-
void save(const std::string &path) const;
23+
void save(std::ostream &out) const;
2424

2525
private:
2626
std::shared_ptr<internal::abstract::Archive> m_impl;

src/odr/internal/abstract/archive.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class Archive {
1616

1717
[[nodiscard]] virtual std::shared_ptr<Filesystem> filesystem() const = 0;
1818

19-
virtual void save(const common::Path &path) const = 0;
19+
virtual void save(std::ostream &out) const = 0;
2020
};
2121

2222
} // namespace odr::internal::abstract
Lines changed: 13 additions & 180 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include <odr/internal/cfb/cfb_archive.hpp>
22

3+
#include <odr/exceptions.hpp>
34
#include <odr/internal/cfb/cfb_util.hpp>
5+
#include <odr/internal/common/filesystem.hpp>
46
#include <odr/internal/util/string_util.hpp>
57

68
namespace odr::internal::abstract {
@@ -13,192 +15,23 @@ class MemoryFile;
1315

1416
namespace odr::internal::cfb {
1517

16-
ReadonlyCfbArchive::Entry::Entry(const ReadonlyCfbArchive &parent,
17-
const impl::CompoundFileEntry &entry)
18-
: m_parent{&parent}, m_entry{&entry}, m_path{"/"} {}
18+
CfbArchive::CfbArchive(std::shared_ptr<util::Archive> archive)
19+
: m_cfb{std::move(archive)} {}
1920

20-
ReadonlyCfbArchive::Entry::Entry(const ReadonlyCfbArchive &parent,
21-
const impl::CompoundFileEntry &entry,
22-
const common::Path &parent_path)
23-
: m_parent{&parent}, m_entry{&entry}, m_path{parent_path.join(name())} {}
21+
std::shared_ptr<abstract::Filesystem> CfbArchive::filesystem() const {
22+
auto filesystem = std::make_shared<common::VirtualFilesystem>();
2423

25-
bool ReadonlyCfbArchive::Entry::operator==(const Entry &other) const {
26-
return m_entry == other.m_entry;
27-
}
28-
29-
bool ReadonlyCfbArchive::Entry::operator!=(const Entry &other) const {
30-
return m_entry != other.m_entry;
31-
}
32-
33-
bool ReadonlyCfbArchive::Entry::is_file() const { return m_entry->is_stream(); }
34-
35-
bool ReadonlyCfbArchive::Entry::is_directory() const {
36-
return !m_entry->is_stream();
37-
}
38-
39-
common::Path ReadonlyCfbArchive::Entry::path() const { return m_path; }
40-
41-
std::unique_ptr<abstract::File> ReadonlyCfbArchive::Entry::file() const {
42-
if (!is_file()) {
43-
return {};
44-
}
45-
return std::make_unique<util::FileInCfb>(m_parent->m_cfb, *m_entry);
46-
}
47-
48-
std::string ReadonlyCfbArchive::Entry::name() const {
49-
return odr::internal::util::string::c16str_to_string(
50-
reinterpret_cast<const char16_t *>(m_entry->name), m_entry->name_len - 2);
51-
}
52-
53-
std::optional<ReadonlyCfbArchive::Entry>
54-
ReadonlyCfbArchive::Entry::left() const {
55-
auto left = m_parent->m_cfb->cfb().get_entry(m_entry->left_sibling_id);
56-
if (left == nullptr) {
57-
return {};
58-
}
59-
return Entry(*m_parent, *left, m_path.parent());
60-
}
61-
62-
std::optional<ReadonlyCfbArchive::Entry>
63-
ReadonlyCfbArchive::Entry::right() const {
64-
auto right = m_parent->m_cfb->cfb().get_entry(m_entry->right_sibling_id);
65-
if (right == nullptr) {
66-
return {};
67-
}
68-
return Entry(*m_parent, *right, m_path.parent());
69-
}
70-
71-
std::optional<ReadonlyCfbArchive::Entry>
72-
ReadonlyCfbArchive::Entry::child() const {
73-
auto child = m_parent->m_cfb->cfb().get_entry(m_entry->child_id);
74-
if (child == nullptr) {
75-
return {};
76-
}
77-
return Entry(*m_parent, *child, m_path);
78-
}
79-
80-
ReadonlyCfbArchive::Iterator::Iterator() = default;
81-
82-
ReadonlyCfbArchive::Iterator::Iterator(const ReadonlyCfbArchive &parent,
83-
const impl::CompoundFileEntry &entry)
84-
: m_entry{Entry(parent, entry)} {
85-
dig_left_();
86-
}
87-
88-
ReadonlyCfbArchive::Iterator::Iterator(const ReadonlyCfbArchive &parent,
89-
const impl::CompoundFileEntry &entry,
90-
const common::Path &parent_path)
91-
: m_entry{Entry(parent, entry, parent_path)} {
92-
dig_left_();
93-
}
94-
95-
void ReadonlyCfbArchive::Iterator::dig_left_() {
96-
if (!m_entry) {
97-
return;
98-
}
99-
100-
while (true) {
101-
auto left = m_entry->left();
102-
if (!left) {
103-
break;
24+
for (const auto &e : *m_cfb) {
25+
if (e.is_directory()) {
26+
filesystem->create_directory(e.path());
27+
} else if (e.is_file()) {
28+
filesystem->copy(e.file(), e.path());
10429
}
105-
m_ancestors.push_back(*m_entry);
106-
m_entry = left;
107-
}
108-
}
109-
110-
void ReadonlyCfbArchive::Iterator::next_() {
111-
if (!m_entry) {
112-
return;
11330
}
11431

115-
auto child = m_entry->child();
116-
if (child) {
117-
m_directories.push_back(*m_entry);
118-
m_entry = child;
119-
dig_left_();
120-
return;
121-
}
122-
123-
next_flat_();
124-
}
125-
126-
void ReadonlyCfbArchive::Iterator::next_flat_() {
127-
if (!m_entry) {
128-
return;
129-
}
130-
131-
auto right = m_entry->right();
132-
if (right) {
133-
m_entry = right;
134-
dig_left_();
135-
return;
136-
}
137-
138-
if (!m_ancestors.empty()) {
139-
m_entry = m_ancestors.back();
140-
m_ancestors.pop_back();
141-
return;
142-
}
143-
144-
if (!m_directories.empty()) {
145-
m_entry = m_directories.back();
146-
m_directories.pop_back();
147-
next_flat_();
148-
return;
149-
}
150-
151-
m_entry = {};
152-
}
153-
154-
ReadonlyCfbArchive::Iterator::reference
155-
ReadonlyCfbArchive::Iterator::operator*() const {
156-
return *m_entry;
157-
}
158-
159-
ReadonlyCfbArchive::Iterator::pointer
160-
ReadonlyCfbArchive::Iterator::operator->() const {
161-
return &*m_entry;
32+
return filesystem;
16233
}
16334

164-
bool ReadonlyCfbArchive::Iterator::operator==(const Iterator &other) const {
165-
return m_entry == other.m_entry;
166-
}
167-
168-
bool ReadonlyCfbArchive::Iterator::operator!=(const Iterator &other) const {
169-
return m_entry != other.m_entry;
170-
}
171-
172-
ReadonlyCfbArchive::Iterator &ReadonlyCfbArchive::Iterator::operator++() {
173-
next_();
174-
return *this;
175-
}
176-
177-
ReadonlyCfbArchive::Iterator ReadonlyCfbArchive::Iterator::operator++(int) {
178-
Iterator tmp = *this;
179-
++(*this);
180-
return tmp;
181-
}
182-
183-
ReadonlyCfbArchive::ReadonlyCfbArchive(
184-
const std::shared_ptr<common::MemoryFile> &file)
185-
: m_cfb{std::make_shared<util::Archive>(file)} {}
186-
187-
ReadonlyCfbArchive::Iterator ReadonlyCfbArchive::begin() const {
188-
return {*this, *m_cfb->cfb().get_root_entry()};
189-
}
190-
191-
ReadonlyCfbArchive::Iterator ReadonlyCfbArchive::end() const { return {}; }
192-
193-
ReadonlyCfbArchive::Iterator
194-
ReadonlyCfbArchive::find(const common::Path &path) const {
195-
for (auto it = begin(); it != end(); ++it) {
196-
if (it->path() == path) {
197-
return it;
198-
}
199-
}
200-
201-
return end();
202-
}
35+
void CfbArchive::save(std::ostream &out) const { throw UnsupportedOperation(); }
20336

20437
} // namespace odr::internal::cfb

src/odr/internal/cfb/cfb_archive.hpp

Lines changed: 10 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#ifndef ODR_INTERNAL_CFB_ARCHIVE_HPP
22
#define ODR_INTERNAL_CFB_ARCHIVE_HPP
33

4-
#include <odr/internal/cfb/cfb_impl.hpp>
4+
#include <odr/internal/abstract/archive.hpp>
55
#include <odr/internal/common/file.hpp>
66
#include <odr/internal/common/path.hpp>
77

@@ -11,6 +11,11 @@
1111
#include <string>
1212
#include <vector>
1313

14+
namespace odr {
15+
enum class FileType;
16+
struct FileMeta;
17+
} // namespace odr
18+
1419
namespace odr::internal::abstract {
1520
class File;
1621
} // namespace odr::internal::abstract
@@ -19,89 +24,19 @@ namespace odr::internal::cfb::impl {
1924
struct CompoundFileEntry;
2025
} // namespace odr::internal::cfb::impl
2126

22-
namespace odr::internal::common {
23-
class MemoryFile;
24-
} // namespace odr::internal::common
25-
2627
namespace odr::internal::cfb::util {
2728
class Archive;
2829
}
2930

3031
namespace odr::internal::cfb {
3132

32-
class ReadonlyCfbArchive final {
33+
class CfbArchive final : public abstract::Archive {
3334
public:
34-
explicit ReadonlyCfbArchive(const std::shared_ptr<common::MemoryFile> &file);
35-
36-
class Iterator;
37-
38-
[[nodiscard]] Iterator begin() const;
39-
[[nodiscard]] Iterator end() const;
40-
41-
[[nodiscard]] Iterator find(const common::Path &path) const;
42-
43-
class Entry {
44-
public:
45-
Entry(const ReadonlyCfbArchive &parent,
46-
const impl::CompoundFileEntry &entry);
47-
Entry(const ReadonlyCfbArchive &parent,
48-
const impl::CompoundFileEntry &entry,
49-
const common::Path &parent_path);
50-
51-
bool operator==(const Entry &other) const;
52-
bool operator!=(const Entry &other) const;
53-
54-
[[nodiscard]] bool is_file() const;
55-
[[nodiscard]] bool is_directory() const;
56-
[[nodiscard]] common::Path path() const;
57-
[[nodiscard]] std::unique_ptr<abstract::File> file() const;
58-
59-
[[nodiscard]] std::string name() const;
60-
[[nodiscard]] std::optional<Entry> left() const;
61-
[[nodiscard]] std::optional<Entry> right() const;
62-
[[nodiscard]] std::optional<Entry> child() const;
63-
64-
private:
65-
const ReadonlyCfbArchive *m_parent;
66-
const impl::CompoundFileEntry *m_entry;
67-
common::Path m_path;
68-
69-
friend Iterator;
70-
};
71-
72-
class Iterator {
73-
public:
74-
using iterator_category = std::forward_iterator_tag;
75-
using difference_type = std::ptrdiff_t;
76-
using value_type = Entry;
77-
using pointer = const Entry *;
78-
using reference = const Entry &;
79-
80-
Iterator();
81-
Iterator(const ReadonlyCfbArchive &parent,
82-
const impl::CompoundFileEntry &entry);
83-
Iterator(const ReadonlyCfbArchive &parent,
84-
const impl::CompoundFileEntry &entry,
85-
const common::Path &parent_path);
86-
87-
reference operator*() const;
88-
pointer operator->() const;
89-
90-
bool operator==(const Iterator &other) const;
91-
bool operator!=(const Iterator &other) const;
92-
93-
Iterator &operator++();
94-
Iterator operator++(int);
35+
explicit CfbArchive(std::shared_ptr<util::Archive> archive);
9536

96-
private:
97-
std::optional<Entry> m_entry;
98-
std::vector<Entry> m_ancestors;
99-
std::vector<Entry> m_directories;
37+
[[nodiscard]] std::shared_ptr<abstract::Filesystem> filesystem() const final;
10038

101-
void dig_left_();
102-
void next_();
103-
void next_flat_();
104-
};
39+
void save(std::ostream &out) const final;
10540

10641
private:
10742
std::shared_ptr<util::Archive> m_cfb;

src/odr/internal/cfb/cfb_file.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include <odr/internal/cfb/cfb_file.hpp>
2+
3+
#include <odr/internal/cfb/cfb_archive.hpp>
4+
#include <odr/internal/cfb/cfb_util.hpp>
5+
6+
namespace odr::internal::cfb {
7+
8+
CfbFile::CfbFile(const std::shared_ptr<common::MemoryFile> &file)
9+
: m_cfb{std::make_shared<util::Archive>(file)} {}
10+
11+
std::shared_ptr<abstract::File> CfbFile::file() const noexcept {
12+
return m_cfb->file();
13+
}
14+
15+
FileType CfbFile::file_type() const noexcept {
16+
return FileType::compound_file_binary_format;
17+
}
18+
19+
FileMeta CfbFile::file_meta() const noexcept {
20+
FileMeta meta;
21+
meta.type = file_type();
22+
return meta;
23+
}
24+
25+
std::shared_ptr<abstract::Archive> CfbFile::archive() const {
26+
return std::make_shared<CfbArchive>(m_cfb);
27+
}
28+
29+
} // namespace odr::internal::cfb

0 commit comments

Comments
 (0)