/*********************************************************************
 * This file is part of the cpplibs suite.
 *
 * Copyright (C) 2001 Topi Mäenpää and Jaakko Viertola
 * All rights reserved.
 *
 * This program is free software. You can redistribute and/or modify
 * it under the terms of the free software licence found in the
 * accompanying file "COPYING". The licence terms must always be
 * redistributed with this source file. The above copyright notice
 * must be reproduced in all modified and unmodified copies of this
 * source file.
 *
 * $Revision: 1.6 $
 *********************************************************************/

#ifndef _MATRIXCODEC_H
#define _MATRIXCODEC_H

#include <fstream>
#include <string>

#include "Matrix.h"

namespace util
{
	/**
	 * MatrixCodec is an interface for classes that are able to read and
	 * write matrix/image data in various formats. 
	 **/
	template <class T> class MatrixCodec : virtual public Object
	{
	public:
		virtual ~MatrixCodec() {}
		/**
		 * Read a matrix from a file. Opens an input stream, reads
		 * the data from the file, and returns them as a matrix.
		 *
		 * @param file The name of the file where the data will be read.
		 * @return Matrix<T> where the data will be placed.
		 * @exception MatrixException& if there is a problem handling the matrix.
		 * @exception IOException& if the data cannot be read for some reason.
		 **/
		virtual Matrix<T> readFromFile(std::string file) throw (MatrixException&, io::IOException&);
		/**
		 * Write a matrix to a file.
		 *
		 * @param file The name of the file where the matrix will be writen.
		 * @param mat The matrix which will be writen.
		 * @exception MatrixException& if there is a problem handling the matrix.
		 * @exception IOException& if the data cannot be write for some reason.
		 **/
		virtual void writeToFile(std::string file, const Matrix<T>& mat) throw (MatrixException&, io::IOException&);
		
		/**
		 * Decode an matrix. Matrix data is read from <i>in</i> and placed
		 * into <i>mat</i>. Matrix dimensions must be read from the stream.
		 *
		 * @param in the input stream to read an matrix from.
		 * @param mat the matrix where output is placed.
		 * @exception MatrixException& if there is a problem handling the matrix.
		 * @exception IOException& if the data cannot be read for some reason.
		 **/
		virtual void decodeMatrix(std::istream& in, Matrix<T>& mat) throw (MatrixException&, io::IOException&) = 0;
		/**
		 * Encode an matrix. Matrix data is extracted from <i>mat</i> and
		 * written into <i>out</i> in some matrix file format.
		 *
		 * @param out the output stream to write an matrix to.
		 * @param mat the matrix to get data from.
		 * @exception MatrixException& if there is a problem handling the matrix.
		 * @exception IOException& if the data cannot be write for some reason.
		 **/
		virtual void encodeMatrix(std::ostream& out, const Matrix<T>& mat) throw (MatrixException&, io::IOException&) = 0;
	};

	
	template <class T> Matrix<T> MatrixCodec<T>::readFromFile(std::string file)
		throw (MatrixException&, io::IOException&)
	{
		std::ifstream in(file.c_str());
		if(!in)
			throw io::IOException("MatrixCodec<T>::readFromFile(string, Matrix<T>&): Cannot open file "+file);

		Matrix<T> mat;
		//then read the matrix
		decodeMatrix(in,mat);
		in.close();

		return mat;
	}

	template <class T> void MatrixCodec<T>::writeToFile(std::string file, const Matrix<T>& mat)
		throw (MatrixException&, io::IOException&)
	{
		std::ofstream out(file.c_str());
		if(!out)
			throw io::IOException("MatrixCodec<T>::writeToFile(string, Matrix<T>&): Cannot open file "+file);

		//then write the matrix
		encodeMatrix(out,mat);
		out.close();
	}
}
#endif
