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 for (size_t i = 0; i < (length-1); i++) {
00145 os << theData[i] << separator;
00146 }
00147 os << theData[length-1];
00148 }
00149
00150 template<typename C>
00151 std::string DataImpl<C>::asString(std::string separator) const {
00152 std::ostringstream o;
00153 toStream(o, separator);
00154 return o.str();
00155 }
00156
00157 template<typename C>
00158 void DataImpl<C>::copyData(size_t startPos, const boost::shared_array<C>& otherData, size_t otherSize, size_t otherFirst, size_t otherLast) throw(CDMException) {
00159 if (otherFirst > otherSize) {
00160 throw(CDMException("data-region-start "+ type2string(otherFirst) + " outside range: "+ type2string(otherSize)));
00161 }
00162
00163 otherLast = std::min(otherLast, otherSize);
00164 otherLast = std::min(size()-startPos+otherFirst, otherLast);
00165 if (otherLast > otherFirst) {
00166 std::copy(&otherData[otherFirst], &otherData[otherLast], &theData[startPos]);
00167 }
00168 }
00169
00170
00171
00172
00173
00174
00175
00176 template<>
00177 void DataImpl<char>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException);
00178 template<>
00179 void DataImpl<short>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException);
00180 template<>
00181 void DataImpl<int>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException);
00182 template<>
00183 void DataImpl<float>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException);
00184 template<>
00185 void DataImpl<double>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException);
00186
00201 template<typename C>
00202 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) {
00203 (*orgData) += newStart[currentDim] * orgSliceSize[currentDim];
00204 if (currentDim == 0) {
00205 *newData = std::copy(&(*orgData)[0], &(*orgData)[newSize[0]], *newData);
00206 (*orgData) += newSize[0];
00207 } else {
00208 for (size_t i = 0; i < newSize[currentDim]; i++) {
00209 recursiveCopyMultiDimData(orgData, newData, orgDimSize, orgSliceSize, newStart, newSize, currentDim - 1);
00210 }
00211 }
00212 (*orgData) += (orgDimSize[currentDim] - (newStart[currentDim] + newSize[currentDim])) * orgSliceSize[currentDim];
00213 }
00214
00215 template<typename C>
00216 boost::shared_ptr<Data> DataImpl<C>::slice(std::vector<size_t> orgDimSize, std::vector<size_t> startDims, std::vector<size_t> outputDimSize) throw(CDMException) {
00217
00218 size_t orgSize = 1;
00219 size_t outputSize = 1;
00220 for (size_t i = 0; i < orgDimSize.size(); ++i) {
00221 outputSize *= outputDimSize[i];
00222 orgSize *= orgDimSize[i];
00223 if (orgDimSize[i] < (startDims[i] + outputDimSize[i])) throw CDMException("dimension-size error, start+size > orgSize: " + type2string(startDims[i]+outputDimSize[i]) + ">" + type2string(orgDimSize[i]) );
00224 }
00225 if (orgSize != size()) throw CDMException("dimension-mismatch: " + type2string(size()) + "!=" + type2string(orgSize));
00226
00227
00228 boost::shared_ptr<DataImpl<C> > output(new DataImpl<C>(outputSize));
00229 C* newData = output->theData.get();
00230 C* oldData = theData.get();
00231
00232
00233 std::vector<size_t> orgSliceSize(orgDimSize.size(), 0);
00234 orgSliceSize[0] = 1;
00235 for (size_t dim = 1; dim < orgDimSize.size(); dim++) {
00236 orgSliceSize[dim] = orgSliceSize[dim-1] * orgDimSize[dim-1];
00237 }
00238
00239 recursiveCopyMultiDimData(&oldData, &newData, orgDimSize, orgSliceSize, startDims, outputDimSize, orgDimSize.size() - 1);
00240
00241 return output;
00242 }
00243
00244 template<typename C>
00245 template<class InputIterator>
00246 void DataImpl<C>::setValues(InputIterator begin, InputIterator end, size_t dataStartPos) throw(CDMException) {
00247 size_t dist = std::distance(begin, end);
00248 if ((dist + dataStartPos) > length)
00249 throw CDMException("dataPos " + type2string(dist+dataStartPos) + " >= dataLength " + type2string(length));
00250 std::transform(begin, end, &theData[dataStartPos], staticCast<C>());
00251 }
00252
00253 template<typename OUT, typename IN>
00254 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) {
00255 boost::shared_array<OUT> outData(new OUT[length]);
00256 std::transform(&inData[0], &inData[length], &outData[0], ScaleValue<IN, OUT>(oldFill, oldScale, oldOffset, newFill, newScale, newOffset));
00257 return outData;
00258 }
00259
00260 template<typename C>
00261 boost::shared_ptr<Data> DataImpl<C>::convertDataType(double oldFill, double oldScale, double oldOffset, CDMDataType newType, double newFill, double newScale, double newOffset) throw(CDMException)
00262 {
00263 boost::shared_ptr<Data> data(new DataImpl<char>(0));
00264 switch (newType) {
00265 case CDM_CHAR: data = boost::shared_ptr<Data>(new DataImpl<char>(convertArrayType<char>(theData, size(), oldFill, oldScale, oldOffset, newFill, newScale, newOffset), size())); break;
00266 case CDM_SHORT: data = boost::shared_ptr<Data>(new DataImpl<short>(convertArrayType<short>(theData, size(), oldFill, oldScale, oldOffset, newFill, newScale, newOffset), size())); break;
00267 case CDM_INT: data = boost::shared_ptr<Data>(new DataImpl<int>(convertArrayType<int>(theData, size(), oldFill, oldScale, oldOffset, newFill, newScale, newOffset), size())); break;
00268 case CDM_FLOAT: data = boost::shared_ptr<Data>(new DataImpl<float>(convertArrayType<float>(theData, size(), oldFill, oldScale, oldOffset, newFill, newScale, newOffset), size())); break;
00269 case CDM_DOUBLE: data = boost::shared_ptr<Data>(new DataImpl<double>(convertArrayType<double>(theData, size(), oldFill, oldScale, oldOffset, newFill, newScale, newOffset), size())); break;
00270 case CDM_STRING: throw CDMException("cannot convert string datatype"); break;
00271 case CDM_NAT: throw CDMException("cannot convert CDM_NAT datatype"); break;
00272 }
00273 return data;
00274 }
00275
00276
00277 template<typename T1, typename T2>
00278 boost::shared_array<T1> duplicateArrayType(const boost::shared_array<T2>& inData, long length) {
00279 boost::shared_array<T1> outData(new T1[length]);
00280 std::transform(&inData[0], &inData[length], &outData[0], staticCast<T2>());
00281 return outData;
00282 }
00283
00284
00285 template<typename T1, typename T2>
00286 const boost::shared_array<T1> constConvertArrayType(const boost::shared_array<T2>& inData, long length) {
00287 return duplicateArrayType<T1,T2>(inData, length);
00288 }
00289
00290 template<class InputIterator>
00291 boost::shared_ptr<Data> createData(CDMDataType datatype, InputIterator first, InputIterator last) throw(CDMException) {
00292 size_t length = std::distance(first, last);
00293 switch (datatype) {
00294 case CDM_DOUBLE: { boost::shared_ptr<DataImpl<double> > data(new DataImpl<double>(length)); data->setValues(first, last); return data; }
00295 case CDM_FLOAT: { boost::shared_ptr<DataImpl<float> > data(new DataImpl<float>(length)); data->setValues(first, last); return data; }
00296 case CDM_INT: { boost::shared_ptr<DataImpl<int> > data(new DataImpl<int>(length)); data->setValues(first, last); return data; }
00297 case CDM_SHORT: { boost::shared_ptr<DataImpl<short> > data(new DataImpl<short>(length)); data->setValues(first, last); return data; }
00298 case CDM_CHAR: { boost::shared_ptr<DataImpl<char> > data(new DataImpl<char>(length)); data->setValues(first, last); return data; }
00299 case CDM_NAT: ;
00300 default: ;
00301 }
00302 return boost::shared_ptr<Data>(new DataImpl<char>(0));
00303
00304 }
00305
00306 }
00307
00308 #endif