14
14
15
15
#include < string_view>
16
16
#include < algorithm>
17
+ #include < span>
17
18
18
19
namespace nbl ::system
19
20
{
@@ -33,99 +34,134 @@ class NBL_API2 IFileArchive : public core::IReferenceCounted
33
34
EAT_MALLOC // decompress to RAM
34
35
};
35
36
// ! An entry in a list of items, can be a folder or a file.
36
- struct SFileList
37
+ class SFileList
37
38
{
38
- struct SEntry
39
- {
40
- // same stuff as `SListEntry` right now
41
- // ! The name of the file including the path relative to archive root
42
- system::path pathRelativeToArchive;
39
+ public:
40
+ struct SEntry
41
+ {
42
+ // same stuff as `SListEntry` right now
43
+ // ! The name of the file including the path relative to archive root
44
+ system::path pathRelativeToArchive;
43
45
44
- // ! The size of the file in bytes
45
- size_t size;
46
+ // ! The size of the file in bytes
47
+ size_t size;
46
48
47
- // ! FileOffset inside an archive
48
- size_t offset;
49
+ // ! FileOffset inside an archive
50
+ size_t offset;
49
51
50
- // ! The ID of the file in an archive, it maps it to a memory pool entry for CFileView
51
- uint32_t ID;
52
+ // ! The ID of the file in an archive, it maps it to a memory pool entry for CFileView
53
+ uint32_t ID;
52
54
53
- // `EAT_NONE` for directories
54
- IFileArchive::E_ALLOCATOR_TYPE allocatorType;
55
+ // `EAT_NONE` for directories
56
+ IFileArchive::E_ALLOCATOR_TYPE allocatorType;
55
57
56
- // ! The == operator is provided so that CFileList can slowly search the list!
57
- inline bool operator ==(const struct SEntry & other) const
58
- {
59
- return pathRelativeToArchive.string () == other.pathRelativeToArchive .string ();
60
- }
58
+ // ! The == operator is provided so that CFileList can slowly search the list!
59
+ inline bool operator ==(const struct SEntry & other) const
60
+ {
61
+ return pathRelativeToArchive.string () == other.pathRelativeToArchive .string ();
62
+ }
63
+
64
+ // ! The < operator is provided so that CFileList can sort and quickly search the list.
65
+ inline bool operator <(const struct SEntry & other) const
66
+ {
67
+ return pathRelativeToArchive < other.pathRelativeToArchive ;
68
+ }
69
+ };
70
+ using refctd_storage_t = std::shared_ptr<const core::vector<SEntry>>;
61
71
62
- // ! The < operator is provided so that CFileList can sort and quickly search the list.
63
- inline bool operator <(const struct SEntry & other) const
72
+ class found_t final
64
73
{
65
- return pathRelativeToArchive < other.pathRelativeToArchive ;
66
- }
67
- };
68
- using refctd_storage_t = std::shared_ptr<const core::vector<SEntry>>;
69
- using range_t = core::SRange<const SEntry>;
70
-
71
- inline operator range_t () const { return m_range; }
72
-
73
- SFileList (const SFileList&) = default ;
74
- SFileList (SFileList&&) = default ;
75
- SFileList& operator =(const SFileList&) = default ;
76
- SFileList& operator =(SFileList&&) = default ;
77
-
78
- private:
79
- // default ctor full range
80
- SFileList (refctd_storage_t _data) : m_data(_data), m_range({ _data->data (),_data->data () + _data->size () }) {}
81
-
82
- friend class IFileArchive ;
83
- refctd_storage_t m_data;
84
- range_t m_range;
74
+ refctd_storage_t m_backingStorage = nullptr ;
75
+
76
+ public:
77
+ using type = refctd_storage_t ::element_type::const_pointer;
78
+
79
+ found_t () = default ;
80
+ found_t (refctd_storage_t && _storage, type _iter) : m_backingStorage(_storage), m_iter(_iter) {}
81
+
82
+ explicit inline operator bool () const {return m_iter;}
83
+
84
+ inline const SEntry& operator *() const {return *m_iter;}
85
+ inline const SEntry* operator ->() const {return m_iter;}
86
+
87
+ type m_iter = nullptr ;
88
+ };
89
+
90
+ /* deprecated*/ using range_t = std::span<const SEntry>;
91
+ using span_t = std::span<const SEntry>;
92
+ inline operator span_t () const {return m_span;}
93
+
94
+ SFileList (const SFileList&) = default ;
95
+ SFileList (SFileList&&) = default ;
96
+ SFileList& operator =(const SFileList&) = default ;
97
+ SFileList& operator =(SFileList&&) = default ;
98
+
99
+ private:
100
+ // default ctor full range
101
+ SFileList (refctd_storage_t _data) : m_data(_data), m_span(m_data->data (),m_data->data()+m_data->size()) {}
102
+
103
+ friend class IFileArchive ;
104
+ refctd_storage_t m_data;
105
+ span_t m_span;
85
106
};
86
107
87
108
//
88
- virtual inline SFileList listAssets () const {
109
+ virtual inline SFileList listAssets () const
110
+ {
89
111
return { m_items.load () };
90
112
}
91
113
92
114
// List all files and directories in a specific dir of the archive
93
115
SFileList listAssets (path pathRelativeToArchive) const ;
94
116
95
117
//
96
- virtual core::smart_refctd_ptr<IFile> getFile (const path& pathRelativeToArchive, const std::string_view& password) = 0;
118
+ inline core::smart_refctd_ptr<IFile> getFile (const path& pathRelativeToArchive, const core::bitflag<IFileBase::E_CREATE_FLAGS> flags, const std::string_view& password)
119
+ {
120
+ const auto item = getItemFromPath (pathRelativeToArchive);
121
+ if (!item)
122
+ return nullptr ;
123
+
124
+ if (flags.hasFlags (IFileBase::ECF_WRITE))
125
+ {
126
+ m_logger.log (" Cannot open file %s with WRITE flag, we don't support writing to archives yet!" ,ILogger::ELL_ERROR,pathRelativeToArchive.c_str ());
127
+ return nullptr ;
128
+ }
129
+ return getFile_impl (item,flags,password);
130
+ }
97
131
98
132
//
99
133
const path& getDefaultAbsolutePath () const {return m_defaultAbsolutePath;}
100
134
101
135
protected:
102
136
IFileArchive (path&& _defaultAbsolutePath, system::logger_opt_smart_ptr&& logger) :
103
- m_defaultAbsolutePath (std::move(_defaultAbsolutePath.make_preferred())), m_logger(std::move(logger))
104
- {
105
- }
137
+ m_defaultAbsolutePath(std::move(_defaultAbsolutePath.make_preferred())), m_logger(std::move(logger)) {}
138
+
139
+ //
140
+ virtual core::smart_refctd_ptr<IFile> getFile_impl (const SFileList::found_t & found, const core::bitflag<IFileBase::E_CREATE_FLAGS> flags, const std::string_view& password) = 0;
106
141
107
- inline const SFileList::SEntry* getItemFromPath (const system::path& pathRelativeToArchive) const
142
+ inline const SFileList::found_t getItemFromPath (const system::path& pathRelativeToArchive) const
108
143
{
109
- const SFileList::SEntry itemToFind = { pathRelativeToArchive };
110
- auto items = m_items.load ();
111
- const auto found = std::lower_bound (items->begin (), items->end (),itemToFind);
112
- if (found==items->end () || found->pathRelativeToArchive != pathRelativeToArchive)
113
- return nullptr ;
114
- return &(*found);
144
+ const SFileList::SEntry itemToFind = { pathRelativeToArchive };
145
+ // calling `listAssets` makes sure any "update list" overload can kick in
146
+ auto items = listAssets ();
147
+ const auto span = SFileList::span_t (items);
148
+ const auto found = std::lower_bound (span.begin (),span.end (),itemToFind);
149
+ if (found==span.end () || found->pathRelativeToArchive !=pathRelativeToArchive)
150
+ return {};
151
+ return SFileList::found_t (std::move (items.m_data ),&(*found));
115
152
}
116
153
117
154
const path m_defaultAbsolutePath;
118
- // files and directories
119
- //
120
155
system::logger_opt_smart_ptr m_logger;
121
156
122
- inline void setItemList (std::shared_ptr<core::vector<SFileList::SEntry>> _items) const {
123
-
124
- std::sort (_items->begin (), _items->end ());
157
+ inline void setItemList (std::shared_ptr<core::vector<SFileList::SEntry>> _items) const
158
+ {
159
+ std::sort (_items->begin (),_items->end ());
125
160
m_items.store (_items);
126
161
}
127
162
128
163
private:
164
+ // files and directories
129
165
mutable std::atomic<SFileList::refctd_storage_t > m_items;
130
166
};
131
167
0 commit comments