# MI - Fimex: include/fimex/DataImpl.h Source File

- Main Page
- Related Pages
- Namespaces
- Classes
- Files
- Examples

# include/fimex/DataImpl.h

Go to the documentation of this file.

    00001 /*
    00002  * Fimex
    00003  *
    00004  * (C) Copyright 2008, met.no
    00005  *
    00006  * Project Info:  https://wiki.met.no/fimex/start
    00007  *
    00008  * This library is free software; you can redistribute it and/or modify it
    00009  * under the terms of the GNU Lesser General Public License as published by
    00010  * the Free Software Foundation; either version 2.1 of the License, or
    00011  * (at your option) any later version.
    00012  *
    00013  * This library is distributed in the hope that it will be useful, but
    00014  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    00015  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
    00016  * License for more details.
    00017  *
    00018  * You should have received a copy of the GNU Lesser General Public
    00019  * License along with this library; if not, write to the Free Software
    00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
    00021  * USA.
    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                 // conversion function
    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                 // specialized for each known type in Data.cc
    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         // below follow implementations of templates
    00141         // (template definitions should be in header files (depending on compiler))
    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                 // last element without separator
    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                 // fixing max range
    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 // don't implement all possible setValues functions, link-time error
    00173 //      template<typename C>
    00174 //      void DataImpl<C>::setValues(size_t startPos, const Data& data, size_t first, size_t last) throw(CDMException){
    00175 //              throw(CDMException("setValues not implemented for this datatype"));
    00176 //      }
    00177
    00178         // declaration of implemented function (in Data.cc)
    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]; // forward orgData pointer
    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             // handle empty data
    00221             if (orgDimSize.size() == 0 || orgDimSize.size() == 0) {
    00222                 return boost::shared_ptr<DataImpl<C> >(new DataImpl<C>(0));
    00223             }
    00224                 // get the sizes of the original data and the output data
    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                 // get the old and new datacontainer
    00235                 boost::shared_ptr<DataImpl<C> > output(new DataImpl<C>(outputSize));
    00236                 C* newData = output->theData.get();
    00237                 C* oldData = theData.get();
    00238
    00239                 // pre-calculation of the slice-size of the different dimensions
    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                 // slice the data
    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)); // dummy default
    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         // this version is identical to duplicateArrayType one, except that it allows for specializations
    00291         // in the case of T1 == T2 (see Data.cc)
    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)); // a dummy dataset
    00310
    00311         }
    00312
    00313 }
    00314
    00315 #endif /*DATAIMPL_H_*/