#ifndef MATLAB_IO_HPP_ #define MATLAB_IO_HPP_ #include <sstream> #include <fstream> #include <zlib.h> #include <opencv2/core.hpp> #include <opencv2/core/persistence.hpp> #include "primitives.hpp" #include "bridge.hpp" #include "mxarray.hpp" #include "map.hpp" namespace Matlab { namespace IO { class RandomAccessRead {}; class SequentialWrite {}; static const int Version5 = 5; static const int Version73 = 73; } // predeclarations class IONode; class IONodeIterator; class MatlabIO; // ---------------------------------------------------------------------------- // FILE AS A DATA STRUCTURE // ---------------------------------------------------------------------------- class IONode { protected: //! the name of the field (if associative container) std::string name_; //! the size of the field std::vector<size_t> size_; //! beginning of the data field in the file size_t begin_; //! address after the last data field size_t end_; //! Matlab stored-type int stored_type_; //! Matlab actual type (sometimes compression is used) int type_; //! is the field compressed? bool compressed_; //! are the descendents associative (mappings) bool associative_; //! is this a leaf node containing data, or an interior node bool leaf_; //! the data stream from which the file was indexed cv::Ptr<std::istream> stream_; //! valid if the container is a sequence (list) std::vector<IONode> sequence_; //! valid if the container is a mapping (associative) Map<std::string, IONode> mapping_; IONode(const std::string& name, const std::Vector<size_t>& size, size_t begin, size_t end, int stored_type, int type, bool compressed, bool associative, bool leaf, istream& stream) : name_(name), size_(size), begin_(begin), end_(end), stored_type_(stored_type), type_(type), compressed_(compressed), associative_(associative), leaf_(leaf), stream_(stream) {} public: std::string name() const { return name_; } std::vector<size_t> size() const { return size_; } size_t begin() const { return begin_; } size_t end() const { return end_; } int stored_type() const { return stored_type_; } int type() const { return type_; } bool compressed() const { return compressed_; } bool associative() const { return associative_; } bool leaf() const { return leaf_; } IONode() : begin_(0), end_(0), stored_type_(0), type_(0), leaf_(true) {} #if __cplusplus >= 201103L // conversion operators template <typename T> void operator=(const T& obj) { static_assert(0, "Unimplemented specialization for given type"); } template <typename T> operator T() { static_assert(0, "Unimplemented specialization for given type"); } #else // conversion operators template <typename T> void operator=(const T& obj) { T::unimplemented_specialization; } template <typename T> operator T() { T::unimplemented_specialization; } #endif void swap(const IONode& other) { using std::swap; swap(name_, other.name_); swap(size_, other.size_); swap(begin_, other.begin_); swap(end_, other.end_); swap(stored_type_, other.stored_type_); swap(type_, other.type_); swap(compressed_, other.compressed_); swap(associative_, other.associative_); swap(leaf_, other.leaf_); swap(stream_, other.stream_); swap(sequence_, other.sequence_); swap(mapping_, other.mapping_); } }; class SequenceIONode : public IONode { public: std::vector<IONode>& sequence() { return sequence_; } SequenceIONode(const std::string& name, const std::Vector<size_t>& size, size_t begin, size_t end, int stored_type, int type, const std::istream& stream) : IONode(name, size, begin, end, stored_type, type, false, false, false, stream) {} }; class MappingIONode : public IONode { public: Map<std::string, IONode>& mapping() { return mapping_; } MappingIONode(const std::string& name, const std::Vector<size_t>& size, size_t begin, size_t end, int stored_type, int type, const std::istream& stream) : IONode(name, size, begin, end, stored_type, type, false, true, false, stream) {} }; class LeafIONode : public IONode { LeafIONode(const std::string& name, const std::Vector<size_t>& size, size_t begin, size_t end, int stored_type, int type, const std::istream& stream) : IONode(name, size, begin, end, stored_type, type, false, false, true, stream) {} }; class CompressedIONode : public IONode { private: std::istringstream uncompressed_stream_; std::vector<char> data_; public: CompressedIONode(const std::string& name, const std::Vector<size_t>& size, size_t begin, size_t end, int stored_type, int type, const std::stream& stream) : IONode(name, size, begin, end, stored_type, type, true, false, false, stream) {} }; class Header : public IONode { Header(const std::string& name, const std::Vector<size_t>& size, size_t begin, size_t end, int stored_type, int type, const std::stream& stream) : IONode(name, size, begin, end, stored_type, type, true, false, false, stream) {} // ---------------------------------------------------------------------------- // FILE NODE // ---------------------------------------------------------------------------- class IONodeIterator : public std::iterator<std::random_access_iterator_tag, MatlabIONode> { }; // ---------------------------------------------------------------------------- // MATLABIO // ---------------------------------------------------------------------------- class MatlabIO { private: // member variables static const int HEADER_LENGTH = 116; static const int SUBSYS_LENGTH = 8; static const int ENDIAN_LENGTH = 2; std::string header_; std::string subsys_; std::string endian_; int version_; bool byte_swap_; std::string filename_; // uses a custom stream buffer for fast memory-mapped access and endian swapping std::fstream stream_; std::ifstream::pos_type stream_pos_; //! the main file index. The top-level index must be associative IONode index_; // internal methods void getFileHeader(); void setFileHeader(); void getHeader(); void setHeader(); CompressedIONode uncompress(const IONode& node); public: // construct/destruct MatlabIO() : header_(HEADER_LENGTH+1, '\0'), subsys_(SUBSYS_LENGTH+1, '\0'), endian_(ENDIAN_LENGTH+1, '\0'), byte_swap(false), stream_pos_(0) {} ~MatlabIO {} // global read and write routines std::string filename(void); bool open(const std::string& filename, std::ios_base::openmode mode); bool isOpen() const; void close(); void clear(); // index the contents of the file void index(); // print all of the top-level variables in the file void printRootIndex() const; void printFullIndex() const; // FileNode operations IONode root() const; IONode operator[](const String& nodename) const; }; #endif