casacore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Copy.h
Go to the documentation of this file.
1 //# Copy.h: Copy objects from one C-style array to another.
2 //# Copyright (C) 1994-1997,1999-2002,2005,2015
3 //# Associated Universities, Inc. Washington DC, USA.
4 //# National Astronomical Observatory of Japan
5 //# 2-21-1, Osawa, Mitaka, Tokyo, 181-8588, Japan.
6 //#
7 //# This library is free software; you can redistribute it and/or modify it
8 //# under the terms of the GNU Library General Public License as published by
9 //# the Free Software Foundation; either version 2 of the License, or (at your
10 //# option) any later version.
11 //#
12 //# This library is distributed in the hope that it will be useful, but WITHOUT
13 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
15 //# License for more details.
16 //#
17 //# You should have received a copy of the GNU Library General Public License
18 //# along with this library; if not, write to the Free Software Foundation,
19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
20 //#
21 //# Correspondence concerning AIPS++ should be addressed as follows:
22 //# Internet email: aips2-request@nrao.edu.
23 //# Postal address: AIPS++ Project Office
24 //# National Radio Astronomy Observatory
25 //# 520 Edgemont Road
26 //# Charlottesville, VA 22903-2475 USA
27 //#
28 //# $Id$
29 
30 #ifndef CASA_COPY_H
31 #define CASA_COPY_H
32 
33 //# Includes
34 #include <casacore/casa/aips.h>
36 #include <algorithm>
37 
38 namespace casacore { //# NAMESPACE CASACORE - BEGIN
39 
40  // <summary>
41  // Copy objects from one C-style array to another.
42  // </summary>
43 
44  // <use visibility=export>
45  // <reviewed reviewer="Friso Olnon" date="1995/03/14" tests="tCopy" demos="">
46  // </reviewed>
47 
48  // <synopsis>
49  // Objset is used to fill a C-style array of objects.
50  //
51  // Objcopy and objmove are used to copy objects from one place to
52  // another. Optionally a stride can be supplied.
53  //
54  // The functions are equivalent to C's <src>memcpy</src> and
55  // <src>memmove</src>.
56  // When possible C++ standard library functions are used to implement them
57  //
58  // Similar to memcpy and memmove, the difference between objcopy
59  // and objmove is that objmove takes account of an overlap of source and
60  // destination. In general, objcopy is slighty (but only slighty) faster.
61  // </synopsis>
62 
63  // <example>
64  // Setting and copying arrays of built-in types:
65  // <srcblock>
66  // // Create int array of 4 elements
67  // size_t size=4;
68  // int* ia = new int[size];
69  // // Initialize all elements to value 99
70  // objset(ia, 99, size);
71  // // Change all odd elements to 66 -> [99 66 99 66]
72  // objset(ia+1, 66, 5, 2);
73  //
74  // // Create another 4-element int array
75  // int* ia2 = new int[size];
76  // // Copy array ia into array ia2 -> [99 66 99 66]
77  // objmove(ia2, ia, size);
78  // // Copy the even elements of ia to the odd elements of ia2
79  // // -> [99 99 99 99]
80  // objcopy(ia2+1, ia, size/2, 2, 2);
81  // </srcblock>
82  //
83  // Setting and copying arrays of a randomly chosen type:
84  // <srcblock>
85  // // Create 4-element array of 3-element Block<int> objects
86  // size_t size=4;
87  // Block<int>* ta = new Block<int>[size];
88  // Block<int> set(3);
89  // // Initialize the array -> [[123][123][123][123]]
90  // set[0] = 1; set[1] = 2; set[2] = 3;
91  // objset(ta, set, size);
92  // // Change odd Blocks to [777]-> [[123][777][123][777]]
93  // set[0] = set[1] = set[2] = 7;
94  // objset(ta + 1, set, size/2, 2);
95  //
96  // // Create another Block<int> array
97  // Block<int>* ta2 = new Block<int>[size];
98  // // Copy the even elements of ta to the first elements of ta2
99  // // -> [[123][123]...]
100  // objcopy(ta2, ta, size/2, 1, 2);
101  // </srcblock>
102  // </example>
103 
104  // <group name=throw>
105  // Throw the various AipsErrors when incorrect arguments used
106  void objthrowmv1(const void *to, const void *from, const size_t n);
107  void objthrowmv2(const void *to, const void *from, const size_t n,
108  const size_t toStride, const size_t fromStride);
109  void objthrowcp1(const void *to, const void *from, const size_t n);
110  void objthrowcp2(const void *to, const void *from, const size_t n,
111  const size_t toStride, const size_t fromStride);
112  void objthrowfl1(const void *to, const size_t n);
113  void objthrowfl2(const void *to, const size_t n,
114  const size_t toStride);
115  // </group>
116 
117  // <summary> Test routines </summary>
118  // <group name=test>
119  // Test on how to handle the overlap in move
120  void objtestmv(size_t &nLeft, size_t &startLeft, size_t &startRight,
121  const void *to, const void *from, const size_t n,
122  const size_t toStride, const size_t fromStride,
123  const void *toPn, const void *fromPn,
124  const size_t fromMto, const size_t toMfrom);
125  // </group>
126 
127  // <summary> Copy methods </summary>
128  // <group name=copy>
129  // The general function to copy <src>n</src> objects from one place
130  // to another if overlap between <src>to</src> and <src>from</src> fields
131  // is possible. Strides may be specified, i.e. you may copy from every
132  // <src>fromStride</src>-th position into every <src>toStride</src>-th
133  // one.
134  //
135  // The function will call <src>std::copy()</src> when possible.
136  // Objmove works correctly if the source and destination overlap in any way.
137  //
138  // An exception will be thrown if the source or the destination does not
139  // exist (and <em>n</em> is non-zero) or if the strides are non-positive.
140  // <thrown>
141  // <li> AipsError
142  // </thrown>
143  //
144  // <group>
145  template<class T> void objmove(T* to, const T* from, size_t n) {
146  objthrowmv1(to,from,n);
147  (to<from || to >= from+n) ? std::copy(from,from+n,to)
148  : std::copy_backward(from,from+n,to+n); }
149  template<class T> void objmove(T* to, const T* from, size_t n,
150  size_t toStride, size_t fromStride) {
151  if (!n) return;
152  objthrowmv2(to,from,n,toStride,fromStride);
153  if (toStride*fromStride == 1) { objmove(to, from, n);
154  return; }
155  size_t nLeft, startLeft, startRight;
156  size_t fromMto=0; size_t toMfrom=0;
157  if (toStride > fromStride && from > to)
158  fromMto = (from-to)/(toStride-fromStride);
159  else if (toStride < fromStride && from < to)
160  toMfrom = (to-from)/(fromStride-toStride);
161  objtestmv(nLeft, startLeft, startRight, to, from, n,
162  toStride, fromStride, to+n*toStride, from+n*fromStride,
163  fromMto, toMfrom);
164  n -= nLeft;
165  if (nLeft) {
166  const T* fromPtr = from + startLeft*fromStride;
167  T* toPtr = to + startLeft*toStride;
168  while (nLeft--) { *toPtr = *fromPtr;
169  fromPtr += fromStride;
170  toPtr += toStride; }; };
171  // Do the moves from the right.
172  if (n) {
173  const T* fromPtr = from + startRight*fromStride;
174  T* toPtr = to + startRight*toStride;
175  while (n--) { fromPtr -= fromStride; toPtr -= toStride;
176  *toPtr = *fromPtr; }; };
177  }
178  // </group>
179 
180  // The non-general function to copy <src>n</src> objects from one place
181  // to another. Strides may be specified, i.e. you may copy from every
182  // <src>fromStride</src>-th position into every <src>toStride</src>-th
183  // one.
184  //
185  // Objcopy/objcopyctor does not take an overlap of source and destination into account.
186  // Objmove should be used if that is an issue.
187  //
188  // Objcopyctor copy objects from <src>from</src> by calling copy constructor
189  // on each element in <src>to</src>.
190  //
191  // An exception will be thrown if the source or the destination does not
192  // exist or if the strides are non-positive.
193  // <thrown>
194  // <li> AipsError
195  // </thrown>
196  //
197  // <group>
198  template<class T> void objcopy(T* to, const T* from, size_t n) {
199  objthrowcp1(to,from,n); std::copy(from, from+n, to); }
200  template<class T> void objcopy(T* to, const T* from, size_t n,
201  size_t toStride, size_t fromStride) {
202  objthrowcp2(to,from,n,toStride,fromStride); while (n--) {
203  *to = *from; to += toStride; from += fromStride; } }
204 
205  template<class T> void objcopyctor(T* to, const T* from, size_t n) {
206  objthrowcp1(to, from, n);
207  size_t i;
208  try {
209  for (i = 0; i < n; ++i) {
210  ::new (&to[i]) T(from[i]);
211  }
212  } catch (...) {
213  while (i > 0) { // roll back
214  to[--i].~T();
215  }
216  throw;
217  }
218  }
219  template<class T> void objcopyctor(T* to, const T* from, size_t n,
220  size_t toStride, size_t fromStride) {
221  objthrowcp2(to, from, n, toStride, fromStride);
222  size_t i = 0;
223  try {
224  for (i = 0; i < n; ++i) {
225  ::new (to) T(*from);
226  to += toStride;
227  from += fromStride;
228  }
229  } catch (...) {
230  while (i > 0) { // roll back
231  --i;
232  to -= toStride;
233  to->~T();
234  }
235  throw;
236  }
237  }
238  // </group>
239 
240  // Fill <src>n</src> elements of an array of objects with the given
241  // value, optionally with a stride. Note that the fillValue is passed
242  // by value.
243  //
244  // An exception will be thrown if the destination array does not exist
245  // or if the stride is non-positive.
246  //
247  // <thrown>
248  // <li> AipsError
249  // </thrown>
250  //
251  // <group>
252  template<class T> void objset(T* to, const T fillValue, size_t n) {
253  objthrowfl1(to,n); std::fill_n(to, n, fillValue); }
254 
255  template<class T> void objset(T* to, const T fillValue, size_t n,
256  size_t toStride) {
257  objthrowfl2(to,n,toStride);
258  while (n--){*to = fillValue; to += toStride; }; }
259 
260  // </group>
261 
262  // </group>
263 
264 } //# NAMESPACE CASACORE - END
265 
266 #ifndef CASACORE_NO_AUTO_TEMPLATES
267 #include <casacore/casa/Utilities/Copy.tcc>
268 #endif //# CASACORE_NO_AUTO_TEMPLATES
269 #endif
void objcopyctor(T *to, const T *from, size_t n, size_t toStride, size_t fromStride)
Definition: Copy.h:219
StatsData< AccumType > copy(const StatsData< AccumType > &stats)
void objmove(T *to, const T *from, size_t n)
The general function to copy n objects from one place to another if overlap between to and from field...
Definition: Copy.h:145
void objcopy(T *to, const T *from, size_t n)
The non-general function to copy &lt;tt&gt;n&lt;/tt&gt; objects from one place to another.
Definition: Copy.h:198
void objcopy(T *to, const T *from, size_t n, size_t toStride, size_t fromStride)
Definition: Copy.h:200
void objcopyctor(T *to, const T *from, size_t n)
Definition: Copy.h:205
void objset(T *to, const T fillValue, size_t n)
Fill &lt;tt&gt;n&lt;/tt&gt; elements of an array of objects with the given value, optionally with a stride...
Definition: Copy.h:252
void objmove(T *to, const T *from, size_t n, size_t toStride, size_t fromStride)
Definition: Copy.h:149
void objset(T *to, const T fillValue, size_t n, size_t toStride)
Definition: Copy.h:255