MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
FileReader.hpp
Go to the documentation of this file.
1#pragma once
2
4
5namespace MayaFlux::Kakshya {
6
7class SignalSourceContainer;
8struct RegionGroup;
9}
10
11namespace MayaFlux::IO {
12
13/**
14 * @struct FileMetadata
15 * @brief Generic metadata structure for any file type.
16 *
17 * Stores both standard and type-specific metadata for files, including format,
18 * MIME type, size, timestamps, and arbitrary key-value attributes.
19 */
21 std::string format; ///< File format identifier (e.g., "wav", "mp3", "hdf5")
22 std::string mime_type; ///< MIME type if applicable (e.g., "audio/wav")
23 uint64_t file_size = 0; ///< Size in bytes
24 std::chrono::system_clock::time_point creation_time; ///< File creation time
25 std::chrono::system_clock::time_point modification_time; ///< Last modification time
26
27 /// Type-specific metadata stored as key-value pairs (e.g., sample rate, channels)
28 std::unordered_map<std::string, std::any> attributes;
29
30 /**
31 * @brief Get a typed attribute value by key.
32 * @tparam T Expected type.
33 * @param key Attribute key.
34 * @return Optional value if present and convertible.
35 */
36 template <typename T>
37 std::optional<T> get_attribute(const std::string& key) const
38 {
39 auto it = attributes.find(key);
40 if (it != attributes.end()) {
41 try {
42 return safe_any_cast<T>(it->second);
43 } catch (const std::bad_any_cast&) {
44 return std::nullopt;
45 }
46 }
47 return std::nullopt;
48 }
49};
50
51/**
52 * @enum FileReadOptions
53 * @brief Generic options for file reading behavior.
54 *
55 * Bitmask flags to control file reading, metadata extraction, streaming, and more.
56 */
57enum class FileReadOptions : uint32_t {
58 NONE = 0, ///< No special options
59 EXTRACT_METADATA = 1 << 0, ///< Extract file metadata
60 EXTRACT_REGIONS = 1 << 1, ///< Extract semantic regions (format-specific)
61 LAZY_LOAD = 1 << 2, ///< Don't load all data immediately
62 STREAMING = 1 << 3, ///< Enable streaming mode
63 HIGH_PRECISION = 1 << 4, ///< Use highest precision available
64 VERIFY_INTEGRITY = 1 << 5, ///< Verify file integrity/checksums
65 DECOMPRESS = 1 << 6, ///< Decompress if compressed
66 PARSE_STRUCTURE = 1 << 7, ///< Parse internal structure
67 ALL = 0xFFFFFFFF ///< All options enabled
68};
69
71{
72 return static_cast<FileReadOptions>(static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
73}
74
76{
77 return static_cast<FileReadOptions>(static_cast<uint32_t>(a) & static_cast<uint32_t>(b));
78}
79
80/**
81 * @struct FileRegion
82 * @brief Generic region descriptor for any file type.
83 *
84 * Describes a logical region or segment within a file, such as a cue, marker,
85 * chapter, scene, or data block. Used for both audio/video and scientific data.
86 */
87struct MAYAFLUX_API FileRegion {
88 std::string type; ///< Region type identifier (e.g., "cue", "scene", "block")
89 std::string name; ///< Human-readable name for the region
90 std::vector<uint64_t> start_coordinates; ///< N-dimensional start position (e.g., frame, x, y)
91 std::vector<uint64_t> end_coordinates; ///< N-dimensional end position (inclusive)
92 std::unordered_map<std::string, std::any> attributes; ///< Region-specific metadata
93
94 /**
95 * @brief Convert this FileRegion to a Region for use in processing.
96 * @return Region with equivalent coordinates and attributes.
97 */
98 Kakshya::Region to_region() const;
99};
100
101/**
102 * @class FileReader
103 * @brief Abstract interface for reading various file formats into containers.
104 *
105 * FileReader provides a type-agnostic interface for loading file data into
106 * the MayaFlux container system. It supports a wide range of structured data:
107 * - Audio files (WAV, MP3, FLAC, etc.)
108 * - Video files (MP4, AVI, MOV, etc.)
109 * - Image sequences or multi-dimensional image data
110 * - Scientific data formats (HDF5, NetCDF, etc.)
111 * - Custom binary formats
112 * - Text-based structured data (JSON, XML, CSV as regions)
113 *
114 * The interface is designed for flexibility, supporting region extraction,
115 * metadata parsing, streaming, and container creation for any data type.
116 */
117class MAYAFLUX_API FileReader {
118public:
119 virtual ~FileReader() = default;
120
121 /**
122 * @brief Check if a file can be read by this reader.
123 * @param filepath Path to the file.
124 * @return true if the file format is supported.
125 */
126 [[nodiscard]] virtual bool can_read(const std::string& filepath) const = 0;
127
128 /**
129 * @brief Open a file for reading.
130 * @param filepath Path to the file.
131 * @param options Reading options (see FileReadOptions).
132 * @return true if file was successfully opened.
133 */
134 virtual bool open(const std::string& filepath, FileReadOptions options = FileReadOptions::ALL) = 0;
135
136 /**
137 * @brief Close the currently open file.
138 */
139 virtual void close() = 0;
140
141 /**
142 * @brief Check if a file is currently open.
143 * @return true if a file is open.
144 */
145 [[nodiscard]] virtual bool is_open() const = 0;
146
147 /**
148 * @brief Get metadata from the open file.
149 * @return File metadata or nullopt if no file is open.
150 */
151 [[nodiscard]] virtual std::optional<FileMetadata> get_metadata() const = 0;
152
153 /**
154 * @brief Get semantic regions from the file.
155 * @return Vector of regions found in the file.
156 *
157 * Regions are format-specific:
158 * - Audio: cues, markers, loops, chapters
159 * - Video: scenes, chapters, keyframes
160 * - Images: layers, selections, annotations
161 * - Data: chunks, blocks, datasets
162 */
163 [[nodiscard]] virtual std::vector<FileRegion> get_regions() const = 0;
164
165 /**
166 * @brief Read all data from the file into memory.
167 * @return DataVariant vector containing the file data.
168 */
169 virtual std::vector<Kakshya::DataVariant> read_all() = 0;
170
171 /**
172 * @brief Read a specific region of data.
173 * @param region Region descriptor.
174 * @return DataVariant vector containing the requested data.
175 */
176 virtual std::vector<Kakshya::DataVariant> read_region(const FileRegion& region) = 0;
177
178 /**
179 * @brief Create and initialize a container from the file.
180 * @return Initialized container appropriate for the file type.
181 *
182 * The specific container type returned depends on the file format:
183 * - Audio files -> SoundFileContainer
184 * - Video files -> VideoContainer (future)
185 * - Image files -> ImageContainer (future)
186 * - Data files -> DataContainer variants
187 */
188 virtual std::shared_ptr<Kakshya::SignalSourceContainer> create_container() = 0;
189
190 /**
191 * @brief Load file data into an existing container.
192 * @param container Target container (must be compatible type).
193 * @return true if successful.
194 */
195 virtual bool load_into_container(std::shared_ptr<Kakshya::SignalSourceContainer> container) = 0;
196
197 /**
198 * @brief Get current read position in primary dimension.
199 * @return Current position (interpretation is format-specific).
200 */
201 [[nodiscard]] virtual std::vector<uint64_t> get_read_position() const = 0;
202
203 /**
204 * @brief Seek to a specific position in the file.
205 * @param position Target position in N-dimensional space.
206 * @return true if seek was successful.
207 */
208 virtual bool seek(const std::vector<uint64_t>& position) = 0;
209
210 /**
211 * @brief Get supported file extensions for this reader.
212 * @return Vector of supported extensions (without dots).
213 */
214 [[nodiscard]] virtual std::vector<std::string> get_supported_extensions() const = 0;
215
216 /**
217 * @brief Get the data type this reader produces.
218 * @return Type info for the data variant content.
219 */
220 [[nodiscard]] virtual std::type_index get_data_type() const = 0;
221
222 /**
223 * @brief Get the container type this reader creates.
224 * @return Type info for the container type.
225 */
226 [[nodiscard]] virtual std::type_index get_container_type() const = 0;
227
228 /**
229 * @brief Get the last error message.
230 * @return Error string or empty if no error.
231 */
232 [[nodiscard]] virtual std::string get_last_error() const = 0;
233
234 /**
235 * @brief Check if streaming is supported for the current file.
236 * @return true if file can be streamed.
237 */
238 [[nodiscard]] virtual bool supports_streaming() const = 0;
239
240 /**
241 * @brief Get the preferred chunk size for streaming.
242 * @return Chunk size in primary dimension units.
243 */
244 [[nodiscard]] virtual uint64_t get_preferred_chunk_size() const = 0;
245
246 /**
247 * @brief Get the dimensionality of the file data.
248 * @return Number of dimensions.
249 */
250 [[nodiscard]] virtual size_t get_num_dimensions() const = 0;
251
252 /**
253 * @brief Get size of each dimension in the file data.
254 * @return Vector of dimension sizes.
255 */
256 [[nodiscard]] virtual std::vector<uint64_t> get_dimension_sizes() const = 0;
257
258 /**
259 * @brief Resolve a filepath against the project source root if not found as-is.
260 *
261 * Absolute paths are returned unchanged. Relative paths are tried as-is
262 * first, then prefixed with the project root. Returns the original path if
263 * neither resolves, allowing the caller to fail naturally.
264 *
265 * @param filepath Path as supplied by the caller.
266 * @return Resolved path string.
267 */
268 [[nodiscard]] static std::string resolve_path(const std::string& filepath)
269 {
270 namespace fs = std::filesystem;
271 auto normalized = std::string(filepath);
272 std::ranges::replace(normalized, '\\', '/');
273
274 if (fs::path(normalized).is_absolute())
275 return normalized;
276 if (fs::exists(normalized))
277 return normalized;
278 auto from_cwd = fs::current_path() / normalized;
279 if (fs::exists(from_cwd))
280 return from_cwd.string();
281 auto from_root = fs::path(Config::project_root()) / normalized;
282 if (fs::exists(from_root))
283 return from_root.string();
284 return normalized;
285 }
286
287protected:
288 /**
289 * @brief Convert file regions to region groups.
290 * @param regions Vector of file regions.
291 * @return Region groups organized by type.
292 *
293 * Groups regions by their type field, producing a map from type to RegionGroup.
294 */
295 static std::unordered_map<std::string, Kakshya::RegionGroup>
296 regions_to_groups(const std::vector<FileRegion>& regions);
297};
298
299// Type alias for factory function
300using FileReaderFactory = std::function<std::unique_ptr<FileReader>()>;
301
302/**
303 * @class FileReaderRegistry
304 * @brief Registry for file reader implementations.
305 *
306 * Allows registration of different FileReader implementations
307 * and automatic selection based on file extension or content.
308 */
310public:
311 /**
312 * @brief Get the singleton instance of the registry.
313 */
315 {
316 static FileReaderRegistry registry;
317 return registry;
318 }
319
320 /**
321 * @brief Register a file reader factory for one or more extensions.
322 * @param extensions Supported file extensions (without dots).
323 * @param factory Factory function to create reader.
324 */
325 void register_reader(const std::vector<std::string>& extensions, const FileReaderFactory& factory)
326 {
327 for (const auto& ext : extensions) {
328 m_factories[ext] = factory;
329 }
330 }
331
332 /**
333 * @brief Create appropriate reader for a file based on extension.
334 * @param filepath Path to file.
335 * @return Reader instance or nullptr if no suitable reader.
336 */
337 std::unique_ptr<FileReader> create_reader(const std::string& filepath) const
338 {
339 auto resolved = FileReader::resolve_path(filepath);
340
341 auto ext = std::filesystem::path(resolved).extension().string();
342 if (!ext.empty() && ext[0] == '.') {
343 ext = ext.substr(1);
344 }
345
346 auto it = m_factories.find(ext);
347 if (it != m_factories.end()) {
348 return it->second();
349 }
350 return nullptr;
351 }
352
353private:
354 std::unordered_map<std::string, FileReaderFactory> m_factories;
355};
356
357} // namespace MayaFlux::Kakshya
std::optional< glm::vec3 > position
Definition Decoder.cpp:93
size_t a
size_t b
std::unique_ptr< FileReader > create_reader(const std::string &filepath) const
Create appropriate reader for a file based on extension.
static FileReaderRegistry & instance()
Get the singleton instance of the registry.
void register_reader(const std::vector< std::string > &extensions, const FileReaderFactory &factory)
Register a file reader factory for one or more extensions.
std::unordered_map< std::string, FileReaderFactory > m_factories
Registry for file reader implementations.
virtual bool open(const std::string &filepath, FileReadOptions options=FileReadOptions::ALL)=0
Open a file for reading.
virtual std::vector< std::string > get_supported_extensions() const =0
Get supported file extensions for this reader.
static std::string resolve_path(const std::string &filepath)
Resolve a filepath against the project source root if not found as-is.
virtual bool seek(const std::vector< uint64_t > &position)=0
Seek to a specific position in the file.
virtual std::vector< FileRegion > get_regions() const =0
Get semantic regions from the file.
virtual std::type_index get_container_type() const =0
Get the container type this reader creates.
virtual std::vector< uint64_t > get_dimension_sizes() const =0
Get size of each dimension in the file data.
virtual ~FileReader()=default
virtual std::vector< Kakshya::DataVariant > read_all()=0
Read all data from the file into memory.
virtual bool supports_streaming() const =0
Check if streaming is supported for the current file.
virtual size_t get_num_dimensions() const =0
Get the dimensionality of the file data.
virtual uint64_t get_preferred_chunk_size() const =0
Get the preferred chunk size for streaming.
virtual std::vector< Kakshya::DataVariant > read_region(const FileRegion &region)=0
Read a specific region of data.
virtual bool can_read(const std::string &filepath) const =0
Check if a file can be read by this reader.
virtual std::string get_last_error() const =0
Get the last error message.
virtual std::optional< FileMetadata > get_metadata() const =0
Get metadata from the open file.
virtual bool is_open() const =0
Check if a file is currently open.
virtual void close()=0
Close the currently open file.
virtual std::shared_ptr< Kakshya::SignalSourceContainer > create_container()=0
Create and initialize a container from the file.
virtual bool load_into_container(std::shared_ptr< Kakshya::SignalSourceContainer > container)=0
Load file data into an existing container.
virtual std::type_index get_data_type() const =0
Get the data type this reader produces.
virtual std::vector< uint64_t > get_read_position() const =0
Get current read position in primary dimension.
Abstract interface for reading various file formats into containers.
std::function< std::unique_ptr< FileReader >()> FileReaderFactory
AudioReadOptions operator&(AudioReadOptions a, AudioReadOptions b)
FileReadOptions
Generic options for file reading behavior.
@ EXTRACT_METADATA
Extract file metadata.
@ HIGH_PRECISION
Use highest precision available.
@ EXTRACT_REGIONS
Extract semantic regions (format-specific)
@ STREAMING
Enable streaming mode.
@ PARSE_STRUCTURE
Parse internal structure.
@ DECOMPRESS
Decompress if compressed.
@ VERIFY_INTEGRITY
Verify file integrity/checksums.
@ LAZY_LOAD
Don't load all data immediately.
AudioReadOptions operator|(AudioReadOptions a, AudioReadOptions b)
uint64_t file_size
Size in bytes.
std::unordered_map< std::string, std::any > attributes
Type-specific metadata stored as key-value pairs (e.g., sample rate, channels)
std::chrono::system_clock::time_point modification_time
Last modification time.
std::string format
File format identifier (e.g., "wav", "mp3", "hdf5")
std::string mime_type
MIME type if applicable (e.g., "audio/wav")
std::chrono::system_clock::time_point creation_time
File creation time.
std::optional< T > get_attribute(const std::string &key) const
Get a typed attribute value by key.
Generic metadata structure for any file type.
std::vector< uint64_t > start_coordinates
N-dimensional start position (e.g., frame, x, y)
std::string name
Human-readable name for the region.
std::string type
Region type identifier (e.g., "cue", "scene", "block")
std::unordered_map< std::string, std::any > attributes
Region-specific metadata.
std::vector< uint64_t > end_coordinates
N-dimensional end position (inclusive)
Generic region descriptor for any file type.
Represents a point or span in N-dimensional space.
Definition Region.hpp:73