//# Copy.h: Copy objects from one C-style array to another. //# Copyright (C) 1994-1997,1999-2002,2005,2015 //# Associated Universities, Inc. Washington DC, USA. //# National Astronomical Observatory of Japan //# 2-21-1, Osawa, Mitaka, Tokyo, 181-8588, Japan. //# //# This library is free software; you can redistribute it and/or modify it //# under the terms of the GNU Library General Public License as published by //# the Free Software Foundation; either version 2 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 MERCHANTABILITY or //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public //# License for more details. //# //# You should have received a copy of the GNU Library General Public License //# along with this library; if not, write to the Free Software Foundation, //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning AIPS++ should be addressed as follows: //# Internet email: aips2-request@nrao.edu. //# Postal address: AIPS++ Project Office //# National Radio Astronomy Observatory //# 520 Edgemont Road //# Charlottesville, VA 22903-2475 USA //# //# $Id$ #ifndef CASA_COPY_H #define CASA_COPY_H //# Includes #include #include #include namespace casacore { //# NAMESPACE CASACORE - BEGIN // // Copy objects from one C-style array to another. // // // // // // Objset is used to fill a C-style array of objects. // // Objcopy and objmove are used to copy objects from one place to // another. Optionally a stride can be supplied. // // The functions are equivalent to C's memcpy and // memmove. // When possible C++ standard library functions are used to implement them // // Similar to memcpy and memmove, the difference between objcopy // and objmove is that objmove takes account of an overlap of source and // destination. In general, objcopy is slighty (but only slighty) faster. // // // Setting and copying arrays of built-in types: // // // Create int array of 4 elements // size_t size=4; // int* ia = new int[size]; // // Initialize all elements to value 99 // objset(ia, 99, size); // // Change all odd elements to 66 -> [99 66 99 66] // objset(ia+1, 66, 5, 2); // // // Create another 4-element int array // int* ia2 = new int[size]; // // Copy array ia into array ia2 -> [99 66 99 66] // objmove(ia2, ia, size); // // Copy the even elements of ia to the odd elements of ia2 // // -> [99 99 99 99] // objcopy(ia2+1, ia, size/2, 2, 2); // // // Setting and copying arrays of a randomly chosen type: // // // Create 4-element array of 3-element Block objects // size_t size=4; // Block* ta = new Block[size]; // Block set(3); // // Initialize the array -> [[123][123][123][123]] // set[0] = 1; set[1] = 2; set[2] = 3; // objset(ta, set, size); // // Change odd Blocks to [777]-> [[123][777][123][777]] // set[0] = set[1] = set[2] = 7; // objset(ta + 1, set, size/2, 2); // // // Create another Block array // Block* ta2 = new Block[size]; // // Copy the even elements of ta to the first elements of ta2 // // -> [[123][123]...] // objcopy(ta2, ta, size/2, 1, 2); // // // // Throw the various AipsErrors when incorrect arguments used void objthrowmv1(const void *to, const void *from, const size_t n); void objthrowmv2(const void *to, const void *from, const size_t n, const size_t toStride, const size_t fromStride); void objthrowcp1(const void *to, const void *from, const size_t n); void objthrowcp2(const void *to, const void *from, const size_t n, const size_t toStride, const size_t fromStride); void objthrowfl1(const void *to, const size_t n); void objthrowfl2(const void *to, const size_t n, const size_t toStride); // // Test routines // // Test on how to handle the overlap in move void objtestmv(size_t &nLeft, size_t &startLeft, size_t &startRight, const void *to, const void *from, const size_t n, const size_t toStride, const size_t fromStride, const void *toPn, const void *fromPn, const size_t fromMto, const size_t toMfrom); // // Copy methods // // The general function to copy n objects from one place // to another if overlap between to and from fields // is possible. Strides may be specified, i.e. you may copy from every // fromStride-th position into every toStride-th // one. // // The function will call std::copy() when possible. // Objmove works correctly if the source and destination overlap in any way. // // An exception will be thrown if the source or the destination does not // exist (and n is non-zero) or if the strides are non-positive. // //
  • AipsError // // // template void objmove(T* to, const T* from, size_t n) { objthrowmv1(to,from,n); (to= from+n) ? std::copy(from,from+n,to) : std::copy_backward(from,from+n,to+n); } template void objmove(T* to, const T* from, size_t n, size_t toStride, size_t fromStride) { if (!n) return; objthrowmv2(to,from,n,toStride,fromStride); if (toStride*fromStride == 1) { objmove(to, from, n); return; } size_t nLeft, startLeft, startRight; size_t fromMto=0; size_t toMfrom=0; if (toStride > fromStride && from > to) fromMto = (from-to)/(toStride-fromStride); else if (toStride < fromStride && from < to) toMfrom = (to-from)/(fromStride-toStride); objtestmv(nLeft, startLeft, startRight, to, from, n, toStride, fromStride, to+n*toStride, from+n*fromStride, fromMto, toMfrom); n -= nLeft; if (nLeft) { const T* fromPtr = from + startLeft*fromStride; T* toPtr = to + startLeft*toStride; while (nLeft--) { *toPtr = *fromPtr; fromPtr += fromStride; toPtr += toStride; }; }; // Do the moves from the right. if (n) { const T* fromPtr = from + startRight*fromStride; T* toPtr = to + startRight*toStride; while (n--) { fromPtr -= fromStride; toPtr -= toStride; *toPtr = *fromPtr; }; }; } // // The non-general function to copy n objects from one place // to another. Strides may be specified, i.e. you may copy from every // fromStride-th position into every toStride-th // one. // // Objcopy/objcopyctor does not take an overlap of source and destination into account. // Objmove should be used if that is an issue. // // Objcopyctor copy objects from from by calling copy constructor // on each element in to. // // An exception will be thrown if the source or the destination does not // exist or if the strides are non-positive. // //
  • AipsError // // // template void objcopy(T* to, const T* from, size_t n) { objthrowcp1(to,from,n); std::copy(from, from+n, to); } template void objcopy(T* to, const T* from, size_t n, size_t toStride, size_t fromStride) { objthrowcp2(to,from,n,toStride,fromStride); while (n--) { *to = *from; to += toStride; from += fromStride; } } template void objcopyctor(T* to, const T* from, size_t n) { objthrowcp1(to, from, n); size_t i; try { for (i = 0; i < n; ++i) { ::new (&to[i]) T(from[i]); } } catch (...) { while (i > 0) { // roll back to[--i].~T(); } throw; } } template void objcopyctor(T* to, const T* from, size_t n, size_t toStride, size_t fromStride) { objthrowcp2(to, from, n, toStride, fromStride); size_t i = 0; try { for (i = 0; i < n; ++i) { ::new (to) T(*from); to += toStride; from += fromStride; } } catch (...) { while (i > 0) { // roll back --i; to -= toStride; to->~T(); } throw; } } // // Fill n elements of an array of objects with the given // value, optionally with a stride. Note that the fillValue is passed // by value. // // An exception will be thrown if the destination array does not exist // or if the stride is non-positive. // // //
  • AipsError // // // template void objset(T* to, const T fillValue, size_t n) { objthrowfl1(to,n); std::fill_n(to, n, fillValue); } template void objset(T* to, const T fillValue, size_t n, size_t toStride) { objthrowfl2(to,n,toStride); while (n--){*to = fillValue; to += toStride; }; } // // } //# NAMESPACE CASACORE - END #ifndef CASACORE_NO_AUTO_TEMPLATES #include #endif //# CASACORE_NO_AUTO_TEMPLATES #endif