00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef DATAIMPL_H_
00025 #define DATAIMPL_H_
00026
00027 #include <typeinfo>
00028 #include <boost/shared_ptr.hpp>
00029 #include <string>
00030 #include <sstream>
00031 #include <iostream>
00032 #include <cmath>
00033 #include "fimex/Data.h"
00034 #include "fimex/CDMDataType.h"
00035 #include "fimex/CDMException.h"
00036 #include "fimex/Utils.h"
00037
00038 namespace MetNoFimex
00039 {
00040
00048 template<typename T1, typename T2>
00049 boost::shared_array<T1> duplicateArrayType(const boost::shared_array<T2>& inData, long length);
00057 template<typename T1, typename T2>
00058 const boost::shared_array<T1> constConvertArrayType(const boost::shared_array<T2>& inData, long length);
00059
00060
00061
00062 template<typename C>
00063 class DataImpl : public Data
00064 {
00065 public:
00067 explicit DataImpl(long length)
00068 : length(length), theData(new C[length]) {}
00069 explicit DataImpl(boost::shared_array<C> array, long length)
00070 : length(length), theData(array) {}
00071 virtual ~DataImpl() {}
00072
00073 virtual size_t size() const {return length;}
00074 virtual int bytes_for_one() const {return sizeof(C);}
00075 virtual void* getDataPtr() {return &theData[0];}
00076 virtual void toStream(std::ostream& os, std::string separator = "") const;
00077
00081 virtual const boost::shared_array<C> asBase() const {return theData;}
00085 template<typename T>
00086 const boost::shared_array<T> as() const {return constConvertArrayType<T, C>(theData, length);}
00087 template<typename T>
00088 boost::shared_array<T> as() {return duplicateArrayType<T, C>(theData, length);}
00089
00090 const virtual boost::shared_array<char> asConstChar() const {return as<char>();}
00091 virtual boost::shared_array<char> asChar() {return as<char>();}
00092 const virtual boost::shared_array<short> asConstShort() const {return as<short>();}
00093 virtual boost::shared_array<short> asShort() {return as<short>();}
00094 const virtual boost::shared_array<int> asConstInt() const {return as<int>();}
00095 virtual boost::shared_array<int> asInt() {return as<int>();}
00096 const virtual boost::shared_array<float> asConstFloat() const {return as<float>();}
00097 virtual boost::shared_array<float> asFloat() {return as<float>();}
00098 const virtual boost::shared_array<double> asConstDouble() const {return as<double>();}
00099 virtual boost::shared_array<double> asDouble() {return as<double>();}
00100 virtual std::string asString(std::string separator = "") const;
00101
00102
00103 virtual void setValue(long pos, double val) {theData[pos] = static_cast<C>(val);}
00104 virtual void setValues(size_t startPos, const Data& data, size_t first = 0, size_t last = -1) throw(CDMException);
00105 virtual boost::shared_ptr<Data> slice(std::vector<size_t> orgDimSize, std::vector<size_t> startDims, std::vector<size_t> outputDimSize) throw(CDMException);
00106 virtual boost::shared_ptr<Data> convertDataType(double oldFill, double oldScale, double oldOffset, CDMDataType newType, double newFill, double newScale, double newOffset) throw(CDMException);
00107
00108 virtual CDMDataType getDataType() const {return CDM_NAT;}
00109
00113 template<class InputIterator>
00114 void setValues(InputIterator first, InputIterator last, size_t dataStartPos = 0) throw(CDMException);
00115
00116 private:
00117 size_t length;
00118 boost::shared_array<C> theData;
00119 void copyData(size_t startPos, const boost::shared_array<C>& otherData, size_t otherSize, size_t otherStart, size_t otherEnd) throw(CDMException);
00120 };
00121
00131 template<class InputIterator>
00132 boost::shared_ptr<Data> createData(CDMDataType datatype, size_t length, InputIterator first, InputIterator last) throw(CDMException);
00133
00134
00135
00136 template<typename C>
00137 void DataImpl<C>::toStream(std::ostream& os, std::string separator) const {
00138 for (size_t i = 0; i < (length-1); i++) {
00139 os << theData[i] << separator;
00140 }
00141 os << theData[length-1];
00142 }
00143
00144 template<typename C>
00145 std::string DataImpl<C>::asString(std::string separator) const {
00146 std::ostringstream o;
00147 toStream(o, separator);
00148 return o.str();
00149 }
00150
00151 template<typename C>
00152 void DataImpl<C>::copyData(size_t startPos, const boost::shared_array<C>& otherData, size_t otherSize, size_t otherFirst, size_t otherLast) throw(CDMException) {
00153 if (otherFirst > otherSize) {
00154 throw(CDMException("data-region-start "+ type2string(otherFirst) + " outside range: "+ type2string(otherSize)));
00155 }
00156
00157 otherLast = std::min(otherLast, otherSize);
00158 otherLast = std::min(size()-startPos+otherFirst, otherLast);
00159 if (otherLast > otherFirst) {
00160 std::copy(&otherData[otherFirst], &otherData[otherLast], &theData[startPos]);
00161 }
00162 }
00163 template<typename C>
00164 void DataImpl<C>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException){
00165 throw(CDMException("setValues not implemented for this datatype"));
00166 }
00167 template<>
00168 void DataImpl<char>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException);
00169 template<>
00170 void DataImpl<short>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException);
00171 template<>
00172 void DataImpl<int>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException);
00173 template<>
00174 void DataImpl<float>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException);
00175 template<>
00176 void DataImpl<double>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException);
00177
00192 template<typename C>
00193 void recursiveCopyMultiDimData(C** orgData, C** newData, const std::vector<size_t>& orgDimSize, const std::vector<size_t>& orgSliceSize, const std::vector<size_t>& newStart, const std::vector<size_t>& newSize, size_t currentDim) {
00194 (*orgData) += newStart[currentDim] * orgSliceSize[currentDim];
00195 if (currentDim == 0) {
00196
00197 for (size_t i = 0; i < newSize[0]; i++) {
00198 *(*newData)++ = *(*orgData)++;
00199 }
00200 } else {
00201 for (size_t i = 0; i < newSize[currentDim]; i++) {
00202 recursiveCopyMultiDimData(orgData, newData, orgDimSize, orgSliceSize, newStart, newSize, currentDim - 1);
00203 }
00204 }
00205 (*orgData) += (orgDimSize[currentDim] - (newStart[currentDim] + newSize[currentDim])) * orgSliceSize[currentDim];
00206 }
00207
00208 template<typename C>
00209 boost::shared_ptr<Data> DataImpl<C>::slice(std::vector<size_t> orgDimSize, std::vector<size_t> startDims, std::vector<size_t> outputDimSize) throw(CDMException) {
00210
00211 size_t orgSize = 1;
00212 size_t outputSize = 1;
00213 for (size_t i = 0; i < orgDimSize.size(); ++i) {
00214 outputSize *= outputDimSize[i];
00215 orgSize *= orgDimSize[i];
00216 if (orgDimSize[i] < (startDims[i] + outputDimSize[i])) throw CDMException("dimension-size error, start+size > orgSize: " + type2string(startDims[i]+outputDimSize[i]) + ">" + type2string(orgDimSize[i]) );
00217 }
00218 if (orgSize != size()) throw CDMException("dimension-mismatch: " + type2string(size()) + "!=" + type2string(orgSize));
00219
00220
00221 boost::shared_ptr<DataImpl<C> > output(new DataImpl<C>(outputSize));
00222 C* newData = output->theData.get();
00223 C* oldData = theData.get();
00224
00225
00226 std::vector<size_t> orgSliceSize;
00227 orgSliceSize.reserve(orgDimSize.size());
00228 orgSliceSize[0] = 1;
00229 for (size_t dim = 1; dim < orgDimSize.size(); dim++) {
00230 orgSliceSize[dim] = orgSliceSize[dim-1] * orgDimSize[dim-1];
00231 }
00232
00233 recursiveCopyMultiDimData(&oldData, &newData, orgDimSize, orgSliceSize, startDims, outputDimSize, orgDimSize.size() - 1);
00234
00235 return output;
00236 }
00237
00238
00239 template<typename C>
00240 template<class InputIterator>
00241 void DataImpl<C>::setValues(InputIterator first, InputIterator last, size_t dataStartPos) throw(CDMException) {
00242 size_t dataPos = dataStartPos;
00243 if (dataPos < 0) {
00244 throw CDMException("dataPos < 0, cannot set data");
00245 }
00246 for (; first != last; ++first) {
00247 if (dataPos < length) {
00248 theData[dataPos] = static_cast<C>(*first);
00249 } else {
00250 throw CDMException("dataPos " + type2string(dataPos) + " >= dataLength " + type2string(length));
00251 }
00252 ++dataPos;
00253 }
00254 }
00255
00256 template<typename T1, typename T2>
00257 boost::shared_array<T1> convertArrayType(const boost::shared_array<T2>& inData, size_t length, double oldFill, double oldScale, double oldOffset, double newFill, double newScale, double newOffset) {
00258 boost::shared_array<T1> outData(new T1[length]);
00259 T2* inDataPos = &inData[0];
00260 T2* inDataLast = &inData[length];
00261 T1* outDataPos = &outData[0];
00262 T1 fill = static_cast<T1>(newFill);
00263 while (inDataPos != inDataLast) {
00264 if (*inDataPos == oldFill || isinf(static_cast<double>(*inDataPos))) {
00265 *outDataPos = fill;
00266 } else {
00267 *outDataPos = static_cast<T1>(((oldScale*(*inDataPos) + oldOffset)-newOffset)/newScale);
00268 }
00269 *inDataPos++;
00270 *outDataPos++;
00271 }
00272 return outData;
00273 }
00274
00275 template<typename C>
00276 boost::shared_ptr<Data> DataImpl<C>::convertDataType(double oldFill, double oldScale, double oldOffset, CDMDataType newType, double newFill, double newScale, double newOffset) throw(CDMException)
00277 {
00278 boost::shared_ptr<Data> data(new DataImpl<char>(0));
00279 switch (newType) {
00280 case CDM_CHAR: data = boost::shared_ptr<Data>(new DataImpl<char>(convertArrayType<char>(theData, size(), oldFill, oldScale, oldOffset, newFill, newScale, newOffset), size())); break;
00281 case CDM_SHORT: data = boost::shared_ptr<Data>(new DataImpl<short>(convertArrayType<short>(theData, size(), oldFill, oldScale, oldOffset, newFill, newScale, newOffset), size())); break;
00282 case CDM_INT: data = boost::shared_ptr<Data>(new DataImpl<int>(convertArrayType<int>(theData, size(), oldFill, oldScale, oldOffset, newFill, newScale, newOffset), size())); break;
00283 case CDM_FLOAT: data = boost::shared_ptr<Data>(new DataImpl<float>(convertArrayType<float>(theData, size(), oldFill, oldScale, oldOffset, newFill, newScale, newOffset), size())); break;
00284 case CDM_DOUBLE: data = boost::shared_ptr<Data>(new DataImpl<double>(convertArrayType<double>(theData, size(), oldFill, oldScale, oldOffset, newFill, newScale, newOffset), size())); break;
00285 case CDM_STRING: throw CDMException("cannot convert string datatype"); break;
00286 case CDM_NAT: throw CDMException("cannot convert CDM_NAT datatype"); break;
00287 }
00288 return data;
00289 }
00290
00291
00292 template<typename T1, typename T2>
00293 boost::shared_array<T1> duplicateArrayType(const boost::shared_array<T2>& inData, long length) {
00294 boost::shared_array<T1> outData(new T1[length]);
00295 T2* inDataPos = &inData[0];
00296 T2* inDataLast = &inData[length];
00297 T1* outDataPos = &outData[0];
00298 while (inDataPos != inDataLast) {
00299 *outDataPos++ = static_cast<T1>(*inDataPos++);
00300 }
00301 return outData;
00302 }
00303
00304
00305 template<typename T1, typename T2>
00306 const boost::shared_array<T1> constConvertArrayType(const boost::shared_array<T2>& inData, long length) {
00307 return duplicateArrayType<T1,T2>(inData, length);
00308 }
00309
00310 template<class InputIterator>
00311 boost::shared_ptr<Data> createData(CDMDataType datatype, size_t length, InputIterator first, InputIterator last) throw(CDMException) {
00312 switch (datatype) {
00313 case CDM_DOUBLE: { boost::shared_ptr<DataImpl<double> > data(new DataImpl<double>(length)); data->setValues(first, last); return data; }
00314 case CDM_FLOAT: { boost::shared_ptr<DataImpl<float> > data(new DataImpl<float>(length)); data->setValues(first, last); return data; }
00315 case CDM_INT: { boost::shared_ptr<DataImpl<int> > data(new DataImpl<int>(length)); data->setValues(first, last); return data; }
00316 case CDM_SHORT: { boost::shared_ptr<DataImpl<short> > data(new DataImpl<short>(length)); data->setValues(first, last); return data; }
00317 case CDM_CHAR: { boost::shared_ptr<DataImpl<char> > data(new DataImpl<char>(length)); data->setValues(first, last); return data; }
00318 case CDM_NAT: ;
00319 default: ;
00320 }
00321 return boost::shared_ptr<Data>(new DataImpl<char>(0));
00322
00323 }
00324
00325 }
00326
00327 #endif