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