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 <iterator>
00033 #include <cmath>
00034 #include <algorithm>
00035 #include "fimex/Data.h"
00036 #include "fimex/CDMDataType.h"
00037 #include "fimex/CDMException.h"
00038 #include "fimex/Utils.h"
00039
00040 namespace MetNoFimex
00041 {
00042
00054 template<typename T1, typename T2>
00055 boost::shared_array<T1> duplicateArrayType(const boost::shared_array<T2>& inData, long length);
00063 template<typename T1, typename T2>
00064 const boost::shared_array<T1> constConvertArrayType(const boost::shared_array<T2>& inData, long length);
00065
00066
00067
00068 template<typename C>
00069 class DataImpl : public Data
00070 {
00071 public:
00073 explicit DataImpl(long length)
00074 : length(length), theData(new C[length]) {}
00075 explicit DataImpl(boost::shared_array<C> array, long length)
00076 : length(length), theData(array) {}
00077 virtual ~DataImpl() {}
00078
00079 virtual size_t size() const {return length;}
00080 virtual int bytes_for_one() const {return sizeof(C);}
00081 virtual void* getDataPtr() {return &theData[0];}
00082 virtual void toStream(std::ostream& os, std::string separator = "") const;
00083
00087 virtual const boost::shared_array<C> asBase() const {return theData;}
00091 template<typename T>
00092 const boost::shared_array<T> as() const {return constConvertArrayType<T, C>(theData, length);}
00093 template<typename T>
00094 boost::shared_array<T> as() {return duplicateArrayType<T, C>(theData, length);}
00095
00096 const virtual boost::shared_array<char> asConstChar() const {return as<char>();}
00097 virtual boost::shared_array<char> asChar() {return as<char>();}
00098 const virtual boost::shared_array<short> asConstShort() const {return as<short>();}
00099 virtual boost::shared_array<short> asShort() {return as<short>();}
00100 const virtual boost::shared_array<int> asConstInt() const {return as<int>();}
00101 virtual boost::shared_array<int> asInt() {return as<int>();}
00102 const virtual boost::shared_array<float> asConstFloat() const {return as<float>();}
00103 virtual boost::shared_array<float> asFloat() {return as<float>();}
00104 const virtual boost::shared_array<double> asConstDouble() const {return as<double>();}
00105 virtual boost::shared_array<double> asDouble() {return as<double>();}
00106 virtual std::string asString(std::string separator = "") const;
00107
00108
00109 virtual void setValue(long pos, double val) {theData[pos] = static_cast<C>(val);}
00110 virtual void setValues(size_t startPos, const Data& data, size_t first = 0, size_t last = -1) throw(CDMException);
00111 virtual void setAllValues(double val) {C v = static_cast<C>(val); for (C* pos = &theData[0]; pos != (&theData[0])+length; ++pos) *pos = v;}
00112 virtual boost::shared_ptr<Data> slice(std::vector<size_t> orgDimSize, std::vector<size_t> startDims, std::vector<size_t> outputDimSize) throw(CDMException);
00113 virtual boost::shared_ptr<Data> convertDataType(double oldFill, double oldScale, double oldOffset, CDMDataType newType, double newFill, double newScale, double newOffset) throw(CDMException);
00114
00115 virtual CDMDataType getDataType() const {return CDM_NAT;}
00116
00120 template<class InputIterator>
00121 void setValues(InputIterator begin, InputIterator end, size_t dataStartPos = 0) throw(CDMException);
00122
00123 private:
00124 size_t length;
00125 boost::shared_array<C> theData;
00126 void copyData(size_t startPos, const boost::shared_array<C>& otherData, size_t otherSize, size_t otherStart, size_t otherEnd) throw(CDMException);
00127 };
00128
00137 template<class InputIterator>
00138 boost::shared_ptr<Data> createData(CDMDataType datatype, InputIterator first, InputIterator last) throw(CDMException);
00139
00140
00141
00142 template<typename C>
00143 void DataImpl<C>::toStream(std::ostream& os, std::string separator) const {
00144 if (length > 0) {
00145 for (size_t i = 0; i < (length-1); i++) {
00146 os << theData[i] << separator;
00147 }
00148
00149 os << theData[length-1];
00150 }
00151 }
00152
00153 template<typename C>
00154 std::string DataImpl<C>::asString(std::string separator) const {
00155 std::ostringstream o;
00156 toStream(o, separator);
00157 return o.str();
00158 }
00159
00160 template<typename C>
00161 void DataImpl<C>::copyData(size_t startPos, const boost::shared_array<C>& otherData, size_t otherSize, size_t otherFirst, size_t otherLast) throw(CDMException) {
00162 if (otherFirst > otherSize) {
00163 throw(CDMException("data-region-start "+ type2string(otherFirst) + " outside range: "+ type2string(otherSize)));
00164 }
00165
00166 otherLast = std::min(otherLast, otherSize);
00167 otherLast = std::min(size()-startPos+otherFirst, otherLast);
00168 if (otherLast > otherFirst) {
00169 std::copy(&otherData[otherFirst], &otherData[otherLast], &theData[startPos]);
00170 }
00171 }
00172
00173
00174
00175
00176
00177
00178
00179 template<>
00180 void DataImpl<char>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException);
00181 template<>
00182 void DataImpl<short>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException);
00183 template<>
00184 void DataImpl<int>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException);
00185 template<>
00186 void DataImpl<float>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException);
00187 template<>
00188 void DataImpl<double>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException);
00189
00204 template<typename C>
00205 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) {
00206 (*orgData) += newStart[currentDim] * orgSliceSize[currentDim];
00207 if (currentDim == 0) {
00208 *newData = std::copy(&(*orgData)[0], &(*orgData)[newSize[0]], *newData);
00209 (*orgData) += newSize[0];
00210 } else {
00211 for (size_t i = 0; i < newSize[currentDim]; i++) {
00212 recursiveCopyMultiDimData(orgData, newData, orgDimSize, orgSliceSize, newStart, newSize, currentDim - 1);
00213 }
00214 }
00215 (*orgData) += (orgDimSize[currentDim] - (newStart[currentDim] + newSize[currentDim])) * orgSliceSize[currentDim];
00216 }
00217
00218 template<typename C>
00219 boost::shared_ptr<Data> DataImpl<C>::slice(std::vector<size_t> orgDimSize, std::vector<size_t> startDims, std::vector<size_t> outputDimSize) throw(CDMException) {
00220
00221 if (orgDimSize.size() == 0 || orgDimSize.size() == 0) {
00222 return boost::shared_ptr<DataImpl<C> >(new DataImpl<C>(0));
00223 }
00224
00225 size_t orgSize = 1;
00226 size_t outputSize = 1;
00227 for (size_t i = 0; i < orgDimSize.size(); ++i) {
00228 outputSize *= outputDimSize[i];
00229 orgSize *= orgDimSize[i];
00230 if (orgDimSize[i] < (startDims[i] + outputDimSize[i])) throw CDMException("dimension-size error, start+size > orgSize: " + type2string(startDims[i]+outputDimSize[i]) + ">" + type2string(orgDimSize[i]) );
00231 }
00232 if (orgSize != size()) throw CDMException("dimension-mismatch: " + type2string(size()) + "!=" + type2string(orgSize));
00233
00234
00235 boost::shared_ptr<DataImpl<C> > output(new DataImpl<C>(outputSize));
00236 C* newData = output->theData.get();
00237 C* oldData = theData.get();
00238
00239
00240 std::vector<size_t> orgSliceSize(orgDimSize.size(), 0);
00241 orgSliceSize[0] = 1;
00242 for (size_t dim = 1; dim < orgDimSize.size(); dim++) {
00243 orgSliceSize[dim] = orgSliceSize[dim-1] * orgDimSize[dim-1];
00244 }
00245
00246 recursiveCopyMultiDimData(&oldData, &newData, orgDimSize, orgSliceSize, startDims, outputDimSize, orgDimSize.size() - 1);
00247
00248 return output;
00249 }
00250
00251 template<typename C>
00252 template<class InputIterator>
00253 void DataImpl<C>::setValues(InputIterator begin, InputIterator end, size_t dataStartPos) throw(CDMException) {
00254 size_t dist = std::distance(begin, end);
00255 if ((dist + dataStartPos) > length)
00256 throw CDMException("dataPos " + type2string(dist+dataStartPos) + " >= dataLength " + type2string(length));
00257 std::transform(begin, end, &theData[dataStartPos], staticCast<C>());
00258 }
00259
00260 template<typename OUT, typename IN>
00261 boost::shared_array<OUT> convertArrayType(const boost::shared_array<IN>& inData, size_t length, double oldFill, double oldScale, double oldOffset, double newFill, double newScale, double newOffset) {
00262 boost::shared_array<OUT> outData(new OUT[length]);
00263 std::transform(&inData[0], &inData[length], &outData[0], ScaleValue<IN, OUT>(oldFill, oldScale, oldOffset, newFill, newScale, newOffset));
00264 return outData;
00265 }
00266
00267 template<typename C>
00268 boost::shared_ptr<Data> DataImpl<C>::convertDataType(double oldFill, double oldScale, double oldOffset, CDMDataType newType, double newFill, double newScale, double newOffset) throw(CDMException)
00269 {
00270 boost::shared_ptr<Data> data(new DataImpl<char>(0));
00271 switch (newType) {
00272 case CDM_CHAR: data = boost::shared_ptr<Data>(new DataImpl<char>(convertArrayType<char>(theData, size(), oldFill, oldScale, oldOffset, newFill, newScale, newOffset), size())); break;
00273 case CDM_SHORT: data = boost::shared_ptr<Data>(new DataImpl<short>(convertArrayType<short>(theData, size(), oldFill, oldScale, oldOffset, newFill, newScale, newOffset), size())); break;
00274 case CDM_INT: data = boost::shared_ptr<Data>(new DataImpl<int>(convertArrayType<int>(theData, size(), oldFill, oldScale, oldOffset, newFill, newScale, newOffset), size())); break;
00275 case CDM_FLOAT: data = boost::shared_ptr<Data>(new DataImpl<float>(convertArrayType<float>(theData, size(), oldFill, oldScale, oldOffset, newFill, newScale, newOffset), size())); break;
00276 case CDM_DOUBLE: data = boost::shared_ptr<Data>(new DataImpl<double>(convertArrayType<double>(theData, size(), oldFill, oldScale, oldOffset, newFill, newScale, newOffset), size())); break;
00277 case CDM_STRING: throw CDMException("cannot convert string datatype"); break;
00278 case CDM_NAT: throw CDMException("cannot convert CDM_NAT datatype"); break;
00279 }
00280 return data;
00281 }
00282
00283
00284 template<typename T1, typename T2>
00285 boost::shared_array<T1> duplicateArrayType(const boost::shared_array<T2>& inData, long length) {
00286 boost::shared_array<T1> outData(new T1[length]);
00287 std::transform(&inData[0], &inData[length], &outData[0], staticCast<T2>());
00288 return outData;
00289 }
00290
00291
00292 template<typename T1, typename T2>
00293 const boost::shared_array<T1> constConvertArrayType(const boost::shared_array<T2>& inData, long length) {
00294 return duplicateArrayType<T1,T2>(inData, length);
00295 }
00296
00297 template<class InputIterator>
00298 boost::shared_ptr<Data> createData(CDMDataType datatype, InputIterator first, InputIterator last) throw(CDMException) {
00299 size_t length = std::distance(first, last);
00300 switch (datatype) {
00301 case CDM_DOUBLE: { boost::shared_ptr<DataImpl<double> > data(new DataImpl<double>(length)); data->setValues(first, last); return data; }
00302 case CDM_FLOAT: { boost::shared_ptr<DataImpl<float> > data(new DataImpl<float>(length)); data->setValues(first, last); return data; }
00303 case CDM_INT: { boost::shared_ptr<DataImpl<int> > data(new DataImpl<int>(length)); data->setValues(first, last); return data; }
00304 case CDM_SHORT: { boost::shared_ptr<DataImpl<short> > data(new DataImpl<short>(length)); data->setValues(first, last); return data; }
00305 case CDM_CHAR: { boost::shared_ptr<DataImpl<char> > data(new DataImpl<char>(length)); data->setValues(first, last); return data; }
00306 case CDM_NAT: ;
00307 default: ;
00308 }
00309 return boost::shared_ptr<Data>(new DataImpl<char>(0));
00310
00311 }
00312
00313 }
00314
00315 #endif