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 "Data.h"
00034 #include "CDMDataType.h"
00035 #include "CDMException.h"
00036 #include "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);
00110 template<class InputIterator>
00111 void setValues(InputIterator first, InputIterator last, size_t dataStartPos = 0) throw(CDMException);
00112
00113 private:
00114 size_t length;
00115 boost::shared_array<C> theData;
00116 void copyData(size_t startPos, const boost::shared_array<C>& otherData, size_t otherSize, size_t otherStart, size_t otherEnd) throw(CDMException);
00117 };
00118
00128 template<class InputIterator>
00129 boost::shared_ptr<Data> createData(CDMDataType datatype, size_t length, InputIterator first, InputIterator last) throw(CDMException);
00130
00131
00132
00133 template<typename C>
00134 void DataImpl<C>::toStream(std::ostream& os, std::string separator) const {
00135 for (size_t i = 0; i < (length-1); i++) {
00136 os << theData[i] << separator;
00137 }
00138 os << theData[length-1];
00139 }
00140
00141 template<typename C>
00142 std::string DataImpl<C>::asString(std::string separator) const {
00143 std::ostringstream o;
00144 toStream(o, separator);
00145 return o.str();
00146 }
00147
00148 template<typename C>
00149 void DataImpl<C>::copyData(size_t startPos, const boost::shared_array<C>& otherData, size_t otherSize, size_t otherFirst, size_t otherLast) throw(CDMException) {
00150 if (otherFirst > otherSize) {
00151 throw(CDMException("data-region-start "+ type2string(otherFirst) + " outside range: "+ type2string(otherSize)));
00152 }
00153
00154 otherLast = std::min(otherLast, otherSize);
00155 otherLast = std::min(size()-startPos+otherFirst, otherLast);
00156 if (otherLast > otherFirst) {
00157 std::copy(&otherData[otherFirst], &otherData[otherLast], &theData[startPos]);
00158 }
00159 }
00160 template<typename C>
00161 void DataImpl<C>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException){
00162 throw(CDMException("setValues not implemented for this datatype"));
00163 }
00164 template<>
00165 void DataImpl<char>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException);
00166 template<>
00167 void DataImpl<short>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException);
00168 template<>
00169 void DataImpl<int>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException);
00170 template<>
00171 void DataImpl<float>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException);
00172 template<>
00173 void DataImpl<double>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException);
00174
00189 template<typename C>
00190 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) {
00191 (*orgData) += newStart[currentDim] * orgSliceSize[currentDim];
00192 if (currentDim == 0) {
00193
00194 for (size_t i = 0; i < newSize[0]; i++) {
00195 *(*newData)++ = *(*orgData)++;
00196 }
00197 } else {
00198 for (size_t i = 0; i < newSize[currentDim]; i++) {
00199 recursiveCopyMultiDimData(orgData, newData, orgDimSize, orgSliceSize, newStart, newSize, currentDim - 1);
00200 }
00201 }
00202 (*orgData) += (orgDimSize[currentDim] - (newStart[currentDim] + newSize[currentDim])) * orgSliceSize[currentDim];
00203 }
00204
00205 template<typename C>
00206 boost::shared_ptr<Data> DataImpl<C>::slice(std::vector<size_t> orgDimSize, std::vector<size_t> startDims, std::vector<size_t> outputDimSize) throw(CDMException) {
00207
00208 size_t orgSize = 1;
00209 size_t outputSize = 1;
00210 for (size_t i = 0; i < orgDimSize.size(); ++i) {
00211 outputSize *= outputDimSize[i];
00212 orgSize *= orgDimSize[i];
00213 if (orgDimSize[i] < (startDims[i] + outputDimSize[i])) throw CDMException("dimension-size error, start+size > orgSize: " + type2string(startDims[i]+outputDimSize[i]) + ">" + type2string(orgDimSize[i]) );
00214 }
00215 if (orgSize != size()) throw CDMException("dimension-mismatch: " + type2string(size()) + "!=" + type2string(orgSize));
00216
00217
00218 boost::shared_ptr<DataImpl<C> > output(new DataImpl<C>(outputSize));
00219 C* newData = output->theData.get();
00220 C* oldData = theData.get();
00221
00222
00223 std::vector<size_t> orgSliceSize;
00224 orgSliceSize.reserve(orgDimSize.size());
00225 orgSliceSize[0] = 1;
00226 for (size_t dim = 1; dim < orgDimSize.size(); dim++) {
00227 orgSliceSize[dim] = orgSliceSize[dim-1] * orgDimSize[dim-1];
00228 }
00229
00230 recursiveCopyMultiDimData(&oldData, &newData, orgDimSize, orgSliceSize, startDims, outputDimSize, orgDimSize.size() - 1);
00231
00232 return output;
00233 }
00234
00235
00236 template<typename C>
00237 template<class InputIterator>
00238 void DataImpl<C>::setValues(InputIterator first, InputIterator last, size_t dataStartPos) throw(CDMException) {
00239 size_t dataPos = dataStartPos;
00240 if (dataPos < 0) {
00241 throw CDMException("dataPos < 0, cannot set data");
00242 }
00243 for (; first != last; ++first) {
00244 if (dataPos < length) {
00245 theData[dataPos] = static_cast<C>(*first);
00246 } else {
00247 throw CDMException("dataPos " + type2string(dataPos) + " >= dataLength " + type2string(length));
00248 }
00249 ++dataPos;
00250 }
00251 }
00252
00253 template<typename T1, typename T2>
00254 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) {
00255 boost::shared_array<T1> outData(new T1[length]);
00256 T2* inDataPos = &inData[0];
00257 T2* inDataLast = &inData[length];
00258 T1* outDataPos = &outData[0];
00259 T1 fill = static_cast<T1>(newFill);
00260 while (inDataPos != inDataLast) {
00261 if (*inDataPos == oldFill || isinf(static_cast<double>(*inDataPos))) {
00262 *outDataPos = fill;
00263 } else {
00264 *outDataPos = static_cast<T1>(((oldScale*(*inDataPos) + oldOffset)-newOffset)/newScale);
00265 }
00266 *inDataPos++;
00267 *outDataPos++;
00268 }
00269 return outData;
00270 }
00271
00272 template<typename C>
00273 boost::shared_ptr<Data> DataImpl<C>::convertDataType(double oldFill, double oldScale, double oldOffset, CDMDataType newType, double newFill, double newScale, double newOffset) throw(CDMException)
00274 {
00275 boost::shared_ptr<Data> data(new DataImpl<char>(0));
00276 switch (newType) {
00277 case CDM_CHAR: data = boost::shared_ptr<Data>(new DataImpl<char>(convertArrayType<char>(theData, size(), oldFill, oldScale, oldOffset, newFill, newScale, newOffset), size())); break;
00278 case CDM_SHORT: data = boost::shared_ptr<Data>(new DataImpl<short>(convertArrayType<short>(theData, size(), oldFill, oldScale, oldOffset, newFill, newScale, newOffset), size())); break;
00279 case CDM_INT: data = boost::shared_ptr<Data>(new DataImpl<int>(convertArrayType<int>(theData, size(), oldFill, oldScale, oldOffset, newFill, newScale, newOffset), size())); break;
00280 case CDM_FLOAT: data = boost::shared_ptr<Data>(new DataImpl<float>(convertArrayType<float>(theData, size(), oldFill, oldScale, oldOffset, newFill, newScale, newOffset), size())); break;
00281 case CDM_DOUBLE: data = boost::shared_ptr<Data>(new DataImpl<double>(convertArrayType<double>(theData, size(), oldFill, oldScale, oldOffset, newFill, newScale, newOffset), size())); break;
00282 case CDM_STRING: throw CDMException("cannot convert string datatype"); break;
00283 case CDM_NAT: throw CDMException("cannot convert CDM_NAT datatype"); break;
00284 }
00285 return data;
00286 }
00287
00288
00289 template<typename T1, typename T2>
00290 boost::shared_array<T1> duplicateArrayType(const boost::shared_array<T2>& inData, long length) {
00291 boost::shared_array<T1> outData(new T1[length]);
00292 T2* inDataPos = &inData[0];
00293 T2* inDataLast = &inData[length];
00294 T1* outDataPos = &outData[0];
00295 while (inDataPos != inDataLast) {
00296 *outDataPos++ = static_cast<T1>(*inDataPos++);
00297 }
00298 return outData;
00299 }
00300
00301
00302 template<typename T1, typename T2>
00303 const boost::shared_array<T1> constConvertArrayType(const boost::shared_array<T2>& inData, long length) {
00304 return duplicateArrayType<T1,T2>(inData, length);
00305 }
00306
00307 template<class InputIterator>
00308 boost::shared_ptr<Data> createData(CDMDataType datatype, size_t length, InputIterator first, InputIterator last) throw(CDMException) {
00309 switch (datatype) {
00310 case CDM_DOUBLE: { boost::shared_ptr<DataImpl<double> > data(new DataImpl<double>(length)); data->setValues(first, last); return data; }
00311 case CDM_FLOAT: { boost::shared_ptr<DataImpl<float> > data(new DataImpl<float>(length)); data->setValues(first, last); return data; }
00312 case CDM_INT: { boost::shared_ptr<DataImpl<int> > data(new DataImpl<int>(length)); data->setValues(first, last); return data; }
00313 case CDM_SHORT: { boost::shared_ptr<DataImpl<short> > data(new DataImpl<short>(length)); data->setValues(first, last); return data; }
00314 case CDM_CHAR: { boost::shared_ptr<DataImpl<char> > data(new DataImpl<char>(length)); data->setValues(first, last); return data; }
00315 case CDM_NAT: ;
00316 default: ;
00317 }
00318 return boost::shared_ptr<Data>(new DataImpl<char>(0));
00319
00320 }
00321
00322 }
00323
00324 #endif