Salome HOME
Addition of tools for combination of part definition for // manip.
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingMemArray.txx
index 5dddb27b6cecfe3a08579ca9bc993ed8bf795a53..90773df2bf988fdc97fb6522ffaf3af13a069222 100644 (file)
@@ -1,9 +1,9 @@
-// Copyright (C) 2007-2012  CEA/DEN, EDF R&D
+// Copyright (C) 2007-2014  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 // License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+// version 2.1 of the License, or (at your option) any later version.
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -27,6 +27,7 @@
 #include "InterpolationUtils.hxx"
 
 #include <sstream>
+#include <cstdlib>
 #include <algorithm>
 
 namespace ParaMEDMEM
@@ -46,53 +47,53 @@ namespace ParaMEDMEM
   }
 
   template<class T>
-  MemArray<T>::MemArray(const MemArray<T>& other):_nb_of_elem(0),_nb_of_elem_alloc(0),_ownership(false),_dealloc(CPP_DEALLOC)
+  MemArray<T>::MemArray(const MemArray<T>& other):_nb_of_elem(0),_nb_of_elem_alloc(0),_ownership(false),_dealloc(0),_param_for_deallocator(0)
   {
     if(!other._pointer.isNull())
       {
         _nb_of_elem_alloc=other._nb_of_elem;
-        T *pointer=new T[_nb_of_elem_alloc];
+        T *pointer=(T*)malloc(_nb_of_elem_alloc*sizeof(T));
         std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+other._nb_of_elem,pointer);
-        useArray(pointer,true,CPP_DEALLOC,other._nb_of_elem);
+        useArray(pointer,true,C_DEALLOC,other._nb_of_elem);
       }
   }
 
   template<class T>
-  void MemArray<T>::useArray(const T *array, bool ownership, DeallocType type, int nbOfElem)
+  void MemArray<T>::useArray(const T *array, bool ownership, DeallocType type, std::size_t nbOfElem)
   {
+    destroy();
     _nb_of_elem=nbOfElem;
     _nb_of_elem_alloc=nbOfElem;
-    destroy();
     if(ownership)
       _pointer.setInternal(const_cast<T *>(array));
     else
       _pointer.setExternal(array);
     _ownership=ownership;
-    _dealloc=type;
+    _dealloc=BuildFromType(type);
   }
 
   template<class T>
-  void MemArray<T>::useExternalArrayWithRWAccess(const T *array, int nbOfElem)
+  void MemArray<T>::useExternalArrayWithRWAccess(const T *array, std::size_t nbOfElem)
   {
+    destroy();
     _nb_of_elem=nbOfElem;
     _nb_of_elem_alloc=nbOfElem;
-    destroy();
     _pointer.setInternal(const_cast<T *>(array));
     _ownership=false;
-    _dealloc=CPP_DEALLOC;
+    _dealloc=CPPDeallocator;
   }
-  
+
   template<class T>
-  void MemArray<T>::writeOnPlace(int id, T element0, const T *others, int sizeOfOthers)
+  void MemArray<T>::writeOnPlace(std::size_t id, T element0, const T *others, std::size_t sizeOfOthers)
   {
     if(id+sizeOfOthers>=_nb_of_elem_alloc)
       reserve(2*_nb_of_elem+sizeOfOthers+1);
     T *pointer=_pointer.getPointer();
     pointer[id]=element0;
     std::copy(others,others+sizeOfOthers,pointer+id+1);
-    _nb_of_elem=std::max<int>(_nb_of_elem,id+sizeOfOthers+1);
+    _nb_of_elem=std::max<std::size_t>(_nb_of_elem,id+sizeOfOthers+1);
   }
-  
+
   template<class T>
   template<class InputIterator>
   void MemArray<T>::insertAtTheEnd(InputIterator first, InputIterator last)
@@ -100,7 +101,7 @@ namespace ParaMEDMEM
     T *pointer=_pointer.getPointer();
     while(first!=last)
       {
-        if(_nb_of_elem>=_nb_of_elem_alloc || _nb_of_elem==0)
+        if(_nb_of_elem>=_nb_of_elem_alloc)
           {
             reserve(_nb_of_elem_alloc>0?2*_nb_of_elem_alloc:1);
             pointer=_pointer.getPointer();
@@ -108,18 +109,18 @@ namespace ParaMEDMEM
         pointer[_nb_of_elem++]=*first++;
       }
   }
-  
+
   template<class T>
-  void MemArray<T>::pushBack(T elem) throw(INTERP_KERNEL::Exception)
+  void MemArray<T>::pushBack(T elem)
   {
     if(_nb_of_elem>=_nb_of_elem_alloc)
       reserve(_nb_of_elem_alloc>0?2*_nb_of_elem_alloc:1);
     T *pt=getPointer();
     pt[_nb_of_elem++]=elem;
   }
-  
+
   template<class T>
-  T MemArray<T>::popBack() throw(INTERP_KERNEL::Exception)
+  T MemArray<T>::popBack()
   {
     if(_nb_of_elem>0)
       {
@@ -128,12 +129,11 @@ namespace ParaMEDMEM
       }
     throw INTERP_KERNEL::Exception("MemArray::popBack : nothing to pop in array !");
   }
-  
+
   template<class T>
   void MemArray<T>::pack() const
   {
-    if(_nb_of_elem>=0)
-      (const_cast<MemArray<T> * >(this))->reserve(_nb_of_elem);
+    (const_cast<MemArray<T> * >(this))->reserve(_nb_of_elem);
   }
 
   template<class T>
@@ -158,7 +158,7 @@ namespace ParaMEDMEM
       }
     if(pt1==pt2)
       return true;
-    for(int i=0;i<_nb_of_elem;i++)
+    for(std::size_t i=0;i<_nb_of_elem;i++)
       if(pt1[i]-pt2[i]<-prec || (pt1[i]-pt2[i])>prec)
         {
           oss << "The content of data differs at pos #" << i << " of coarse data ! this[i]=" << pt1[i] << " other[i]=" << pt2[i];
@@ -180,7 +180,7 @@ namespace ParaMEDMEM
       {
         if(sl!=0)
           stream << _nb_of_elem/sl << std::endl << "Internal memory facts : " << _nb_of_elem << "/" << _nb_of_elem_alloc;
-       else
+        else
           stream << "Empty Data";
       }
     else
@@ -192,7 +192,7 @@ namespace ParaMEDMEM
       stream << "No data !\n";
     return ret;
   }
-  
+
   /*!
    * \param [in] sl is typically the number of components
    */
@@ -204,8 +204,8 @@ namespace ParaMEDMEM
         const T *data=getConstPointer();
         if(_nb_of_elem!=0 && sl!=0)
           {
-            int nbOfTuples=_nb_of_elem/sl;
-            for(int i=0;i<nbOfTuples;i++)
+            std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
+            for(std::size_t i=0;i<nbOfTuples;i++)
               {
                 stream << "Tuple #" << i << " : ";
                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
@@ -217,7 +217,7 @@ namespace ParaMEDMEM
           stream << "Empty Data\n";
       }
   }
-  
+
   /*!
    * \param [in] sl is typically the number of components
    */
@@ -241,8 +241,8 @@ namespace ParaMEDMEM
       {
         if(_nb_of_elem!=0 && sl!=0)
           {
-            int nbOfTuples=_nb_of_elem/sl;
-            for(int i=0;i<nbOfTuples;i++)
+            std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
+            for(std::size_t i=0;i<nbOfTuples;i++)
               {
                 stream << "|";
                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
@@ -257,36 +257,40 @@ namespace ParaMEDMEM
     else
       stream << "No data !\n";
   }
-  
+
   template<class T>
   void MemArray<T>::fillWithValue(const T& val)
   {
     T *pt=_pointer.getPointer();
     std::fill(pt,pt+_nb_of_elem,val);
   }
-  
+
   template<class T>
   T *MemArray<T>::fromNoInterlace(int nbOfComp) const
   {
+    if(nbOfComp<1)
+      throw INTERP_KERNEL::Exception("MemArray<T>::fromNoInterlace : number of components must be > 0 !");
     const T *pt=_pointer.getConstPointer();
-    int nbOfTuples=_nb_of_elem/nbOfComp;
-    T *ret=new T[_nb_of_elem];
+    std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
+    T *ret=(T*)malloc(_nb_of_elem*sizeof(T));
     T *w=ret;
-    for(int i=0;i<nbOfTuples;i++)
+    for(std::size_t i=0;i<nbOfTuples;i++)
       for(int j=0;j<nbOfComp;j++,w++)
         *w=pt[j*nbOfTuples+i];
     return ret;
   }
-  
+
   template<class T>
   T *MemArray<T>::toNoInterlace(int nbOfComp) const
   {
+    if(nbOfComp<1)
+      throw INTERP_KERNEL::Exception("MemArray<T>::toNoInterlace : number of components must be > 0 !");
     const T *pt=_pointer.getConstPointer();
-    int nbOfTuples=_nb_of_elem/nbOfComp;
-    T *ret=new T[_nb_of_elem];
+    std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
+    T *ret=(T*)malloc(_nb_of_elem*sizeof(T));
     T *w=ret;
     for(int i=0;i<nbOfComp;i++)
-      for(int j=0;j<nbOfTuples;j++,w++)
+      for(std::size_t j=0;j<nbOfTuples;j++,w++)
         *w=pt[j*nbOfComp+i];
     return ret;
   }
@@ -306,108 +310,135 @@ namespace ParaMEDMEM
   }
 
   template<class T>
-  void MemArray<T>::reverse()
+  void MemArray<T>::reverse(int nbOfComp)
   {
+    if(nbOfComp<1)
+      throw INTERP_KERNEL::Exception("MemArray<T>::reverse : only supported with 'this' array with ONE or more than ONE component !");
     T *pt=_pointer.getPointer();
-    std::reverse(pt,pt+_nb_of_elem);
+    if(nbOfComp==1)
+      {
+        std::reverse(pt,pt+_nb_of_elem);
+        return ;
+      }
+    else
+      {
+        T *pt2=pt+_nb_of_elem-nbOfComp;
+        std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
+        for(std::size_t i=0;i<nbOfTuples/2;i++,pt+=nbOfComp,pt2-=nbOfComp)
+          {
+            for(int j=0;j<nbOfComp;j++)
+              std::swap(pt[j],pt2[j]);
+          }
+      }
   }
 
   template<class T>
-  void MemArray<T>::alloc(int nbOfElements) throw(INTERP_KERNEL::Exception)
+  void MemArray<T>::alloc(std::size_t nbOfElements)
   {
     destroy();
-    if(nbOfElements<0)
-      throw INTERP_KERNEL::Exception("MemArray::alloc : request for negative length of data !");
     _nb_of_elem=nbOfElements;
     _nb_of_elem_alloc=nbOfElements;
-    _pointer.setInternal(new T[_nb_of_elem_alloc]);
+    _pointer.setInternal((T*)malloc(_nb_of_elem_alloc*sizeof(T)));
     _ownership=true;
-    _dealloc=CPP_DEALLOC;
+    _dealloc=CDeallocator;
   }
 
   /*!
    * This method performs systematically an allocation of \a newNbOfElements elements in \a this.
    * \a _nb_of_elem and \a _nb_of_elem_alloc will \b NOT be systematically equal (contrary to MemArray<T>::reAlloc method.
-   * So after the call of this method \a _nb_of_elem will be equal tostd::min<int>(_nb_of_elem,newNbOfElements) and \a _nb_of_elem_alloc equal to 
+   * So after the call of this method \a _nb_of_elem will be equal tostd::min<std::size_t>(_nb_of_elem,newNbOfElements) and \a _nb_of_elem_alloc equal to 
    * \a newNbOfElements. This method is typically used to perform a pushBack to avoid systematic allocations-copy-deallocation.
    * So after the call of this method the accessible content is perfectly set.
    * 
    * So this method should not be confused with MemArray<T>::reserve that is close to MemArray<T>::reAlloc but not same.
    */
   template<class T>
-  void MemArray<T>::reserve(int newNbOfElements) throw(INTERP_KERNEL::Exception)
+  void MemArray<T>::reserve(std::size_t newNbOfElements)
   {
-    if(newNbOfElements<0)
-      throw INTERP_KERNEL::Exception("MemArray::reAlloc : request for negative length of data !");
     if(_nb_of_elem_alloc==newNbOfElements)
       return ;
-    T *pointer=new T[newNbOfElements];
-    std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min<int>(_nb_of_elem,newNbOfElements),pointer);
+    T *pointer=(T*)malloc(newNbOfElements*sizeof(T));
+    std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min<std::size_t>(_nb_of_elem,newNbOfElements),pointer);
     if(_ownership)
-      destroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc);//Do not use getPointer because in case of _external
+      DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
     _pointer.setInternal(pointer);
-    _nb_of_elem=std::min<int>(_nb_of_elem,newNbOfElements);
+    _nb_of_elem=std::min<std::size_t>(_nb_of_elem,newNbOfElements);
     _nb_of_elem_alloc=newNbOfElements;
     _ownership=true;
-    _dealloc=CPP_DEALLOC;
+    _dealloc=CDeallocator;
+    _param_for_deallocator=0;
   }
 
   /*!
    * This method performs systematically an allocation of \a newNbOfElements elements in \a this.
-   * \a _nb_of_elem and \a _nb_of_elem_alloc will be equal even if only std::min<int>(_nb_of_elem,newNbOfElements) come from the .
+   * \a _nb_of_elem and \a _nb_of_elem_alloc will be equal even if only std::min<std::size_t>(_nb_of_elem,newNbOfElements) come from the .
    * The remaing part of the new allocated chunk are available but not set previouly !
    * 
    * So this method should not be confused with MemArray<T>::reserve that is close to MemArray<T>::reAlloc but not same.
    */
   template<class T>
-  void MemArray<T>::reAlloc(int newNbOfElements) throw(INTERP_KERNEL::Exception)
+  void MemArray<T>::reAlloc(std::size_t newNbOfElements)
   {
-    if(newNbOfElements<0)
-      throw INTERP_KERNEL::Exception("MemArray::reAlloc : request for negative length of data !");
     if(_nb_of_elem==newNbOfElements)
       return ;
-    T *pointer=new T[newNbOfElements];
-    std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min<int>(_nb_of_elem,newNbOfElements),pointer);
+    T *pointer=(T*)malloc(newNbOfElements*sizeof(T));
+    std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min<std::size_t>(_nb_of_elem,newNbOfElements),pointer);
     if(_ownership)
-      destroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc);//Do not use getPointer because in case of _external
+      DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
     _pointer.setInternal(pointer);
     _nb_of_elem=newNbOfElements;
     _nb_of_elem_alloc=newNbOfElements;
     _ownership=true;
-    _dealloc=CPP_DEALLOC;
+    _dealloc=CDeallocator;
+    _param_for_deallocator=0;
+  }
+
+  template<class T>
+  void MemArray<T>::CPPDeallocator(void *pt, void *param)
+  {
+    delete [] reinterpret_cast<T*>(pt);
   }
 
   template<class T>
-  void MemArray<T>::destroyPointer(T *pt, DeallocType type)
+  void MemArray<T>::CDeallocator(void *pt, void *param)
+  {
+    free(pt);
+  }
+
+  template<class T>
+  typename MemArray<T>::Deallocator MemArray<T>::BuildFromType(DeallocType type)
   {
     switch(type)
-      {
+    {
       case CPP_DEALLOC:
-        {
-          delete [] pt;
-          return ;
-        }
+        return CPPDeallocator;
       case C_DEALLOC:
-        {
-          free(pt);
-          return ;
-        }
+        return CDeallocator;
       default:
-        std::ostringstream stream;
-        stream << "Invalid deallocation requested for pointer " << pt;
-        throw INTERP_KERNEL::Exception(stream.str().c_str());
-      }
+        throw INTERP_KERNEL::Exception("Invalid deallocation requested ! Unrecognized enum DeallocType !");
+    }
+  }
+
+  template<class T>
+  void MemArray<T>::DestroyPointer(T *pt, typename MemArray<T>::Deallocator dealloc, void *param)
+  {
+    if(dealloc)
+      dealloc(pt,param);
   }
 
   template<class T>
   void MemArray<T>::destroy()
   {
     if(_ownership)
-      destroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc);//Do not use getPointer because in case of _external
+      DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
     _pointer.null();
     _ownership=false;
+    _dealloc=NULL;
+    _param_for_deallocator=NULL;
+    _nb_of_elem=0;
+    _nb_of_elem_alloc=0;
   }
-  
+
   template<class T>
   MemArray<T> &MemArray<T>::operator=(const MemArray<T>& other)
   {