/*---------------------------------------------------------------------------*
* IT++ *
*---------------------------------------------------------------------------*
* Copyright (c) 1995-2004 by Tony Ottosson, Thomas Eriksson, Pål Frenger, *
* Tobias Ringström, and Jonas Samuelsson. *
* *
* Permission to use, copy, modify, and distribute this software and its *
* documentation under the terms of the GNU General Public License is hereby *
* granted. No representations are made about the suitability of this *
* software for any purpose. It is provided "as is" without expressed or *
* implied warranty. See the GNU General Public License for more details. *
*---------------------------------------------------------------------------*/
/*!
\file
\brief Definition of classes for the IT++ file format
\author Tobias Ringström and Tony Ottosson
1.18
2004/02/17 12:25:13
*/
#ifndef __itfile_h
#define __itfile_h
#include "base/binary.h"
#include "base/mat.h"
#include "base/vec.h"
#include "base/array.h"
#include "base/binfile.h"
#include "base/machdep.h"
#include <fstream>
namespace itpp {
/*!
\defgroup itfile IT++ File Format
\brief The IT++ file format
\author Tobias Ringstrom and Tony Ottosson
The IT++ file format is a file format that can be used to save variables to
files. These files can also be read an written by Matlab using the m-files
\c load_it.m and \c save_it.m.
The class it_ifile is used for reading only, and the class it_file
can be used for both reading and writing.
The variables must be given a name when they are saved. The saving is done in
two steps. The first step is to supply a name of the variable to be saved.
This can be done either by calling the function it_file::seek() or by
using the helper class Name as follows:
\code
vec v("1 2 3");
it_file f("file.it");
f << Name("v") << v;
\endcode
The reading is done in a similar way:
\code
vec v;
it_ifile f("file.it");
f >> Name("v") >> v;
\endcode
\warning Do no use names that begin with an existing type.
*/
/*!
\brief Base class for it_ifile and it_file.
\ingroup itfile
*/
class it_file_base {
public:
//! Error exception. Thrown by it_ifile and it_file.
class Error {
public:
//! Construct an error.
Error(const std::string &m) : msg(m) { }
//! String describing the error.
std::string msg;
};
//! Data header structure
struct data_header {
//! 0=little, 1=big
char endianity;
//! ACTION: Add documentation
it_u32 hdr_bytes, data_bytes, block_bytes;
//! type=="" means deleted
std::string name, type;
};
protected:
//! File header structure
struct file_header {
//! ACTION: Add documentation
char magic[4];
//! ACTION: Add documentation
char version;
};
//! ACTION: Add documentation
static char file_magic[4];
//! ACTION: Add documentation
static char file_version;
};
/*!
\brief The IT++ file format reading class.
\ingroup itfile
Errors are handled by exceptions.
*/
class it_ifile : public it_file_base {
public:
//!Constructor.
it_ifile();
//!Constructor. Calls open().
explicit it_ifile(const std::string &name);
//!Destructor.
virtual ~it_ifile() { }
//!Open a file. The file must exist.
virtual void open(const std::string &name);
//!Close a file.
virtual void close();
//!Returns pointer to the underlying \c bfstream used
bfstream &low_level() { return s; }
//!Reads and checks the file data header. Returns true if the header is valid and false otherwise.
bool read_check_file_header();
//!Read the data header and return the result in the variable \c h
void read_data_header(data_header &h);
//!Read a binary value at the current file pointer position
void low_level_read(bin &x);
//!Read a short value at the current file pointer position
void low_level_read(short &x);
//!Read an integer value at the current file pointer position
void low_level_read(int &x);
//Read a long long value at the current file pointer position
//void low_level_read(long_long &x);
//!Read a float value at the current file pointer position
void low_level_read(float &x);
//!Read a double value at the current file pointer position
void low_level_read(double &x);
//!Read a float complex value at the current file pointer position
void low_level_read(complex<float> &x);
//!Read a double complex value at the current file pointer position
void low_level_read(complex<double> &x);
//!Read a vector of float values at the current file pointer position
void low_level_read_lo(vec &v);
//!Read a vector of double values at the current file pointer position
void low_level_read_hi(vec &v);
//Read a vector of long long values at the current file pointer position
//void low_level_read(llvec &v);
//!Read a vector of integer values at the current file pointer position
void low_level_read(ivec &v);
//!Read a vector of binary values at the current file pointer position
void low_level_read(bvec &v);
//!Read a vector of float complex values at the current file pointer position
void low_level_read_lo(cvec &v);
//!Read a vector of double complex values at the current file pointer position
void low_level_read_hi(cvec &v);
//!Read a string at the current file pointer position
void low_level_read(std::string &str);
//!Read a matrix of float values at the current file pointer position
void low_level_read_lo(mat &m);
//!Read a matrix of double values at the current file pointer position
void low_level_read_hi(mat &m);
//Read a matrix of long long values at the current file pointer position
//void low_level_read(llmat &m);
//!Read a matrix of integer values at the current file pointer position
void low_level_read(imat &m);
//!Read a matrix of binary values at the current file pointer position
void low_level_read(bmat &m);
//!Read a matrix of float complex values at the current file pointer position
void low_level_read_lo(cmat &m);
//!Read a matrix of double complex values at the current file pointer position
void low_level_read_hi(cmat &m);
//!Read an Array of float values at the current file pointer position
void low_level_read_lo(Array<float> &v);
//!Read an Array of float values at the current file pointer position
void low_level_read_lo(Array<double> &v);
//!Read an Array of double values at the current file pointer position
void low_level_read_hi(Array<double> &v);
//Read an Array of long long values at the current file pointer position
//void low_level_read(Array<long_long> &v);
//!Read an Array of integer values at the current file pointer position
void low_level_read(Array<int> &v);
//!Read an Array of binary values at the current file pointer position
void low_level_read(Array<bin> &v);
//!Read an Array of float complex values at the current file pointer position
void low_level_read_lo(Array<complex<float> > &v);
//!Read an Array of float complex values at the current file pointer position
void low_level_read_lo(Array<complex<double> > &v);
//!Read an Array of double complex values at the current file pointer position
void low_level_read_hi(Array<complex<double> > &v);
//! Find the variable \c name.
void seek(const std::string &name);
//! Find the variable number \c n.
bool seek(int n);
//! Get information about the current variable.
void info(std::string &name, std::string &type, int &bytes);
protected:
//! Protected binary file stream
bfstream s;
};
/*!
\brief The IT++ file format reading and writing class.
\ingroup itfile
Errors are handled by exceptions.
*/
class it_file : public it_ifile {
public:
//! ACTION: Add documentation for this typedef
typedef it_file& (*it_manip)(it_file&);
//! Constructor.
it_file();
/*!
\brief Constructor.
If the file does not exist it will be created. If \c trunc is true,
the file will be truncated.
*/
explicit it_file(const std::string &name, bool trunc=false);
//! Destructor.
virtual ~it_file() { }
/*!
\brief Open a file for reading and writing.
If the file does not exist it will be created. If \c trunc is true,
the file will be truncated.
*/
void open(const std::string &name, bool trunc=false);
//! Close the file.
void close();
//! Flush the data to disk.
void flush();
//! Returns pointer to the underlying \c bfstream used
bfstream &low_level() { return s; }
//! Set the precision. Low precision means floats, high means doubles.
void set_low_precision(bool p=true) { low_prec = p; }
//! Get the precision.
bool get_low_precision() { return low_prec; }
//! Set the name of the next name to be saved. See also the \c Name class.
void set_next_name(const std::string &n) { next_name=n; }
//!Write the header for the \c it_file
void write_file_header();
//!Write the data header for a variable, specifying the type and size of the data to follow.
void write_data_header(const std::string &type, it_u32 size);
//!Write the data header for a variable, specifying the type, name, and size of the data to follow.
void write_data_header(const std::string &type, const std::string &name, it_u32 size);
//!Write a binary value at the current file pointer position
void low_level_write(bin x);
//!Write a short value at the current file pointer position
void low_level_write(short x);
//!Write an integer value at the current file pointer position
void low_level_write(int x);
//Write a long long value at the current file pointer position
//void low_level_write(long_long x);
//!Write a float value at the current file pointer position
void low_level_write(float x);
//!Write a double value at the current file pointer position
void low_level_write(double x);
//!Write a float complex value at the current file pointer position
void low_level_write(const complex<float> &x);
//!Write a double complex value at the current file pointer position
void low_level_write(const complex<double> &x);
//!Write a vec at the current file pointer position
void low_level_write(const vec &v);
//!Write an ivec at the current file pointer position
void low_level_write(const ivec &v);
//!Write a bvec at the current file pointer position
void low_level_write(const bvec &v);
//Write a llvec at the current file pointer position
//void low_level_write(const llvec &v);
//!Write a cvec at the current file pointer position
void low_level_write(const cvec &v);
//!Write a string at the current file pointer position
void low_level_write(const std::string &str);
//!Write a mat at the current file pointer position
void low_level_write(const mat &m);
//!Write a imat at the current file pointer position
void low_level_write(const imat &m);
//!Write a bmat at the current file pointer position
void low_level_write(const bmat &m);
//Write a llmat at the current file pointer position
//void low_level_write(const llmat &m);
//!Write a cmat at the current file pointer position
void low_level_write(const cmat &m);
//!Write a float Array at the current file pointer position
void low_level_write(const Array<float> &v);
//!Write a double Array at the current file pointer position
void low_level_write(const Array<double> &v);
//!Write a integer Array at the current file pointer position
void low_level_write(const Array<int> &v);
//!Write a bin Array at the current file pointer position
void low_level_write(const Array<bin> &v);
//Write a long long Array at the current file pointer position
//void low_level_write(const Array<long_long> &v);
//!Write a float complex Array at the current file pointer position
void low_level_write(const Array<complex<float> > &v);
//!Write a double complex Array at the current file pointer position
void low_level_write(const Array<complex<double> > &v);
//!ACTTION: ADD DOCUMENTATION FOR THIS MEMBER !!!!!!!!
it_file& operator<<(it_manip func) { return (*func)(*this); }
//! Removes the variable \c name from the file.
void remove(const std::string &name);
//! Returns true if the variable \c name exists in the file.
bool exists(const std::string &name);
//! Remove slack space from the file.
void pack();
protected:
//! ACTION: Add documenation for this protected member
void remove();
//! ACTION: Add documenation for this protected member
void write_data_header_here(const data_header &h);
//! ACTION: Add documenation for this protected member
bool low_prec;
//! ACTION: Add documenation for this protected member
std::string next_name;
};
/*!
\brief Flush operator.
\ingroup itfile
Flushes the data. Usage:
\code
vec v1("1 2 3"), v2;
it_file f("file.it");
f << Name("v") << v1 << flush;
\endcode
*/
inline it_file& flush(it_file& f)
{
f.flush();
return f;
}
/*!
\brief Automatic naming when saving.
\ingroup itfile
An easy way to give a variable a name when saving. Usage:
\code
vec v1("1 2 3"), v2;
it_file f("file.it");
f << Name("v") << v1;
f >> Name("v") >> v2;
\endcode
*/
class Name {
public:
//! Constructor
Name(const std::string &n) : name(n) { }
//! The name string
const std::string &name;
};
/*! \addtogroup itfile */
//!@{
//!Finds the variable \c Name in the \c it_ifile. Returns file pointer for reading.
inline it_ifile &operator>>(it_ifile &f, const Name &s)
{
f.seek(s.name);
return f;
}
//!Finds the variable \c Name in the \c it_file. Returns file pointer for writing.
inline it_file &operator<<(it_file &f, const Name &s)
{
f.set_next_name(s.name);
return f;
}
//!Read the binary variable \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, bin &v);
//!Read the short variable \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, short &v);
//!Read the integer variable \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, int &v);
//!Read the float variable \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, float &v);
//!Read the double variable \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, double &v);
//!Read the float complex variable \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, complex<float> &v);
//!Read the double complex variable \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, complex<double> &v);
//!Read the vec \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, vec &v);
//!Read the ivec \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, ivec &v);
//!Read the bvec \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, bvec &v);
//!Read the cvec \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, cvec &v);
//!Read the string \c str from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, std::string &str);
//!Read the mat \c m from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, mat &m);
//!Read the imat \c m from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, imat &m);
//!Read the bmat \c m from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, bmat &m);
//!Read the cmat \c m from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, cmat &m);
//!Read the float Array \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, Array<float> &v);
//!Read the double Array \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, Array<double> &v);
//!Read the integer Array \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, Array<int> &v);
//!Read the binary Array \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, Array<bin> &v);
//!Read the float complex Array \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, Array<complex<float> > &v);
//!Read the double complex Array \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, Array<complex<double> > &v);
//!Read the vec Array \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, Array<vec> &v);
//!Read the ivec Array \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, Array<ivec> &v);
//!Read the bvec Array \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, Array<bvec> &v);
//!Read the cvec Array \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, Array<cvec> &v);
//!Read the string Array \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, Array<std::string> &v);
//!Read the mat Array \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, Array<mat> &v);
//!Read the imat Array \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, Array<imat> &v);
//!Read the bmat Array \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, Array<bmat> &v);
//!Read the cmat Array \c v from the \c it_ifile pointer
it_ifile &operator>>(it_ifile &f, Array<cmat> &v);
//!Write the binary variable \c x to the \c it_file pointer
it_file &operator<<(it_file &f, bin x);
//!Write the short variable \c x to the \c it_file pointer
it_file &operator<<(it_file &f, short x);
//!Write the integer variable \c x to the \c it_file pointer
it_file &operator<<(it_file &f, int x);
//!Write the float variable \c x to the \c it_file pointer
it_file &operator<<(it_file &f, float x);
//!Write the double variable \c x to the \c it_file pointer
it_file &operator<<(it_file &f, double x);
//!Write the float complex variable \c x to the \c it_file pointer
it_file &operator<<(it_file &f, complex<float> x);
//!Write the double complex variable \c x to the \c it_file pointer
it_file &operator<<(it_file &f, complex<double> x);
//!Write the vec \c v to the \c it_file pointer
it_file &operator<<(it_file &f, const vec &v);
//!Write the ivec \c v to the \c it_file pointer
it_file &operator<<(it_file &f, const ivec &v);
//!Write the bvec \c v to the \c it_file pointer
it_file &operator<<(it_file &f, const bvec &v);
//!Write the cvec \c v to the \c it_file pointer
it_file &operator<<(it_file &f, const cvec &v);
//!Write the string \c str to the \c it_file pointer
it_file &operator<<(it_file &f, const std::string &str);
//!Write the mat \c m to the \c it_file pointer
it_file &operator<<(it_file &f, const mat &m);
//!Write the imat \c m to the \c it_file pointer
it_file &operator<<(it_file &f, const imat &m);
//!Write the bmat \c m to the \c it_file pointer
it_file &operator<<(it_file &f, const bmat &m);
//!Write the cmat \c m to the \c it_file pointer
it_file &operator<<(it_file &f, const cmat &m);
//!Write the float Array \c v to the \c it_file pointer
it_file &operator<<(it_file &f, const Array<float> &v);
//!Write the double Array \c v to the \c it_file pointer
it_file &operator<<(it_file &f, const Array<double> &v);
//!Write the int Array \c v to the \c it_file pointer
it_file &operator<<(it_file &f, const Array<int> &v);
//!Write the bin Array \c v to the \c it_file pointer
it_file &operator<<(it_file &f, const Array<bin> &v);
//!Write the float complex Array \c v to the \c it_file pointer
it_file &operator<<(it_file &f, const Array<complex<float> > &v);
//!Write the double complex Array \c v to the \c it_file pointer
it_file &operator<<(it_file &f, const Array<complex<double> > &v);
//!Write the vec Array \c v to the \c it_file pointer
it_file &operator<<(it_file &f, const Array<vec> &v);
//!Write the ivec Array \c v to the \c it_file pointer
it_file &operator<<(it_file &f, const Array<ivec> &v);
//!Write the bvec Array \c v to the \c it_file pointer
it_file &operator<<(it_file &f, const Array<bvec> &v);
//!Write the cvec Array \c v to the \c it_file pointer
it_file &operator<<(it_file &f, const Array<cvec> &v);
//!Write the string Array \c v to the \c it_file pointer
it_file &operator<<(it_file &f, const Array<std::string> &v);
//!Write the mat Array \c v to the \c it_file pointer
it_file &operator<<(it_file &f, const Array<mat> &v);
//!Write the imat Array \c v to the \c it_file pointer
it_file &operator<<(it_file &f, const Array<imat> &v);
//!Write the bmat Array \c v to the \c it_file pointer
it_file &operator<<(it_file &f, const Array<bmat> &v);
//!Write the cmat Array \c v to the \c it_file pointer
it_file &operator<<(it_file &f, const Array<cmat> &v);
//! Save the variable v in the file name.it as the name name.
template <class T>
void it_save_var_as(const T &v, const std::string &name)
{
it_file f(name + ".it");
f << Name(name) << v;
f.close();
}
//! Load the variable v from the file name.it as the name name.
template <class T>
void it_load_var_as(T &v, const std::string &name)
{
it_ifile f(name + ".it");
f.seek(name);
f >> v;
f.close();
}
//! A convenient macro. Calling it_save_var(M) saves M as 'M' in the file 'M.it'.
#define it_save_var(v) it_save_var_as(v,#v)
//! A convenient macro. Calling it_load_var(M) loads M as 'M' in the file 'M.it'.
#define it_load_var(v) it_load_var_as(v,#v)
//!@}
} //namespace itpp
#endif // __itfile_h
syntax highlighted by Code2HTML, v. 0.9.1