Pusher.hh 5.24 KB
/*
 * Pusher.h
 *
 *  Created on: Dec 10, 2012
 *      Author: f.casimir
 */

#ifndef PUSHER_H_
#define PUSHER_H_

#include <vector>
#include "ParamData.hh"


#include "DD.hh"

namespace AMDA {
namespace Parameters {

namespace Base {
	/**
	 * @class Pusher
	 * @details This class is the operation responsible to transform raw data from DDServer into a ParamData
	 * of the corresponding type ( scalar or vector or Tab2D of short or int or float or double or ... type).
	 */
	struct Pusher {
		Pusher (int dim1=1,int dim2=1) : _dim1(dim1), _dim2(dim2), _paramData(NULL), _fillValue(NAN) {}
		virtual ~Pusher() {}
		virtual void put(DD_data_t *data) = 0;
		void setFillValue(double pFillValue) {
			_fillValue = pFillValue;
		}
		double getFillValue() {
			return _fillValue;
		}
		int _dim1; /*!< Used for vector and Tab2D */
		int _dim2; /*!< Used for Tab2D */
		ParamData* _paramData; /*!< return ParamData to a Process*/
	protected:
		float _fillValue; /*!< When this value is different of NAN, into the raw data, it is replaced by NAN into ParamData. */
	};
}

//#define DD_SHORT 4
//#define DD_INT     1
//#define DD_FLOAT   2
//#define DD_DOUBLE 3
//#define DD_CHAR   0

typedef enum {
	CT_UNKNOWN,
	CT_SCALAR,
	CT_TAB1D,
	CT_TAB2D
} ContainerType;

template <int type>
struct MapType { typedef void Type; };

template <> struct MapType<4> {	typedef short Type; };
template <> struct MapType<1> {	typedef int Type; };
template <> struct MapType<2> {	typedef float Type; };
template <> struct MapType<3> {	typedef double Type;  };
template <> struct MapType<0> {	typedef char Type; };



template<int type,ContainerType container = CT_SCALAR>
class Pusher;

/**
 * @brief Pusher implementation for the CT_TAB2D.
 */
template<int type>
class Pusher<type,CT_TAB2D> : public Base::Pusher {
public:
	typedef typename MapType<type>::Type BaseElemenType;
	typedef Tab2DData<BaseElemenType> ElemenType;
	typedef ParamDataSpec<ElemenType> SpecParamData;

	SpecParamData* _specParamData;

	Pusher(int dim1, int dim2) : Base::Pusher(dim1,dim2) {
		_paramData = _specParamData = createParamData();
	}

	void put(DD_data_t *data) {
		BaseElemenType **lData = reinterpret_cast<BaseElemenType **>(data->Variables);

		//ParamData is created, add data
		_specParamData->getDataList().resize(data->VarNumber);

		for (int index = 0; index < data->VarNumber; index++) {
			ElemenType elem = ElemenType(data->Dimensions[0],data->Dimensions[1]);
			for (int dim1Index= 0; dim1Index < data->Dimensions[0]; ++dim1Index)
			{
				for (int dim2Index= 0; dim2Index < data->Dimensions[1]; ++dim2Index)
				{
					BaseElemenType baseElem = lData[index][dim1Index*data->Dimensions[1]+dim2Index];
					if (!isnan(_fillValue))
					{
						if(baseElem == _fillValue)
							baseElem = (BaseElemenType)NAN;
					}
					elem[dim1Index][dim2Index] = baseElem;
				}
			}
			_specParamData->getDataList().push_back(elem);
		}
	}

	SpecParamData* createParamData() {
		return new ParamDataSpec< Tab2DData<typename MapType<type>::Type> >(_dim1,_dim2);
	}

};

/**
 * @brief Pusher implementation for the CT_TAB1D.
 */
template<int type>
class Pusher<type,CT_TAB1D> : public Base::Pusher {
public:
	typedef typename MapType<type>::Type BaseElemenType;
	typedef std::vector<BaseElemenType> ElemenType;
	typedef ParamDataSpec<ElemenType> SpecParamData;

	SpecParamData* _specParamData;

	Pusher(int dim) : Base::Pusher(dim) {
		_paramData = _specParamData = createParamData();
	}

	void put(DD_data_t *data) {
		BaseElemenType **lData = reinterpret_cast<BaseElemenType **>(data->Variables);

		//ParamData is created, add data
		_specParamData->getDataList().resize(data->VarNumber);

		for (int index = 0; index < data->VarNumber; index++) {
			ElemenType elem = ElemenType(lData[index],lData[index]+_dim1);
			if(!isnan(_fillValue)) {
				for(auto it = elem.begin(); it != elem.end(); ++it) {
					if(*it == _fillValue) {
						*it = (BaseElemenType)NAN;
					}
				}
			}
			_specParamData->getDataList().push_back(elem);
		}
	}

	SpecParamData* createParamData() {
		return new ParamDataSpec< std::vector<typename MapType<type>::Type> >(_dim1);
	}

};


/**
 * @brief Pusher implementation for the scalar.
 */
template<int type>
class Pusher<type,CT_SCALAR> : public Base::Pusher {
public:
	typedef typename MapType<type>::Type BaseElemenType;
	typedef BaseElemenType ElemenType;
	typedef ParamDataSpec<ElemenType> SpecParamData;

	SpecParamData* _specParamData;

	/**
	 * @brief Constructor
	 * @details Create the real ParamData.
	 */
	Pusher() : Base::Pusher() {
		_paramData = _specParamData = createParamData();
	}

	void put(DD_data_t *data) {
		BaseElemenType **lData = reinterpret_cast<BaseElemenType **>(data->Variables);

		//ParamData is created, add data
		_specParamData->getDataList().resize(data->VarNumber);

		if(!isnan(_fillValue)) {
			for (int index = 0; index < data->VarNumber; index++) {
				if(*lData[index] != _fillValue) {
				_specParamData->getDataList().push_back(*lData[index]);
				} else {
					_specParamData->getDataList().push_back((BaseElemenType)NAN);
				}
			}
		}
		else {
			for (int index = 0; index < data->VarNumber; index++) {
				_specParamData->getDataList().push_back(*lData[index]);
			}

		}
	}

	SpecParamData* createParamData() {
		return new SpecParamData();
	}
};

} /* namespace Parameters */
} /* namespace AMDA */
#endif /* PUSHER_H_ */