opencv/modules/matlab/io/MatlabIO.hpp

205 lines
6.7 KiB
C++

#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