Copy.h

Go to the documentation of this file.
00001 //# Copy.h: Copy objects from one C-style array to another.
00002 //# Copyright (C) 1994-1997,1999-2002,2005,2015
00003 //# Associated Universities, Inc. Washington DC, USA.
00004 //# National Astronomical Observatory of Japan
00005 //# 2-21-1, Osawa, Mitaka, Tokyo, 181-8588, Japan.
00006 //#
00007 //# This library is free software; you can redistribute it and/or modify it
00008 //# under the terms of the GNU Library General Public License as published by
00009 //# the Free Software Foundation; either version 2 of the License, or (at your
00010 //# option) any later version.
00011 //#
00012 //# This library is distributed in the hope that it will be useful, but WITHOUT
00013 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00015 //# License for more details.
00016 //#
00017 //# You should have received a copy of the GNU Library General Public License
00018 //# along with this library; if not, write to the Free Software Foundation,
00019 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00020 //#
00021 //# Correspondence concerning AIPS++ should be addressed as follows:
00022 //#        Internet email: aips2-request@nrao.edu.
00023 //#        Postal address: AIPS++ Project Office
00024 //#                        National Radio Astronomy Observatory
00025 //#                        520 Edgemont Road
00026 //#                        Charlottesville, VA 22903-2475 USA
00027 //#
00028 //# $Id$
00029 
00030 #ifndef CASA_COPY_H
00031 #define CASA_COPY_H
00032 
00033 //# Includes
00034 #include <casacore/casa/aips.h>
00035 #include <casacore/casa/BasicSL/Complex.h>
00036 #include <algorithm>
00037 
00038 namespace casacore { //# NAMESPACE CASACORE - BEGIN
00039 
00040   // <summary>
00041   // Copy objects from one C-style array to another.
00042   // </summary>
00043 
00044   // <use visibility=export>
00045   // <reviewed reviewer="Friso Olnon" date="1995/03/14" tests="tCopy" demos="">
00046   // </reviewed>
00047 
00048   // <synopsis>
00049   // Objset is used to fill a C-style array of objects.
00050   //
00051   // Objcopy and objmove are used to copy objects from one place to
00052   // another. Optionally a stride can be supplied.
00053   //
00054   // The functions are equivalent to C's <src>memcpy</src> and
00055   // <src>memmove</src>.
00056   // When possible C++ standard library functions are used to implement them
00057   //
00058   // Similar to memcpy and memmove, the difference between objcopy
00059   // and objmove is that objmove takes account of an overlap of source and
00060   // destination. In general, objcopy is slighty (but only slighty) faster.
00061   // </synopsis>
00062 
00063   // <example>
00064   // Setting and copying arrays of built-in types:
00065   // <srcblock>
00066   // // Create int array of 4 elements
00067   // size_t size=4;
00068   // int* ia = new int[size];
00069   // // Initialize all elements to value 99
00070   // objset(ia, 99, size);
00071   // // Change all odd elements to 66 -> [99 66 99 66]
00072   // objset(ia+1, 66, 5, 2);
00073   //
00074   // // Create another 4-element int array
00075   // int* ia2 = new int[size];
00076   // // Copy array ia into array ia2 -> [99 66 99 66]
00077   // objmove(ia2, ia, size);
00078   // // Copy the even elements of ia to the odd elements of ia2
00079   // //                              -> [99 99 99 99]
00080   // objcopy(ia2+1, ia, size/2, 2, 2);
00081   // </srcblock>
00082   //
00083   // Setting and copying arrays of a randomly chosen type:
00084   // <srcblock>
00085   // // Create 4-element array of 3-element Block<int> objects 
00086   // size_t size=4;
00087   // Block<int>* ta = new Block<int>[size];
00088   // Block<int> set(3);
00089   // // Initialize the array -> [[123][123][123][123]]
00090   // set[0] = 1; set[1] = 2; set[2] = 3;
00091   // objset(ta, set, size);
00092   // // Change odd Blocks to [777]-> [[123][777][123][777]]
00093   // set[0] = set[1] = set[2] = 7;
00094   // objset(ta + 1, set, size/2, 2);
00095   //
00096   // // Create another Block<int> array 
00097   // Block<int>* ta2 = new Block<int>[size];
00098   // // Copy the even elements of ta to the first elements of ta2
00099   // //                      -> [[123][123]...]
00100   // objcopy(ta2, ta, size/2, 1, 2);
00101   // </srcblock>
00102   // </example>
00103   
00104   // <group name=throw>
00105   // Throw the various AipsErrors when incorrect arguments used
00106   void objthrowmv1(const void *to, const void *from, const size_t n);
00107   void objthrowmv2(const void *to, const void *from, const size_t n,
00108                    const size_t toStride, const size_t fromStride);
00109   void objthrowcp1(const void *to, const void *from, const size_t n);
00110   void objthrowcp2(const void *to, const void *from, const size_t n,
00111                    const size_t toStride, const size_t fromStride);
00112   void objthrowfl1(const void *to, const size_t n);
00113   void objthrowfl2(const void *to, const size_t n,
00114                    const size_t toStride);
00115   // </group>
00116   
00117   // <summary> Test routines </summary>
00118   // <group name=test>
00119   // Test on how to handle the overlap in move
00120   void objtestmv(size_t &nLeft, size_t &startLeft, size_t &startRight,
00121                  const void *to, const void *from, const size_t n,
00122                  const size_t toStride, const size_t fromStride,
00123                  const void *toPn, const void *fromPn,
00124                  const size_t fromMto, const size_t toMfrom);
00125   // </group>
00126   
00127   // <summary> Copy methods </summary>
00128   // <group name=copy>
00129   // The general function to copy <src>n</src> objects from one place
00130   // to another if overlap between <src>to</src> and <src>from</src> fields
00131   // is possible. Strides may be specified, i.e. you may copy from every
00132   // <src>fromStride</src>-th position into every <src>toStride</src>-th
00133   // one.
00134   //
00135   // The function will call <src>std::copy()</src> when possible.
00136   // Objmove works correctly if the source and destination overlap in any way.
00137   //
00138   // An exception will be thrown if the source or the destination does not
00139   // exist (and <em>n</em> is non-zero) or if the strides are non-positive.
00140   // <thrown>
00141   //  <li> AipsError
00142   // </thrown>
00143   //
00144   // <group>
00145   template<class T> void objmove(T* to, const T* from, size_t n) {
00146     objthrowmv1(to,from,n);
00147     (to<from || to >= from+n) ? std::copy(from,from+n,to)
00148       : std::copy_backward(from,from+n,to+n); }
00149   template<class T> void objmove(T* to, const T* from, size_t n,
00150                                  size_t toStride, size_t fromStride) {
00151     if (!n) return;
00152     objthrowmv2(to,from,n,toStride,fromStride);
00153     if (toStride*fromStride == 1) { objmove(to, from, n);
00154     return; }
00155     size_t nLeft, startLeft, startRight;
00156     size_t fromMto=0; size_t toMfrom=0;
00157     if (toStride > fromStride && from > to)
00158       fromMto = (from-to)/(toStride-fromStride);
00159     else if (toStride < fromStride && from < to)
00160       toMfrom = (to-from)/(fromStride-toStride);
00161     objtestmv(nLeft, startLeft, startRight, to, from, n,
00162               toStride, fromStride, to+n*toStride, from+n*fromStride,
00163               fromMto, toMfrom);
00164     n -= nLeft;
00165     if (nLeft) {
00166       const T* fromPtr = from + startLeft*fromStride;
00167       T* toPtr = to + startLeft*toStride;
00168       while (nLeft--) { *toPtr = *fromPtr;
00169       fromPtr += fromStride;
00170       toPtr += toStride; }; };
00171     // Do the moves from the right.
00172     if (n) {
00173       const T* fromPtr = from + startRight*fromStride;
00174       T* toPtr = to + startRight*toStride;
00175       while (n--) { fromPtr -= fromStride; toPtr -= toStride;
00176       *toPtr = *fromPtr; }; };
00177   }
00178   // </group> 
00179   
00180   // The non-general function to copy <src>n</src> objects from one place
00181   // to another. Strides may be specified, i.e. you may copy from every
00182   // <src>fromStride</src>-th position into every <src>toStride</src>-th
00183   // one.
00184   //
00185   // Objcopy/objcopyctor does not take an overlap of source and destination into account.
00186   // Objmove should be used if that is an issue.
00187   //
00188   // Objcopyctor copy objects from <src>from</src> by calling copy constructor
00189   // on each element in <src>to</src>.
00190   //
00191   // An exception will be thrown if the source or the destination does not
00192   // exist or if the strides are non-positive.
00193   // <thrown>
00194   //  <li> AipsError
00195   // </thrown>
00196   //
00197   // <group>
00198   template<class T> void objcopy(T* to, const T* from, size_t n) {
00199     objthrowcp1(to,from,n); std::copy(from, from+n, to); }
00200   template<class T> void objcopy(T* to, const T* from, size_t n,
00201                                  size_t toStride, size_t fromStride) {
00202     objthrowcp2(to,from,n,toStride,fromStride); while (n--) {
00203       *to = *from; to += toStride; from += fromStride; } }
00204 
00205   template<class T> void objcopyctor(T* to, const T* from, size_t n) {
00206     objthrowcp1(to, from, n);
00207     size_t i;
00208     try {
00209         for (i = 0; i < n; ++i) {
00210             ::new (&to[i]) T(from[i]);
00211         }
00212     } catch (...) {
00213         while (i > 0) { // roll back
00214             to[--i].~T();
00215         }
00216         throw;
00217     }
00218   }
00219   template<class T> void objcopyctor(T* to, const T* from, size_t n,
00220                                  size_t toStride, size_t fromStride) {
00221     objthrowcp2(to, from, n, toStride, fromStride);
00222     size_t i = 0;
00223     try {
00224         for (i = 0; i < n; ++i) {
00225             ::new (to) T(*from);
00226             to += toStride;
00227             from += fromStride;
00228         }
00229     } catch (...) {
00230         while (i > 0) { // roll back
00231             --i;
00232             to -= toStride;
00233             to->~T();
00234         }
00235         throw;
00236     }
00237   }
00238   // </group>
00239   
00240   // Fill <src>n</src> elements of an array of objects with the given
00241   // value, optionally with a stride. Note that the fillValue is passed
00242   // by value.
00243   //
00244   // An exception will be thrown if the destination array does not exist
00245   // or if the stride is non-positive.
00246   //
00247   // <thrown>
00248   //  <li> AipsError
00249   // </thrown>
00250   //
00251   // <group>
00252   template<class T> void objset(T* to, const T fillValue, size_t n) {
00253     objthrowfl1(to,n); std::fill_n(to, n, fillValue); }
00254   
00255   template<class T> void objset(T* to, const T fillValue, size_t n,
00256                                 size_t toStride) {
00257     objthrowfl2(to,n,toStride); 
00258     while (n--){*to = fillValue; to += toStride; }; }
00259   
00260   // </group>
00261   
00262   // </group>
00263   
00264 } //# NAMESPACE CASACORE - END
00265 
00266 #ifndef CASACORE_NO_AUTO_TEMPLATES
00267 #include <casacore/casa/Utilities/Copy.tcc>
00268 #endif //# CASACORE_NO_AUTO_TEMPLATES
00269 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 31 Aug 2016 for casa by  doxygen 1.6.1