Salome HOME
Get relevant changes from V7_dev branch (copyright update, adm files etc)
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingMemArrayChar.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingMemArray.txx"
22 #include "MCAuto.hxx"
23
24 #include <set>
25 #include <cmath>
26 #include <limits>
27 #include <numeric>
28 #include <algorithm>
29 #include <functional>
30
31 using namespace MEDCoupling;
32
33 /*!
34  * Checks if raw data is allocated. Read more on the raw data
35  * in \ref MEDCouplingArrayBasicsTuplesAndCompo "DataArrays infos" for more information.
36  *  \return bool - \a true if the raw data is allocated, \a false else.
37  */
38 bool DataArrayChar::isAllocated() const
39 {
40   return getConstPointer()!=0;
41 }
42
43 /*!
44  * Checks if raw data is allocated and throws an exception if it is not the case.
45  *  \throw If the raw data is not allocated.
46  */
47 void DataArrayChar::checkAllocated() const
48 {
49   if(!isAllocated())
50     throw INTERP_KERNEL::Exception("DataArrayChar::checkAllocated : Array is defined but not allocated ! Call alloc or setValues method first !");
51 }
52
53 /*!
54  * This method desallocated \a this without modification of informations relative to the components.
55  * After call of this method, DataArrayChar::isAllocated will return false.
56  * If \a this is already not allocated, \a this is let unchanged.
57  */
58 void DataArrayChar::desallocate()
59 {
60   _mem.destroy();
61 }
62
63 std::size_t DataArrayChar::getHeapMemorySizeWithoutChildren() const
64 {
65   std::size_t sz(_mem.getNbOfElemAllocated());
66   return DataArray::getHeapMemorySizeWithoutChildren()+sz;
67 }
68
69 /*!
70  * Returns an integer value characterizing \a this array, which is useful for a quick
71  * comparison of many instances of DataArrayInt.
72  *  \return int - the hash value.
73  *  \throw If \a this is not allocated.
74  */
75 int DataArrayChar::getHashCode() const
76 {
77   checkAllocated();
78   std::size_t nbOfElems=getNbOfElems();
79   int ret=nbOfElems*65536;
80   int delta=3;
81   if(nbOfElems>48)
82     delta=nbOfElems/8;
83   int ret0=0;
84   const char *pt=begin();
85   for(std::size_t i=0;i<nbOfElems;i+=delta)
86     ret0+=pt[i];
87   return ret+ret0;
88 }
89
90 /*!
91  * Checks the number of tuples.
92  *  \return bool - \a true if getNumberOfTuples() == 0, \a false else.
93  *  \throw If \a this is not allocated.
94  */
95 bool DataArrayChar::empty() const
96 {
97   checkAllocated();
98   return getNumberOfTuples()==0;
99 }
100
101 /*!
102  * Copies all the data from another DataArrayChar. For more info see
103  * \ref MEDCouplingArrayBasicsCopyDeepAssign.
104  *  \param [in] other - another instance of DataArrayChar to copy data from.
105  *  \throw If the \a other is not allocated.
106  */
107 void DataArrayChar::deepCopyFrom(const DataArrayChar& other)
108 {
109   other.checkAllocated();
110   int nbOfTuples=other.getNumberOfTuples();
111   int nbOfComp=other.getNumberOfComponents();
112   allocIfNecessary(nbOfTuples,nbOfComp);
113   std::size_t nbOfElems=(std::size_t)nbOfTuples*nbOfComp;
114   char *pt=getPointer();
115   const char *ptI=other.getConstPointer();
116   for(std::size_t i=0;i<nbOfElems;i++)
117     pt[i]=ptI[i];
118   copyStringInfoFrom(other);
119 }
120
121 /*!
122  * This method reserve nbOfElems elements in memory ( nbOfElems*4 bytes ) \b without impacting the number of tuples in \a this.
123  * If \a this has already been allocated, this method checks that \a this has only one component. If not an INTERP_KERNEL::Exception will be thrown.
124  * If \a this has not already been allocated, number of components is set to one.
125  * This method allows to reduce number of reallocations on invokation of DataArrayChar::pushBackSilent and DataArrayChar::pushBackValsSilent on \a this.
126  * 
127  * \sa DataArrayChar::pack, DataArrayChar::pushBackSilent, DataArrayChar::pushBackValsSilent
128  */
129 void DataArrayChar::reserve(std::size_t nbOfElems)
130 {
131   int nbCompo=getNumberOfComponents();
132   if(nbCompo==1)
133     {
134       _mem.reserve(nbOfElems);
135     }
136   else if(nbCompo==0)
137     {
138       _mem.reserve(nbOfElems);
139       _info_on_compo.resize(1);
140     }
141   else
142     throw INTERP_KERNEL::Exception("DataArrayChar::reserve : not available for DataArrayChar with number of components different than 1 !");
143 }
144
145 /*!
146  * This method adds at the end of \a this the single value \a val. This method do \b not update its time label to avoid useless incrementation
147  * of counter. So the caller is expected to call TimeLabel::declareAsNew on \a this at the end of the push session.
148  *
149  * \param [in] val the value to be added in \a this
150  * \throw If \a this has already been allocated with number of components different from one.
151  * \sa DataArrayChar::pushBackValsSilent
152  */
153 void DataArrayChar::pushBackSilent(char val)
154 {
155   int nbCompo=getNumberOfComponents();
156   if(nbCompo==1)
157     _mem.pushBack(val);
158   else if(nbCompo==0)
159     {
160       _info_on_compo.resize(1);
161       _mem.pushBack(val);
162     }
163   else
164     throw INTERP_KERNEL::Exception("DataArrayChar::pushBackSilent : not available for DataArrayChar with number of components different than 1 !");
165 }
166
167 /*!
168  * This method adds at the end of \a this a serie of values [\c valsBg,\c valsEnd). This method do \b not update its time label to avoid useless incrementation
169  * of counter. So the caller is expected to call TimeLabel::declareAsNew on \a this at the end of the push session.
170  *
171  *  \param [in] valsBg - an array of values to push at the end of \this.
172  *  \param [in] valsEnd - specifies the end of the array \a valsBg, so that
173  *              the last value of \a valsBg is \a valsEnd[ -1 ].
174  * \throw If \a this has already been allocated with number of components different from one.
175  * \sa DataArrayChar::pushBackSilent
176  */
177 void DataArrayChar::pushBackValsSilent(const char *valsBg, const char *valsEnd)
178 {
179   int nbCompo=getNumberOfComponents();
180   if(nbCompo==1)
181     _mem.insertAtTheEnd(valsBg,valsEnd);
182   else if(nbCompo==0)
183     {
184       _info_on_compo.resize(1);
185       _mem.insertAtTheEnd(valsBg,valsEnd);
186     }
187   else
188     throw INTERP_KERNEL::Exception("DataArrayChar::pushBackValsSilent : not available for DataArrayChar with number of components different than 1 !");
189 }
190
191 /*!
192  * This method returns silently ( without updating time label in \a this ) the last value, if any and suppress it.
193  * \throw If \a this is already empty.
194  * \throw If \a this has number of components different from one.
195  */
196 char DataArrayChar::popBackSilent()
197 {
198   if(getNumberOfComponents()==1)
199     return _mem.popBack();
200   else
201     throw INTERP_KERNEL::Exception("DataArrayChar::popBackSilent : not available for DataArrayChar with number of components different than 1 !");
202 }
203
204 /*!
205  * This method \b do \b not modify content of \a this. It only modify its memory footprint if the allocated memory is to high regarding real data to store.
206  *
207  * \sa DataArrayChar::getHeapMemorySizeWithoutChildren, DataArrayChar::reserve
208  */
209 void DataArrayChar::pack() const
210 {
211   _mem.pack();
212 }
213
214 /*!
215  * Allocates the raw data in memory. If exactly as same memory as needed already
216  * allocated, it is not re-allocated.
217  *  \param [in] nbOfTuple - number of tuples of data to allocate.
218  *  \param [in] nbOfCompo - number of components of data to allocate.
219  *  \throw If \a nbOfTuple < 0 or \a nbOfCompo < 0.
220  */
221 void DataArrayChar::allocIfNecessary(int nbOfTuple, int nbOfCompo)
222 {
223   if(isAllocated())
224     {
225       if(nbOfTuple!=getNumberOfTuples() || nbOfCompo!=getNumberOfComponents())
226         alloc(nbOfTuple,nbOfCompo);
227     }
228   else
229     alloc(nbOfTuple,nbOfCompo);
230 }
231
232 /*!
233  * Allocates the raw data in memory. If the memory was already allocated, then it is
234  * freed and re-allocated. See an example of this method use
235  * \ref MEDCouplingArraySteps1WC "here".
236  *  \param [in] nbOfTuple - number of tuples of data to allocate.
237  *  \param [in] nbOfCompo - number of components of data to allocate.
238  *  \throw If \a nbOfTuple < 0 or \a nbOfCompo < 0.
239  */
240 void DataArrayChar::alloc(int nbOfTuple, int nbOfCompo)
241 {
242   if(nbOfTuple<0 || nbOfCompo<0)
243     throw INTERP_KERNEL::Exception("DataArrayChar::alloc : request for negative length of data !");
244   _info_on_compo.resize(nbOfCompo);
245   _mem.alloc(nbOfCompo*(std::size_t)nbOfTuple);
246   declareAsNew();
247 }
248
249 /*!
250  * Checks if \a this and another DataArrayChar are fully equal. For more info see
251  * \ref MEDCouplingArrayBasicsCompare.
252  *  \param [in] other - an instance of DataArrayChar to compare with \a this one.
253  *  \return bool - \a true if the two arrays are equal, \a false else.
254  */
255 bool DataArrayChar::isEqual(const DataArrayChar& other) const
256 {
257   std::string tmp;
258   return isEqualIfNotWhy(other,tmp);
259 }
260
261 /*!
262  * Equivalent to DataArrayChar::isEqual except that if false the reason of
263  * mismatch is given.
264  * 
265  * \param [in] other the instance to be compared with \a this
266  * \param [out] reason In case of inequality returns the reason.
267  * \sa DataArrayChar::isEqual
268  */
269 bool DataArrayChar::isEqualIfNotWhy(const DataArrayChar& other, std::string& reason) const
270 {
271   if(!areInfoEqualsIfNotWhy(other,reason))
272     return false;
273   return _mem.isEqual(other._mem,0,reason);
274 }
275
276 /*!
277  * Checks if values of \a this and another DataArrayChar are equal. For more info see
278  * \ref MEDCouplingArrayBasicsCompare.
279  *  \param [in] other - an instance of DataArrayChar to compare with \a this one.
280  *  \return bool - \a true if the values of two arrays are equal, \a false else.
281  */
282 bool DataArrayChar::isEqualWithoutConsideringStr(const DataArrayChar& other) const
283 {
284   std::string tmp;
285   return _mem.isEqual(other._mem,0,tmp);
286 }
287
288 /*!
289  * Reverse the array values.
290  *  \throw If \a this->getNumberOfComponents() < 1.
291  *  \throw If \a this is not allocated.
292  */
293 void DataArrayChar::reverse()
294 {
295   checkAllocated();
296   _mem.reverse(getNumberOfComponents());
297   declareAsNew();
298 }
299
300 /*!
301  * Assign zero to all values in \a this array. To know more on filling arrays see
302  * \ref MEDCouplingArrayFill.
303  * \throw If \a this is not allocated.
304  */
305 void DataArrayChar::fillWithZero()
306 {
307   checkAllocated();
308   _mem.fillWithValue(0);
309   declareAsNew();
310 }
311
312 /*!
313  * Assign \a val to all values in \a this array. To know more on filling arrays see
314  * \ref MEDCouplingArrayFill.
315  *  \param [in] val - the value to fill with.
316  *  \throw If \a this is not allocated.
317  */
318 void DataArrayChar::fillWithValue(char val)
319 {
320   checkAllocated();
321   _mem.fillWithValue(val);
322   declareAsNew();
323 }
324
325 /*!
326  * Returns a textual and human readable representation of \a this instance of
327  * DataArrayChar. This text is shown when a DataArrayChar is printed in Python.
328  *  \return std::string - text describing \a this DataArrayChar.
329  */
330 std::string DataArrayChar::repr() const
331 {
332   std::ostringstream ret;
333   reprStream(ret);
334   return ret.str();
335 }
336
337 std::string DataArrayChar::reprZip() const
338 {
339   std::ostringstream ret;
340   reprZipStream(ret);
341   return ret.str();
342 }
343
344 /*!
345  * Changes number of tuples in the array. If the new number of tuples is smaller
346  * than the current number the array is truncated, otherwise the array is extended.
347  *  \param [in] nbOfTuples - new number of tuples. 
348  *  \throw If \a this is not allocated.
349  *  \throw If \a nbOfTuples is negative.
350  */
351 void DataArrayChar::reAlloc(int nbOfTuples)
352 {
353   if(nbOfTuples<0)
354     throw INTERP_KERNEL::Exception("DataArrayChar::reAlloc : input new number of tuples should be >=0 !");
355   checkAllocated();
356   _mem.reAlloc(getNumberOfComponents()*(std::size_t)nbOfTuples);
357   declareAsNew();
358 }
359
360 /*!
361  * Creates a new DataArrayInt and assigns all (textual and numerical) data of \a this
362  * array to the new one.
363  *  \return DataArrayInt * - the new instance of DataArrayChar.
364  */
365 DataArrayInt *DataArrayChar::convertToIntArr() const
366 {
367   checkAllocated();
368   DataArrayInt *ret=DataArrayInt::New();
369   ret->alloc(getNumberOfTuples(),getNumberOfComponents());
370   std::size_t nbOfVals=getNbOfElems();
371   const char *src=getConstPointer();
372   int *dest=ret->getPointer();
373   std::copy(src,src+nbOfVals,dest);
374   ret->copyStringInfoFrom(*this);
375   return ret;
376 }
377
378 /*!
379  * Permutes values of \a this array as required by \a old2New array. The values are
380  * permuted so that \c new[ \a old2New[ i ]] = \c old[ i ]. Number of tuples remains
381  * the same as in \this one.
382  * If a permutation reduction is needed, subArray() or selectByTupleId() should be used.
383  * For more info on renumbering see \ref numbering.
384  *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
385  *     giving a new position for i-th old value.
386  */
387 void DataArrayChar::renumberInPlace(const int *old2New)
388 {
389   checkAllocated();
390   int nbTuples=getNumberOfTuples();
391   int nbOfCompo=getNumberOfComponents();
392   char *tmp=new char[nbTuples*nbOfCompo];
393   const char *iptr=getConstPointer();
394   for(int i=0;i<nbTuples;i++)
395     std::copy(iptr+nbOfCompo*i,iptr+nbOfCompo*(i+1),tmp+nbOfCompo*old2New[i]);
396   std::copy(tmp,tmp+nbTuples*nbOfCompo,getPointer());
397   delete [] tmp;
398   declareAsNew();
399 }
400
401 /*!
402  * Permutes values of \a this array as required by \a new2Old array. The values are
403  * permuted so that \c new[ i ] = \c old[ \a new2Old[ i ]]. Number of tuples remains
404  * the same as in \this one.
405  * For more info on renumbering see \ref numbering.
406  *  \param [in] new2Old - C array of length equal to \a this->getNumberOfTuples()
407  *     giving a previous position of i-th new value.
408  */
409 void DataArrayChar::renumberInPlaceR(const int *new2Old)
410 {
411   checkAllocated();
412   int nbTuples=getNumberOfTuples();
413   int nbOfCompo=getNumberOfComponents();
414   char *tmp=new char[nbTuples*nbOfCompo];
415   const char *iptr=getConstPointer();
416   for(int i=0;i<nbTuples;i++)
417     std::copy(iptr+nbOfCompo*new2Old[i],iptr+nbOfCompo*(new2Old[i]+1),tmp+nbOfCompo*i);
418   std::copy(tmp,tmp+nbTuples*nbOfCompo,getPointer());
419   delete [] tmp;
420   declareAsNew();
421 }
422
423 /*!
424  * Returns a copy of \a this array with values permuted as required by \a old2New array.
425  * The values are permuted so that  \c new[ \a old2New[ i ]] = \c old[ i ].
426  * Number of tuples in the result array remains the same as in \this one.
427  * If a permutation reduction is needed, renumberAndReduce() should be used.
428  * For more info on renumbering see \ref numbering.
429  *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
430  *          giving a new position for i-th old value.
431  *  \return DataArrayChar * - the new instance of DataArrayChar that the caller
432  *          is to delete using decrRef() as it is no more needed.
433  *  \throw If \a this is not allocated.
434  */
435 DataArrayChar *DataArrayChar::renumber(const int *old2New) const
436 {
437   checkAllocated();
438   int nbTuples=getNumberOfTuples();
439   int nbOfCompo=getNumberOfComponents();
440   MCAuto<DataArrayChar> ret=buildEmptySpecializedDAChar();
441   ret->alloc(nbTuples,nbOfCompo);
442   ret->copyStringInfoFrom(*this);
443   const char *iptr=getConstPointer();
444   char *optr=ret->getPointer();
445   for(int i=0;i<nbTuples;i++)
446     std::copy(iptr+nbOfCompo*i,iptr+nbOfCompo*(i+1),optr+nbOfCompo*old2New[i]);
447   ret->copyStringInfoFrom(*this);
448   return ret.retn();
449 }
450
451 /*!
452  * Returns a copy of \a this array with values permuted as required by \a new2Old array.
453  * The values are permuted so that  \c new[ i ] = \c old[ \a new2Old[ i ]]. Number of
454  * tuples in the result array remains the same as in \this one.
455  * If a permutation reduction is needed, subArray() or selectByTupleId() should be used.
456  * For more info on renumbering see \ref numbering.
457  *  \param [in] new2Old - C array of length equal to \a this->getNumberOfTuples()
458  *     giving a previous position of i-th new value.
459  *  \return DataArrayChar * - the new instance of DataArrayChar that the caller
460  *          is to delete using decrRef() as it is no more needed.
461  */
462 DataArrayChar *DataArrayChar::renumberR(const int *new2Old) const
463 {
464   checkAllocated();
465   int nbTuples=getNumberOfTuples();
466   int nbOfCompo=getNumberOfComponents();
467   MCAuto<DataArrayChar> ret=buildEmptySpecializedDAChar();
468   ret->alloc(nbTuples,nbOfCompo);
469   ret->copyStringInfoFrom(*this);
470   const char *iptr=getConstPointer();
471   char *optr=ret->getPointer();
472   for(int i=0;i<nbTuples;i++)
473     std::copy(iptr+nbOfCompo*new2Old[i],iptr+nbOfCompo*(new2Old[i]+1),optr+nbOfCompo*i);
474   ret->copyStringInfoFrom(*this);
475   return ret.retn();
476 }
477
478 /*!
479  * Returns a shorten and permuted copy of \a this array. The new DataArrayChar is
480  * of size \a newNbOfTuple and it's values are permuted as required by \a old2New array.
481  * The values are permuted so that  \c new[ \a old2New[ i ]] = \c old[ i ] for all
482  * \a old2New[ i ] >= 0. In other words every i-th tuple in \a this array, for which 
483  * \a old2New[ i ] is negative, is missing from the result array.
484  * For more info on renumbering see \ref numbering.
485  *  \param [in] old2New - C array of length equal to \a this->getNumberOfTuples()
486  *     giving a new position for i-th old tuple and giving negative position for
487  *     for i-th old tuple that should be omitted.
488  *  \return DataArrayChar * - the new instance of DataArrayChar that the caller
489  *          is to delete using decrRef() as it is no more needed.
490  */
491 DataArrayChar *DataArrayChar::renumberAndReduce(const int *old2New, int newNbOfTuple) const
492 {
493   checkAllocated();
494   int nbTuples=getNumberOfTuples();
495   int nbOfCompo=getNumberOfComponents();
496   MCAuto<DataArrayChar> ret=buildEmptySpecializedDAChar();
497   ret->alloc(newNbOfTuple,nbOfCompo);
498   const char *iptr=getConstPointer();
499   char *optr=ret->getPointer();
500   for(int i=0;i<nbTuples;i++)
501     {
502       int w=old2New[i];
503       if(w>=0)
504         std::copy(iptr+i*nbOfCompo,iptr+(i+1)*nbOfCompo,optr+w*nbOfCompo);
505     }
506   ret->copyStringInfoFrom(*this);
507   return ret.retn();
508 }
509
510 /*!
511  * Returns a shorten and permuted copy of \a this array. The new DataArrayChar is
512  * of size \a new2OldEnd - \a new2OldBg and it's values are permuted as required by
513  * \a new2OldBg array.
514  * The values are permuted so that  \c new[ i ] = \c old[ \a new2OldBg[ i ]].
515  * This method is equivalent to renumberAndReduce() except that convention in input is
516  * \c new2old and \b not \c old2new.
517  * For more info on renumbering see \ref numbering.
518  *  \param [in] new2OldBg - pointer to the beginning of a permutation array that gives a
519  *              tuple index in \a this array to fill the i-th tuple in the new array.
520  *  \param [in] new2OldEnd - specifies the end of the permutation array that starts at
521  *              \a new2OldBg, so that pointer to a tuple index (\a pi) varies as this:
522  *              \a new2OldBg <= \a pi < \a new2OldEnd.
523  *  \return DataArrayChar * - the new instance of DataArrayChar that the caller
524  *          is to delete using decrRef() as it is no more needed.
525  */
526 DataArrayChar *DataArrayChar::selectByTupleId(const int *new2OldBg, const int *new2OldEnd) const
527 {
528   return selectByTupleIdSafe(new2OldBg,new2OldEnd);
529 }
530
531 /*!
532  * Returns a shorten and permuted copy of \a this array. The new DataArrayChar is
533  * of size \a new2OldEnd - \a new2OldBg and it's values are permuted as required by
534  * \a new2OldBg array.
535  * The values are permuted so that  \c new[ i ] = \c old[ \a new2OldBg[ i ]].
536  * This method is equivalent to renumberAndReduce() except that convention in input is
537  * \c new2old and \b not \c old2new.
538  * This method is equivalent to selectByTupleId() except that it prevents coping data
539  * from behind the end of \a this array.
540  * For more info on renumbering see \ref numbering.
541  *  \param [in] new2OldBg - pointer to the beginning of a permutation array that gives a
542  *              tuple index in \a this array to fill the i-th tuple in the new array.
543  *  \param [in] new2OldEnd - specifies the end of the permutation array that starts at
544  *              \a new2OldBg, so that pointer to a tuple index (\a pi) varies as this:
545  *              \a new2OldBg <= \a pi < \a new2OldEnd.
546  *  \return DataArrayChar * - the new instance of DataArrayChar that the caller
547  *          is to delete using decrRef() as it is no more needed.
548  *  \throw If \a new2OldEnd - \a new2OldBg > \a this->getNumberOfTuples().
549  */
550 DataArrayChar *DataArrayChar::selectByTupleIdSafe(const int *new2OldBg, const int *new2OldEnd) const
551 {
552   checkAllocated();
553   MCAuto<DataArrayChar> ret=buildEmptySpecializedDAChar();
554   int nbComp=getNumberOfComponents();
555   int oldNbOfTuples=getNumberOfTuples();
556   ret->alloc((int)std::distance(new2OldBg,new2OldEnd),nbComp);
557   ret->copyStringInfoFrom(*this);
558   char *pt=ret->getPointer();
559   const char *srcPt=getConstPointer();
560   int i=0;
561   for(const int *w=new2OldBg;w!=new2OldEnd;w++,i++)
562     if(*w>=0 && *w<oldNbOfTuples)
563       std::copy(srcPt+(*w)*nbComp,srcPt+((*w)+1)*nbComp,pt+i*nbComp);
564     else
565       throw INTERP_KERNEL::Exception("DataArrayChar::selectByTupleIdSafe : some ids has been detected to be out of [0,this->getNumberOfTuples) !");
566   ret->copyStringInfoFrom(*this);
567   return ret.retn();
568 }
569
570 /*!
571  * Returns a shorten copy of \a this array. The new DataArrayChar contains every
572  * (\a bg + \c i * \a step)-th tuple of \a this array located before the \a end2-th
573  * tuple. Indices of the selected tuples are the same as ones returned by the Python
574  * command \c range( \a bg, \a end2, \a step ).
575  * This method is equivalent to selectByTupleIdSafe() except that the input array is
576  * not constructed explicitly.
577  * For more info on renumbering see \ref numbering.
578  *  \param [in] bg - index of the first tuple to copy from \a this array.
579  *  \param [in] end2 - index of the tuple before which the tuples to copy are located.
580  *  \param [in] step - index increment to get index of the next tuple to copy.
581  *  \return DataArrayChar * - the new instance of DataArrayChar that the caller
582  *          is to delete using decrRef() as it is no more needed.
583  *  \throw If (\a end2 < \a bg) or (\a step <= 0).
584  *  \sa DataArrayChar::substr.
585  */
586 DataArrayChar *DataArrayChar::selectByTupleIdSafeSlice(int bg, int end2, int step) const
587 {
588   checkAllocated();
589   MCAuto<DataArrayChar> ret=buildEmptySpecializedDAChar();
590   int nbComp=getNumberOfComponents();
591   int newNbOfTuples=GetNumberOfItemGivenBESRelative(bg,end2,step,"DataArrayInt::selectByTupleIdSafeSlice : ");
592   ret->alloc(newNbOfTuples,nbComp);
593   char *pt=ret->getPointer();
594   const char *srcPt=getConstPointer()+bg*nbComp;
595   for(int i=0;i<newNbOfTuples;i++,srcPt+=step*nbComp)
596     std::copy(srcPt,srcPt+nbComp,pt+i*nbComp);
597   ret->copyStringInfoFrom(*this);
598   return ret.retn();
599 }
600
601 /*!
602  * Checks if all values in \a this array are equal to \a val.
603  *  \param [in] val - value to check equality of array values to.
604  *  \return bool - \a true if all values are \a val.
605  *  \throw If \a this is not allocated.
606  *  \throw If \a this->getNumberOfComponents() != 1
607  */
608 bool DataArrayChar::isUniform(char val) const
609 {
610   checkAllocated();
611   if(getNumberOfComponents()!=1)
612     throw INTERP_KERNEL::Exception("DataArrayChar::isUniform : must be applied on DataArrayChar with only one component, you can call 'rearrange' method before !");
613   int nbOfTuples=getNumberOfTuples();
614   const char *w=getConstPointer();
615   const char *end2=w+nbOfTuples;
616   for(;w!=end2;w++)
617     if(*w!=val)
618       return false;
619   return true;
620 }
621
622 /*!
623  * Changes the number of components within \a this array so that its raw data **does
624  * not** change, instead splitting this data into tuples changes.
625  *  \param [in] newNbOfComp - number of components for \a this array to have.
626  *  \throw If \a this is not allocated
627  *  \throw If getNbOfElems() % \a newNbOfCompo != 0.
628  *  \throw If \a newNbOfCompo is lower than 1.
629  *  \throw If the rearrange method would lead to a number of tuples higher than 2147483647 (maximal capacity of int32 !).
630  *  \warning This method erases all (name and unit) component info set before!
631  */
632 void DataArrayChar::rearrange(int newNbOfCompo)
633 {
634   checkAllocated();
635   if(newNbOfCompo<1)
636     throw INTERP_KERNEL::Exception("DataArrayChar::rearrange : input newNbOfCompo must be > 0 !");
637   std::size_t nbOfElems=getNbOfElems();
638   if(nbOfElems%newNbOfCompo!=0)
639     throw INTERP_KERNEL::Exception("DataArrayChar::rearrange : nbOfElems%newNbOfCompo!=0 !");
640   if(nbOfElems/newNbOfCompo>(std::size_t)std::numeric_limits<int>::max())
641     throw INTERP_KERNEL::Exception("DataArrayChar::rearrange : the rearrangement leads to too high number of tuples (> 2147483647) !");
642   _info_on_compo.clear();
643   _info_on_compo.resize(newNbOfCompo);
644   declareAsNew();
645 }
646
647 /*!
648  * Returns a shorten copy of \a this array. The new DataArrayChar contains all
649  * tuples starting from the \a tupleIdBg-th tuple and including all tuples located before
650  * the \a tupleIdEnd-th one. This methods has a similar behavior as std::string::subArray().
651  * This method is a specialization of selectByTupleIdSafeSlice().
652  *  \param [in] tupleIdBg - index of the first tuple to copy from \a this array.
653  *  \param [in] tupleIdEnd - index of the tuple before which the tuples to copy are located.
654  *          If \a tupleIdEnd == -1, all the tuples till the end of \a this array are copied.
655  *  \return DataArrayChar * - the new instance of DataArrayChar that the caller
656  *          is to delete using decrRef() as it is no more needed.
657  *  \throw If \a tupleIdBg < 0.
658  *  \throw If \a tupleIdBg > \a this->getNumberOfTuples().
659     \throw If \a tupleIdEnd != -1 && \a tupleIdEnd < \a this->getNumberOfTuples().
660  *  \sa DataArrayChar::selectByTupleIdSafeSlice
661  */
662 DataArrayChar *DataArrayChar::subArray(int tupleIdBg, int tupleIdEnd) const
663 {
664   checkAllocated();
665   int nbt=getNumberOfTuples();
666   if(tupleIdBg<0)
667     throw INTERP_KERNEL::Exception("DataArrayChar::substr : The tupleIdBg parameter must be greater than 0 !");
668   if(tupleIdBg>nbt)
669     throw INTERP_KERNEL::Exception("DataArrayChar::substr : The tupleIdBg parameter is greater than number of tuples !");
670   int trueEnd=tupleIdEnd;
671   if(tupleIdEnd!=-1)
672     {
673       if(tupleIdEnd>nbt)
674         throw INTERP_KERNEL::Exception("DataArrayChar::substr : The tupleIdBg parameter is greater or equal than number of tuples !");
675     }
676   else
677     trueEnd=nbt;
678   int nbComp=getNumberOfComponents();
679   MCAuto<DataArrayChar> ret=buildEmptySpecializedDAChar();
680   ret->alloc(trueEnd-tupleIdBg,nbComp);
681   ret->copyStringInfoFrom(*this);
682   std::copy(getConstPointer()+tupleIdBg*nbComp,getConstPointer()+trueEnd*nbComp,ret->getPointer());
683   return ret.retn();
684 }
685
686 /*!
687  * Returns a shorten or extended copy of \a this array. If \a newNbOfComp is less
688  * than \a this->getNumberOfComponents() then the result array is shorten as each tuple
689  * is truncated to have \a newNbOfComp components, keeping first components. If \a
690  * newNbOfComp is more than \a this->getNumberOfComponents() then the result array is
691  * expanded as each tuple is populated with \a dftValue to have \a newNbOfComp
692  * components.  
693  *  \param [in] newNbOfComp - number of components for the new array to have.
694  *  \param [in] dftValue - value assigned to new values added to the new array.
695  *  \return DataArrayChar * - the new instance of DataArrayChar that the caller
696  *          is to delete using decrRef() as it is no more needed.
697  *  \throw If \a this is not allocated.
698  */
699 DataArrayChar *DataArrayChar::changeNbOfComponents(int newNbOfComp, char dftValue) const
700 {
701   checkAllocated();
702   MCAuto<DataArrayChar> ret=buildEmptySpecializedDAChar();
703   ret->alloc(getNumberOfTuples(),newNbOfComp);
704   const char *oldc=getConstPointer();
705   char *nc=ret->getPointer();
706   int nbOfTuples=getNumberOfTuples();
707   int oldNbOfComp=getNumberOfComponents();
708   int dim=std::min(oldNbOfComp,newNbOfComp);
709   for(int i=0;i<nbOfTuples;i++)
710     {
711       int j=0;
712       for(;j<dim;j++)
713         nc[newNbOfComp*i+j]=oldc[i*oldNbOfComp+j];
714       for(;j<newNbOfComp;j++)
715         nc[newNbOfComp*i+j]=dftValue;
716     }
717   ret->setName(getName());
718   for(int i=0;i<dim;i++)
719     ret->setInfoOnComponent(i,getInfoOnComponent(i));
720   ret->setName(getName());
721   return ret.retn();
722 }
723
724 /*!
725  * Returns a copy of \a this array composed of selected components.
726  * The new DataArrayChar has the same number of tuples but includes components
727  * specified by \a compoIds parameter. So that getNbOfElems() of the result array
728  * can be either less, same or more than \a this->getNbOfElems().
729  *  \param [in] compoIds - sequence of zero based indices of components to include
730  *              into the new array.
731  *  \return DataArrayChar * - the new instance of DataArrayChar that the caller
732  *          is to delete using decrRef() as it is no more needed.
733  *  \throw If \a this is not allocated.
734  *  \throw If a component index (\a i) is not valid: 
735  *         \a i < 0 || \a i >= \a this->getNumberOfComponents().
736  *
737  *  \if ENABLE_EXAMPLES
738  *  \ref py_mcdataarrayint_keepselectedcomponents "Here is a Python example".
739  *  \endif
740  */
741 DataArrayChar *DataArrayChar::keepSelectedComponents(const std::vector<int>& compoIds) const
742 {
743   checkAllocated();
744   MCAuto<DataArrayChar> ret(buildEmptySpecializedDAChar());
745   int newNbOfCompo=(int)compoIds.size();
746   int oldNbOfCompo=getNumberOfComponents();
747   for(std::vector<int>::const_iterator it=compoIds.begin();it!=compoIds.end();it++)
748     DataArray::CheckValueInRange(oldNbOfCompo,(*it),"keepSelectedComponents invalid requested component");
749   int nbOfTuples=getNumberOfTuples();
750   ret->alloc(nbOfTuples,newNbOfCompo);
751   ret->copyPartOfStringInfoFrom(*this,compoIds);
752   const char *oldc=getConstPointer();
753   char *nc=ret->getPointer();
754   for(int i=0;i<nbOfTuples;i++)
755     for(int j=0;j<newNbOfCompo;j++,nc++)
756       *nc=oldc[i*oldNbOfCompo+compoIds[j]];
757   return ret.retn();
758 }
759
760 /*!
761  * Appends components of another array to components of \a this one, tuple by tuple.
762  * So that the number of tuples of \a this array remains the same and the number of 
763  * components increases.
764  *  \param [in] other - the DataArrayChar to append to \a this one.
765  *  \throw If \a this is not allocated.
766  *  \throw If \a this and \a other arrays have different number of tuples.
767  *
768  *  \if ENABLE_EXAMPLES
769  *  \ref cpp_mcdataarrayint_meldwith "Here is a C++ example".
770  *
771  *  \ref py_mcdataarrayint_meldwith "Here is a Python example".
772  *  \endif
773  */
774 void DataArrayChar::meldWith(const DataArrayChar *other)
775 {
776   if(!other)
777     throw INTERP_KERNEL::Exception("DataArrayChar::meldWith : DataArrayChar pointer in input is NULL !");
778   checkAllocated();
779   other->checkAllocated();
780   int nbOfTuples=getNumberOfTuples();
781   if(nbOfTuples!=other->getNumberOfTuples())
782     throw INTERP_KERNEL::Exception("DataArrayChar::meldWith : mismatch of number of tuples !");
783   int nbOfComp1=getNumberOfComponents();
784   int nbOfComp2=other->getNumberOfComponents();
785   char *newArr=(char *)malloc(nbOfTuples*(nbOfComp1+nbOfComp2)*sizeof(char));
786   char *w=newArr;
787   const char *inp1=getConstPointer();
788   const char *inp2=other->getConstPointer();
789   for(int i=0;i<nbOfTuples;i++,inp1+=nbOfComp1,inp2+=nbOfComp2)
790     {
791       w=std::copy(inp1,inp1+nbOfComp1,w);
792       w=std::copy(inp2,inp2+nbOfComp2,w);
793     }
794   useArray(newArr,true,C_DEALLOC,nbOfTuples,nbOfComp1+nbOfComp2);
795   std::vector<int> compIds(nbOfComp2);
796   for(int i=0;i<nbOfComp2;i++)
797     compIds[i]=nbOfComp1+i;
798   copyPartOfStringInfoFrom2(compIds,*other);
799 }
800
801 /*!
802  * Copy all values from another DataArrayChar into specified tuples and components
803  * of \a this array. Textual data is not copied.
804  * The tree parameters defining set of indices of tuples and components are similar to
805  * the tree parameters of the Python function \c range(\c start,\c stop,\c step).
806  *  \param [in] a - the array to copy values from.
807  *  \param [in] bgTuples - index of the first tuple of \a this array to assign values to.
808  *  \param [in] endTuples - index of the tuple before which the tuples to assign to
809  *              are located.
810  *  \param [in] stepTuples - index increment to get index of the next tuple to assign to.
811  *  \param [in] bgComp - index of the first component of \a this array to assign values to.
812  *  \param [in] endComp - index of the component before which the components to assign
813  *              to are located.
814  *  \param [in] stepComp - index increment to get index of the next component to assign to.
815  *  \param [in] strictCompoCompare - if \a true (by default), then \a a->getNumberOfComponents() 
816  *              must be equal to the number of columns to assign to, else an
817  *              exception is thrown; if \a false, then it is only required that \a
818  *              a->getNbOfElems() equals to number of values to assign to (this condition
819  *              must be respected even if \a strictCompoCompare is \a true). The number of 
820  *              values to assign to is given by following Python expression:
821  *              \a nbTargetValues = 
822  *              \c len(\c range(\a bgTuples,\a endTuples,\a stepTuples)) *
823  *              \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
824  *  \throw If \a a is NULL.
825  *  \throw If \a a is not allocated.
826  *  \throw If \a this is not allocated.
827  *  \throw If parameters specifying tuples and components to assign to do not give a
828  *            non-empty range of increasing indices.
829  *  \throw If \a a->getNbOfElems() != \a nbTargetValues.
830  *  \throw If \a strictCompoCompare == \a true && \a a->getNumberOfComponents() !=
831  *            \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
832  *
833  *  \if ENABLE_EXAMPLES
834  *  \ref py_mcdataarrayint_setpartofvalues1 "Here is a Python example".
835  *  \endif
836  */
837 void DataArrayChar::setPartOfValues1(const DataArrayChar *a, int bgTuples, int endTuples, int stepTuples, int bgComp, int endComp, int stepComp, bool strictCompoCompare)
838 {
839   if(!a)
840     throw INTERP_KERNEL::Exception("DataArrayChar::setPartOfValues1 : DataArrayChar pointer in input is NULL !");
841   const char msg[]="DataArrayChar::setPartOfValues1";
842   checkAllocated();
843   a->checkAllocated();
844   int newNbOfTuples=DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg);
845   int newNbOfComp=DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg);
846   int nbComp=getNumberOfComponents();
847   int nbOfTuples=getNumberOfTuples();
848   DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
849   DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
850   bool assignTech=true;
851   if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
852     {
853       if(strictCompoCompare)
854         a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
855     }
856   else
857     {
858       a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
859       assignTech=false;
860     }
861   char *pt=getPointer()+bgTuples*nbComp+bgComp;
862   const char *srcPt=a->getConstPointer();
863   if(assignTech)
864     {
865       for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
866         for(int j=0;j<newNbOfComp;j++,srcPt++)
867           pt[j*stepComp]=*srcPt;
868     }
869   else
870     {
871       for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
872         {
873           const char *srcPt2=srcPt;
874           for(int j=0;j<newNbOfComp;j++,srcPt2++)
875             pt[j*stepComp]=*srcPt2;
876         }
877     }
878 }
879
880 /*!
881  * Assign a given value to values at specified tuples and components of \a this array.
882  * The tree parameters defining set of indices of tuples and components are similar to
883  * the tree parameters of the Python function \c range(\c start,\c stop,\c step)..
884  *  \param [in] a - the value to assign.
885  *  \param [in] bgTuples - index of the first tuple of \a this array to assign to.
886  *  \param [in] endTuples - index of the tuple before which the tuples to assign to
887  *              are located.
888  *  \param [in] stepTuples - index increment to get index of the next tuple to assign to.
889  *  \param [in] bgComp - index of the first component of \a this array to assign to.
890  *  \param [in] endComp - index of the component before which the components to assign
891  *              to are located.
892  *  \param [in] stepComp - index increment to get index of the next component to assign to.
893  *  \throw If \a this is not allocated.
894  *  \throw If parameters specifying tuples and components to assign to, do not give a
895  *            non-empty range of increasing indices or indices are out of a valid range
896  *            for \this array.
897  *
898  *  \if ENABLE_EXAMPLES
899  *  \ref py_mcdataarrayint_setpartofvaluessimple1 "Here is a Python example".
900  *  \endif
901  */
902 void DataArrayChar::setPartOfValuesSimple1(char a, int bgTuples, int endTuples, int stepTuples, int bgComp, int endComp, int stepComp)
903 {
904   const char msg[]="DataArrayChar::setPartOfValuesSimple1";
905   checkAllocated();
906   int newNbOfTuples=DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg);
907   int newNbOfComp=DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg);
908   int nbComp=getNumberOfComponents();
909   int nbOfTuples=getNumberOfTuples();
910   DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
911   DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
912   char *pt=getPointer()+bgTuples*nbComp+bgComp;
913   for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
914     for(int j=0;j<newNbOfComp;j++)
915       pt[j*stepComp]=a;
916 }
917
918
919 /*!
920  * Copy all values from another DataArrayChar (\a a) into specified tuples and 
921  * components of \a this array. Textual data is not copied.
922  * The tuples and components to assign to are defined by C arrays of indices.
923  * There are two *modes of usage*:
924  * - If \a a->getNbOfElems() equals to number of values to assign to, then every value
925  *   of \a a is assigned to its own location within \a this array. 
926  * - If \a a includes one tuple, then all values of \a a are assigned to the specified
927  *   components of every specified tuple of \a this array. In this mode it is required
928  *   that \a a->getNumberOfComponents() equals to the number of specified components.
929  * 
930  *  \param [in] a - the array to copy values from.
931  *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
932  *              assign values of \a a to.
933  *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
934  *              pointer to a tuple index <em>(pi)</em> varies as this: 
935  *              \a bgTuples <= \a pi < \a endTuples.
936  *  \param [in] bgComp - pointer to an array of component indices of \a this array to
937  *              assign values of \a a to.
938  *  \param [in] endComp - specifies the end of the array \a bgTuples, so that
939  *              pointer to a component index <em>(pi)</em> varies as this: 
940  *              \a bgComp <= \a pi < \a endComp.
941  *  \param [in] strictCompoCompare - this parameter is checked only if the
942  *               *mode of usage* is the first; if it is \a true (default), 
943  *               then \a a->getNumberOfComponents() must be equal 
944  *               to the number of specified columns, else this is not required.
945  *  \throw If \a a is NULL.
946  *  \throw If \a a is not allocated.
947  *  \throw If \a this is not allocated.
948  *  \throw If any index of tuple/component given by <em>bgTuples / bgComp</em> is
949  *         out of a valid range for \a this array.
950  *  \throw In the first *mode of usage*, if <em>strictCompoCompare == true </em> and
951  *         if <em> a->getNumberOfComponents() != (endComp - bgComp) </em>.
952  *  \throw In the second *mode of usage*, if \a a->getNumberOfTuples() != 1 or
953  *         <em> a->getNumberOfComponents() != (endComp - bgComp)</em>.
954  *
955  *  \if ENABLE_EXAMPLES
956  *  \ref py_mcdataarrayint_setpartofvalues2 "Here is a Python example".
957  *  \endif
958  */
959 void DataArrayChar::setPartOfValues2(const DataArrayChar *a, const int *bgTuples, const int *endTuples, const int *bgComp, const int *endComp, bool strictCompoCompare)
960 {
961   if(!a)
962     throw INTERP_KERNEL::Exception("DataArrayChar::setPartOfValues2 : DataArrayChar pointer in input is NULL !");
963   const char msg[]="DataArrayChar::setPartOfValues2";
964   checkAllocated();
965   a->checkAllocated();
966   int nbComp=getNumberOfComponents();
967   int nbOfTuples=getNumberOfTuples();
968   for(const int *z=bgComp;z!=endComp;z++)
969     DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
970   int newNbOfTuples=(int)std::distance(bgTuples,endTuples);
971   int newNbOfComp=(int)std::distance(bgComp,endComp);
972   bool assignTech=true;
973   if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
974     {
975       if(strictCompoCompare)
976         a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
977     }
978   else
979     {
980       a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
981       assignTech=false;
982     }
983   char *pt=getPointer();
984   const char *srcPt=a->getConstPointer();
985   if(assignTech)
986     {    
987       for(const int *w=bgTuples;w!=endTuples;w++)
988         {
989           DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
990           for(const int *z=bgComp;z!=endComp;z++,srcPt++)
991             {    
992               pt[(std::size_t)(*w)*nbComp+(*z)]=*srcPt;
993             }
994         }
995     }
996   else
997     {
998       for(const int *w=bgTuples;w!=endTuples;w++)
999         {
1000           const char *srcPt2=srcPt;
1001           DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1002           for(const int *z=bgComp;z!=endComp;z++,srcPt2++)
1003             {    
1004               pt[(std::size_t)(*w)*nbComp+(*z)]=*srcPt2;
1005             }
1006         }
1007     }
1008 }
1009
1010 /*!
1011  * Assign a given value to values at specified tuples and components of \a this array.
1012  * The tuples and components to assign to are defined by C arrays of indices.
1013  *  \param [in] a - the value to assign.
1014  *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1015  *              assign \a a to.
1016  *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1017  *              pointer to a tuple index (\a pi) varies as this: 
1018  *              \a bgTuples <= \a pi < \a endTuples.
1019  *  \param [in] bgComp - pointer to an array of component indices of \a this array to
1020  *              assign \a a to.
1021  *  \param [in] endComp - specifies the end of the array \a bgTuples, so that
1022  *              pointer to a component index (\a pi) varies as this: 
1023  *              \a bgComp <= \a pi < \a endComp.
1024  *  \throw If \a this is not allocated.
1025  *  \throw If any index of tuple/component given by <em>bgTuples / bgComp</em> is
1026  *         out of a valid range for \a this array.
1027  *
1028  *  \if ENABLE_EXAMPLES
1029  *  \ref py_mcdataarrayint_setpartofvaluessimple2 "Here is a Python example".
1030  *  \endif
1031  */
1032 void DataArrayChar::setPartOfValuesSimple2(char a, const int *bgTuples, const int *endTuples, const int *bgComp, const int *endComp)
1033 {
1034   checkAllocated();
1035   int nbComp=getNumberOfComponents();
1036   int nbOfTuples=getNumberOfTuples();
1037   for(const int *z=bgComp;z!=endComp;z++)
1038     DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
1039   char *pt=getPointer();
1040   for(const int *w=bgTuples;w!=endTuples;w++)
1041     for(const int *z=bgComp;z!=endComp;z++)
1042       {
1043         DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1044         pt[(std::size_t)(*w)*nbComp+(*z)]=a;
1045       }
1046 }
1047
1048 /*!
1049  * Copy all values from another DataArrayChar (\a a) into specified tuples and 
1050  * components of \a this array. Textual data is not copied.
1051  * The tuples to assign to are defined by a C array of indices.
1052  * The components to assign to are defined by three values similar to parameters of
1053  * the Python function \c range(\c start,\c stop,\c step).
1054  * There are two *modes of usage*:
1055  * - If \a a->getNbOfElems() equals to number of values to assign to, then every value
1056  *   of \a a is assigned to its own location within \a this array. 
1057  * - If \a a includes one tuple, then all values of \a a are assigned to the specified
1058  *   components of every specified tuple of \a this array. In this mode it is required
1059  *   that \a a->getNumberOfComponents() equals to the number of specified components.
1060  *
1061  *  \param [in] a - the array to copy values from.
1062  *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1063  *              assign values of \a a to.
1064  *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1065  *              pointer to a tuple index <em>(pi)</em> varies as this: 
1066  *              \a bgTuples <= \a pi < \a endTuples.
1067  *  \param [in] bgComp - index of the first component of \a this array to assign to.
1068  *  \param [in] endComp - index of the component before which the components to assign
1069  *              to are located.
1070  *  \param [in] stepComp - index increment to get index of the next component to assign to.
1071  *  \param [in] strictCompoCompare - this parameter is checked only in the first
1072  *               *mode of usage*; if \a strictCompoCompare is \a true (default), 
1073  *               then \a a->getNumberOfComponents() must be equal 
1074  *               to the number of specified columns, else this is not required.
1075  *  \throw If \a a is NULL.
1076  *  \throw If \a a is not allocated.
1077  *  \throw If \a this is not allocated.
1078  *  \throw If any index of tuple given by \a bgTuples is out of a valid range for 
1079  *         \a this array.
1080  *  \throw In the first *mode of usage*, if <em>strictCompoCompare == true </em> and
1081  *         if <em> a->getNumberOfComponents()</em> is unequal to the number of components
1082  *         defined by <em>(bgComp,endComp,stepComp)</em>.
1083  *  \throw In the second *mode of usage*, if \a a->getNumberOfTuples() != 1 or
1084  *         <em> a->getNumberOfComponents()</em> is unequal to the number of components
1085  *         defined by <em>(bgComp,endComp,stepComp)</em>.
1086  *  \throw If parameters specifying components to assign to, do not give a
1087  *            non-empty range of increasing indices or indices are out of a valid range
1088  *            for \this array.
1089  *
1090  *  \if ENABLE_EXAMPLES
1091  *  \ref py_mcdataarrayint_setpartofvalues3 "Here is a Python example".
1092  *  \endif
1093  */
1094 void DataArrayChar::setPartOfValues3(const DataArrayChar *a, const int *bgTuples, const int *endTuples, int bgComp, int endComp, int stepComp, bool strictCompoCompare)
1095 {
1096   if(!a)
1097     throw INTERP_KERNEL::Exception("DataArrayChar::setPartOfValues3 : DataArrayChar pointer in input is NULL !");
1098   const char msg[]="DataArrayChar::setPartOfValues3";
1099   checkAllocated();
1100   a->checkAllocated();
1101   int newNbOfComp=DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg);
1102   int nbComp=getNumberOfComponents();
1103   int nbOfTuples=getNumberOfTuples();
1104   DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
1105   int newNbOfTuples=(int)std::distance(bgTuples,endTuples);
1106   bool assignTech=true;
1107   if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
1108     {
1109       if(strictCompoCompare)
1110         a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1111     }
1112   else
1113     {
1114       a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1115       assignTech=false;
1116     }
1117   char *pt=getPointer()+bgComp;
1118   const char *srcPt=a->getConstPointer();
1119   if(assignTech)
1120     {
1121       for(const int *w=bgTuples;w!=endTuples;w++)
1122         for(int j=0;j<newNbOfComp;j++,srcPt++)
1123           {
1124             DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1125             pt[(std::size_t)(*w)*nbComp+j*stepComp]=*srcPt;
1126           }
1127     }
1128   else
1129     {
1130       for(const int *w=bgTuples;w!=endTuples;w++)
1131         {
1132           const char *srcPt2=srcPt;
1133           for(int j=0;j<newNbOfComp;j++,srcPt2++)
1134             {
1135               DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1136               pt[(std::size_t)(*w)*nbComp+j*stepComp]=*srcPt2;
1137             }
1138         }
1139     }
1140 }
1141
1142 /*!
1143  * Assign a given value to values at specified tuples and components of \a this array.
1144  * The tuples to assign to are defined by a C array of indices.
1145  * The components to assign to are defined by three values similar to parameters of
1146  * the Python function \c range(\c start,\c stop,\c step).
1147  *  \param [in] a - the value to assign.
1148  *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1149  *              assign \a a to.
1150  *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1151  *              pointer to a tuple index <em>(pi)</em> varies as this: 
1152  *              \a bgTuples <= \a pi < \a endTuples.
1153  *  \param [in] bgComp - index of the first component of \a this array to assign to.
1154  *  \param [in] endComp - index of the component before which the components to assign
1155  *              to are located.
1156  *  \param [in] stepComp - index increment to get index of the next component to assign to.
1157  *  \throw If \a this is not allocated.
1158  *  \throw If any index of tuple given by \a bgTuples is out of a valid range for 
1159  *         \a this array.
1160  *  \throw If parameters specifying components to assign to, do not give a
1161  *            non-empty range of increasing indices or indices are out of a valid range
1162  *            for \this array.
1163  *
1164  *  \if ENABLE_EXAMPLES
1165  *  \ref py_mcdataarrayint_setpartofvaluessimple3 "Here is a Python example".
1166  *  \endif
1167  */
1168 void DataArrayChar::setPartOfValuesSimple3(char a, const int *bgTuples, const int *endTuples, int bgComp, int endComp, int stepComp)
1169 {
1170   const char msg[]="DataArrayChar::setPartOfValuesSimple3";
1171   checkAllocated();
1172   int newNbOfComp=DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg);
1173   int nbComp=getNumberOfComponents();
1174   int nbOfTuples=getNumberOfTuples();
1175   DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
1176   char *pt=getPointer()+bgComp;
1177   for(const int *w=bgTuples;w!=endTuples;w++)
1178     for(int j=0;j<newNbOfComp;j++)
1179       {
1180         DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1181         pt[(*w)*nbComp+j*stepComp]=a;
1182       }
1183 }
1184
1185 void DataArrayChar::setPartOfValues4(const DataArrayChar *a, int bgTuples, int endTuples, int stepTuples, const int *bgComp, const int *endComp, bool strictCompoCompare)
1186 {
1187   if(!a)
1188     throw INTERP_KERNEL::Exception("DataArrayInt::setPartOfValues4 : input DataArrayInt is NULL !");
1189   const char msg[]="DataArrayInt::setPartOfValues4";
1190   checkAllocated();
1191   a->checkAllocated();
1192   int newNbOfTuples=DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg);
1193   int newNbOfComp=(int)std::distance(bgComp,endComp);
1194   int nbComp=getNumberOfComponents();
1195   for(const int *z=bgComp;z!=endComp;z++)
1196     DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
1197   int nbOfTuples=getNumberOfTuples();
1198   DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1199   bool assignTech=true;
1200   if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
1201     {
1202       if(strictCompoCompare)
1203         a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1204     }
1205   else
1206     {
1207       a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1208       assignTech=false;
1209     }
1210   const char *srcPt=a->getConstPointer();
1211   char *pt=getPointer()+bgTuples*nbComp;
1212   if(assignTech)
1213     {
1214       for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1215         for(const int *z=bgComp;z!=endComp;z++,srcPt++)
1216           pt[*z]=*srcPt;
1217     }
1218   else
1219     {
1220       for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1221         {
1222           const char *srcPt2=srcPt;
1223           for(const int *z=bgComp;z!=endComp;z++,srcPt2++)
1224             pt[*z]=*srcPt2;
1225         }
1226     }
1227 }
1228
1229 void DataArrayChar::setPartOfValuesSimple4(char a, int bgTuples, int endTuples, int stepTuples, const int *bgComp, const int *endComp)
1230 {
1231   const char msg[]="DataArrayInt::setPartOfValuesSimple4";
1232   checkAllocated();
1233   int newNbOfTuples=DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg);
1234   int nbComp=getNumberOfComponents();
1235   for(const int *z=bgComp;z!=endComp;z++)
1236     DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
1237   int nbOfTuples=getNumberOfTuples();
1238   DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1239   char *pt=getPointer()+bgTuples*nbComp;
1240   for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1241     for(const int *z=bgComp;z!=endComp;z++)
1242       pt[*z]=a;
1243 }
1244
1245 /*!
1246  * Copy some tuples from another DataArrayChar into specified tuples
1247  * of \a this array. Textual data is not copied. Both arrays must have equal number of
1248  * components.
1249  * Both the tuples to assign and the tuples to assign to are defined by a DataArrayChar.
1250  * All components of selected tuples are copied.
1251  *  \param [in] a - the array to copy values from.
1252  *  \param [in] tuplesSelec - the array specifying both source tuples of \a a and
1253  *              target tuples of \a this. \a tuplesSelec has two components, and the
1254  *              first component specifies index of the source tuple and the second
1255  *              one specifies index of the target tuple.
1256  *  \throw If \a this is not allocated.
1257  *  \throw If \a a is NULL.
1258  *  \throw If \a a is not allocated.
1259  *  \throw If \a tuplesSelec is NULL.
1260  *  \throw If \a tuplesSelec is not allocated.
1261  *  \throw If <em>this->getNumberOfComponents() != a->getNumberOfComponents()</em>.
1262  *  \throw If \a tuplesSelec->getNumberOfComponents() != 2.
1263  *  \throw If any tuple index given by \a tuplesSelec is out of a valid range for 
1264  *         the corresponding (\a this or \a a) array.
1265  */
1266 void DataArrayChar::setPartOfValuesAdv(const DataArrayChar *a, const DataArrayChar *tuplesSelec)
1267 {
1268   if(!a || !tuplesSelec)
1269     throw INTERP_KERNEL::Exception("DataArrayChar::setPartOfValuesAdv : DataArrayChar pointer in input is NULL !");
1270   checkAllocated();
1271   a->checkAllocated();
1272   tuplesSelec->checkAllocated();
1273   int nbOfComp=getNumberOfComponents();
1274   if(nbOfComp!=a->getNumberOfComponents())
1275     throw INTERP_KERNEL::Exception("DataArrayChar::setPartOfValuesAdv : This and a do not have the same number of components !");
1276   if(tuplesSelec->getNumberOfComponents()!=2)
1277     throw INTERP_KERNEL::Exception("DataArrayChar::setPartOfValuesAdv : Expecting to have a tuple selector DataArrayChar instance with exactly 2 components !");
1278   int thisNt=getNumberOfTuples();
1279   int aNt=a->getNumberOfTuples();
1280   char *valsToSet=getPointer();
1281   const char *valsSrc=a->getConstPointer();
1282   for(const char *tuple=tuplesSelec->begin();tuple!=tuplesSelec->end();tuple+=2)
1283     {
1284       if(tuple[1]>=0 && tuple[1]<aNt)
1285         {
1286           if(tuple[0]>=0 && tuple[0]<thisNt)
1287             std::copy(valsSrc+nbOfComp*tuple[1],valsSrc+nbOfComp*(tuple[1]+1),valsToSet+nbOfComp*tuple[0]);
1288           else
1289             {
1290               std::ostringstream oss; oss << "DataArrayChar::setPartOfValuesAdv : Tuple #" << std::distance(tuplesSelec->begin(),tuple)/2;
1291               oss << " of 'tuplesSelec' request of tuple id #" << tuple[0] << " in 'this' ! It should be in [0," << thisNt << ") !";
1292               throw INTERP_KERNEL::Exception(oss.str().c_str());
1293             }
1294         }
1295       else
1296         {
1297           std::ostringstream oss; oss << "DataArrayChar::setPartOfValuesAdv : Tuple #" << std::distance(tuplesSelec->begin(),tuple)/2;
1298           oss << " of 'tuplesSelec' request of tuple id #" << tuple[1] << " in 'a' ! It should be in [0," << aNt << ") !";
1299           throw INTERP_KERNEL::Exception(oss.str().c_str());
1300         }
1301     }
1302 }
1303
1304 /*!
1305  * Copy some tuples from another DataArrayChar (\a aBase) into contiguous tuples
1306  * of \a this array. Textual data is not copied. Both arrays must have equal number of
1307  * components.
1308  * The tuples to assign to are defined by index of the first tuple, and
1309  * their number is defined by \a tuplesSelec->getNumberOfTuples().
1310  * The tuples to copy are defined by values of a DataArrayChar.
1311  * All components of selected tuples are copied.
1312  *  \param [in] tupleIdStart - index of the first tuple of \a this array to assign
1313  *              values to.
1314  *  \param [in] aBase - the array to copy values from.
1315  *  \param [in] tuplesSelec - the array specifying tuples of \a aBase to copy.
1316  *  \throw If \a this is not allocated.
1317  *  \throw If \a aBase is NULL.
1318  *  \throw If \a aBase is not allocated.
1319  *  \throw If \a tuplesSelec is NULL.
1320  *  \throw If \a tuplesSelec is not allocated.
1321  *  \throw If <em>this->getNumberOfComponents() != aBase->getNumberOfComponents()</em>.
1322  *  \throw If \a tuplesSelec->getNumberOfComponents() != 1.
1323  *  \throw If <em>tupleIdStart + tuplesSelec->getNumberOfTuples() > this->getNumberOfTuples().</em>
1324  *  \throw If any tuple index given by \a tuplesSelec is out of a valid range for 
1325  *         \a aBase array.
1326  */
1327 void DataArrayChar::setContigPartOfSelectedValues(int tupleIdStart, const DataArray *aBase, const DataArrayInt *tuplesSelec)
1328 {
1329   if(!aBase || !tuplesSelec)
1330     throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues : input DataArray is NULL !");
1331   const DataArrayChar *a=dynamic_cast<const DataArrayChar *>(aBase);
1332   if(!a)
1333     throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues : input DataArray aBase is not a DataArrayChar !");
1334   checkAllocated();
1335   a->checkAllocated();
1336   tuplesSelec->checkAllocated();
1337   int nbOfComp=getNumberOfComponents();
1338   if(nbOfComp!=a->getNumberOfComponents())
1339     throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues : This and a do not have the same number of components !");
1340   if(tuplesSelec->getNumberOfComponents()!=1)
1341     throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues : Expecting to have a tuple selector DataArrayChar instance with exactly 1 component !");
1342   int thisNt=getNumberOfTuples();
1343   int aNt=a->getNumberOfTuples();
1344   int nbOfTupleToWrite=tuplesSelec->getNumberOfTuples();
1345   char *valsToSet=getPointer()+tupleIdStart*nbOfComp;
1346   if(tupleIdStart+nbOfTupleToWrite>thisNt)
1347     throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues : invalid number range of values to write !");
1348   const char *valsSrc=a->getConstPointer();
1349   for(const int *tuple=tuplesSelec->begin();tuple!=tuplesSelec->end();tuple++,valsToSet+=nbOfComp)
1350     {
1351       if(*tuple>=0 && *tuple<aNt)
1352         {
1353           std::copy(valsSrc+nbOfComp*(*tuple),valsSrc+nbOfComp*(*tuple+1),valsToSet);
1354         }
1355       else
1356         {
1357           std::ostringstream oss; oss << "DataArrayChar::setContigPartOfSelectedValues : Tuple #" << std::distance(tuplesSelec->begin(),tuple);
1358           oss << " of 'tuplesSelec' request of tuple id #" << *tuple << " in 'a' ! It should be in [0," << aNt << ") !";
1359           throw INTERP_KERNEL::Exception(oss.str().c_str());
1360         }
1361     }
1362 }
1363
1364 /*!
1365  * Copy some tuples from another DataArrayChar (\a aBase) into contiguous tuples
1366  * of \a this array. Textual data is not copied. Both arrays must have equal number of
1367  * components.
1368  * The tuples to copy are defined by three values similar to parameters of
1369  * the Python function \c range(\c start,\c stop,\c step).
1370  * The tuples to assign to are defined by index of the first tuple, and
1371  * their number is defined by number of tuples to copy.
1372  * All components of selected tuples are copied.
1373  *  \param [in] tupleIdStart - index of the first tuple of \a this array to assign
1374  *              values to.
1375  *  \param [in] aBase - the array to copy values from.
1376  *  \param [in] bg - index of the first tuple to copy of the array \a aBase.
1377  *  \param [in] end2 - index of the tuple of \a aBase before which the tuples to copy
1378  *              are located.
1379  *  \param [in] step - index increment to get index of the next tuple to copy.
1380  *  \throw If \a this is not allocated.
1381  *  \throw If \a aBase is NULL.
1382  *  \throw If \a aBase is not allocated.
1383  *  \throw If <em>this->getNumberOfComponents() != aBase->getNumberOfComponents()</em>.
1384  *  \throw If <em>tupleIdStart + len(range(bg,end2,step)) > this->getNumberOfTuples().</em>
1385  *  \throw If parameters specifying tuples to copy, do not give a
1386  *            non-empty range of increasing indices or indices are out of a valid range
1387  *            for the array \a aBase.
1388  */
1389 void DataArrayChar::setContigPartOfSelectedValuesSlice(int tupleIdStart, const DataArray *aBase, int bg, int end2, int step)
1390 {
1391   if(!aBase)
1392     throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValuesSlice : input DataArray is NULL !");
1393   const DataArrayChar *a=dynamic_cast<const DataArrayChar *>(aBase);
1394   if(!a)
1395     throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValuesSlice : input DataArray aBase is not a DataArrayChar !");
1396   checkAllocated();
1397   a->checkAllocated();
1398   int nbOfComp=getNumberOfComponents();
1399   const char msg[]="DataArrayChar::setContigPartOfSelectedValuesSlice";
1400   int nbOfTupleToWrite=DataArray::GetNumberOfItemGivenBES(bg,end2,step,msg);
1401   if(nbOfComp!=a->getNumberOfComponents())
1402     throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValuesSlice : This and a do not have the same number of components !");
1403   int thisNt=getNumberOfTuples();
1404   int aNt=a->getNumberOfTuples();
1405   char *valsToSet=getPointer()+tupleIdStart*nbOfComp;
1406   if(tupleIdStart+nbOfTupleToWrite>thisNt)
1407     throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValuesSlice : invalid number range of values to write !");
1408   if(end2>aNt)
1409     throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValuesSlice : invalid range of values to read !");
1410   const char *valsSrc=a->getConstPointer()+bg*nbOfComp;
1411   for(int i=0;i<nbOfTupleToWrite;i++,valsToSet+=nbOfComp,valsSrc+=step*nbOfComp)
1412     {
1413       std::copy(valsSrc,valsSrc+nbOfComp,valsToSet);
1414     }
1415 }
1416
1417 /*!
1418  * Returns a shorten copy of \a this array. The new DataArrayChar contains ranges
1419  * of tuples specified by \a ranges parameter.
1420  * For more info on renumbering see \ref numbering.
1421  *  \param [in] ranges - std::vector of std::pair's each of which defines a range
1422  *              of tuples in [\c begin,\c end) format.
1423  *  \return DataArrayChar * - the new instance of DataArrayChar that the caller
1424  *          is to delete using decrRef() as it is no more needed.
1425  *  \throw If \a end < \a begin.
1426  *  \throw If \a end > \a this->getNumberOfTuples().
1427  *  \throw If \a this is not allocated.
1428  */
1429 DataArray *DataArrayChar::selectByTupleRanges(const std::vector<std::pair<int,int> >& ranges) const
1430 {
1431   checkAllocated();
1432   int nbOfComp=getNumberOfComponents();
1433   int nbOfTuplesThis=getNumberOfTuples();
1434   if(ranges.empty())
1435     {
1436       MCAuto<DataArrayChar> ret=buildEmptySpecializedDAChar();
1437       ret->alloc(0,nbOfComp);
1438       ret->copyStringInfoFrom(*this);
1439       return ret.retn();
1440     }
1441   int ref=ranges.front().first;
1442   int nbOfTuples=0;
1443   bool isIncreasing=true;
1444   for(std::vector<std::pair<int,int> >::const_iterator it=ranges.begin();it!=ranges.end();it++)
1445     {
1446       if((*it).first<=(*it).second)
1447         {
1448           if((*it).first>=0 && (*it).second<=nbOfTuplesThis)
1449             {
1450               nbOfTuples+=(*it).second-(*it).first;
1451               if(isIncreasing)
1452                 isIncreasing=ref<=(*it).first;
1453               ref=(*it).second;
1454             }
1455           else
1456             {
1457               std::ostringstream oss; oss << "DataArrayChar::selectByTupleRanges : on range #" << std::distance(ranges.begin(),it);
1458               oss << " (" << (*it).first << "," << (*it).second << ") is greater than number of tuples of this :" << nbOfTuples << " !";
1459               throw INTERP_KERNEL::Exception(oss.str().c_str());
1460             }
1461         }
1462       else
1463         {
1464           std::ostringstream oss; oss << "DataArrayChar::selectByTupleRanges : on range #" << std::distance(ranges.begin(),it);
1465           oss << " (" << (*it).first << "," << (*it).second << ") end is before begin !";
1466           throw INTERP_KERNEL::Exception(oss.str().c_str());
1467         }
1468     }
1469   if(isIncreasing && nbOfTuplesThis==nbOfTuples)
1470     return deepCopy();
1471   MCAuto<DataArrayChar> ret=buildEmptySpecializedDAChar();
1472   ret->alloc(nbOfTuples,nbOfComp);
1473   ret->copyStringInfoFrom(*this);
1474   const char *src=getConstPointer();
1475   char *work=ret->getPointer();
1476   for(std::vector<std::pair<int,int> >::const_iterator it=ranges.begin();it!=ranges.end();it++)
1477     work=std::copy(src+(*it).first*nbOfComp,src+(*it).second*nbOfComp,work);
1478   return ret.retn();
1479 }
1480
1481 /*!
1482  * Returns a value located at specified tuple and component.
1483  * This method is equivalent to DataArrayChar::getIJ() except that validity of
1484  * parameters is checked. So this method is safe but expensive if used to go through
1485  * all values of \a this.
1486  *  \param [in] tupleId - index of tuple of interest.
1487  *  \param [in] compoId - index of component of interest.
1488  *  \return char - value located by \a tupleId and \a compoId.
1489  *  \throw If \a this is not allocated.
1490  *  \throw If condition <em>( 0 <= tupleId < this->getNumberOfTuples() )</em> is violated.
1491  *  \throw If condition <em>( 0 <= compoId < this->getNumberOfComponents() )</em> is violated.
1492  */
1493 char DataArrayChar::getIJSafe(int tupleId, int compoId) const
1494 {
1495   checkAllocated();
1496   if(tupleId<0 || tupleId>=getNumberOfTuples())
1497     {
1498       std::ostringstream oss; oss << "DataArrayChar::getIJSafe : request for tupleId " << tupleId << " should be in [0," << getNumberOfTuples() << ") !";
1499       throw INTERP_KERNEL::Exception(oss.str().c_str());
1500     }
1501   if(compoId<0 || compoId>=getNumberOfComponents())
1502     {
1503       std::ostringstream oss; oss << "DataArrayChar::getIJSafe : request for compoId " << compoId << " should be in [0," << getNumberOfComponents() << ") !";
1504       throw INTERP_KERNEL::Exception(oss.str().c_str());
1505     }
1506   return _mem[tupleId*_info_on_compo.size()+compoId];
1507 }
1508
1509 /*!
1510  * Returns the first value of \a this. 
1511  *  \return char - the last value of \a this array.
1512  *  \throw If \a this is not allocated.
1513  *  \throw If \a this->getNumberOfComponents() != 1.
1514  *  \throw If \a this->getNumberOfTuples() < 1.
1515  */
1516 char DataArrayChar::front() const
1517 {
1518   checkAllocated();
1519   if(getNumberOfComponents()!=1)
1520     throw INTERP_KERNEL::Exception("DataArrayChar::front : number of components not equal to one !");
1521   int nbOfTuples=getNumberOfTuples();
1522   if(nbOfTuples<1)
1523     throw INTERP_KERNEL::Exception("DataArrayChar::front : number of tuples must be >= 1 !");
1524   return *(getConstPointer());
1525 }
1526
1527 /*!
1528  * Returns the last value of \a this. 
1529  *  \return char - the last value of \a this array.
1530  *  \throw If \a this is not allocated.
1531  *  \throw If \a this->getNumberOfComponents() != 1.
1532  *  \throw If \a this->getNumberOfTuples() < 1.
1533  */
1534 char DataArrayChar::back() const
1535 {
1536   checkAllocated();
1537   if(getNumberOfComponents()!=1)
1538     throw INTERP_KERNEL::Exception("DataArrayChar::back : number of components not equal to one !");
1539   int nbOfTuples=getNumberOfTuples();
1540   if(nbOfTuples<1)
1541     throw INTERP_KERNEL::Exception("DataArrayChar::back : number of tuples must be >= 1 !");
1542   return *(getConstPointer()+nbOfTuples-1);
1543 }
1544
1545 /*!
1546  * Creates a new DataArrayChar containing IDs (indices) of tuples holding value equal to a
1547  * given one.
1548  *  \param [in] val - the value to find within \a this.
1549  *  \return DataArrayChar * - a new instance of DataArrayChar. The caller is to delete this
1550  *          array using decrRef() as it is no more needed.
1551  *  \throw If \a this is not allocated.
1552  *  \throw If \a this->getNumberOfComponents() != 1.
1553  */
1554 DataArrayInt *DataArrayChar::findIdsEqual(char val) const
1555 {
1556   checkAllocated();
1557   if(getNumberOfComponents()!=1)
1558     throw INTERP_KERNEL::Exception("DataArrayChar::findIdsEqual : the array must have only one component, you can call 'rearrange' method before !");
1559   const char *cptr=getConstPointer();
1560   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
1561   int nbOfTuples=getNumberOfTuples();
1562   for(int i=0;i<nbOfTuples;i++,cptr++)
1563     if(*cptr==val)
1564       ret->pushBackSilent(i);
1565   return ret.retn();
1566 }
1567
1568 /*!
1569  * Creates a new DataArrayChar containing IDs (indices) of tuples holding value \b not
1570  * equal to a given one. 
1571  *  \param [in] val - the value to ignore within \a this.
1572  *  \return DataArrayChar * - a new instance of DataArrayChar. The caller is to delete this
1573  *          array using decrRef() as it is no more needed.
1574  *  \throw If \a this is not allocated.
1575  *  \throw If \a this->getNumberOfComponents() != 1.
1576  */
1577 DataArrayInt *DataArrayChar::findIdsNotEqual(char val) const
1578 {
1579   checkAllocated();
1580   if(getNumberOfComponents()!=1)
1581     throw INTERP_KERNEL::Exception("DataArrayChar::findIdsNotEqual : the array must have only one component, you can call 'rearrange' method before !");
1582   const char *cptr=getConstPointer();
1583   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
1584   int nbOfTuples=getNumberOfTuples();
1585   for(int i=0;i<nbOfTuples;i++,cptr++)
1586     if(*cptr!=val)
1587       ret->pushBackSilent(i);
1588   return ret.retn();
1589 }
1590
1591 /*!
1592  * This method searches the sequence specified in input parameter \b vals in \b this.
1593  * This works only for DataArrayChar having number of components equal to one (if not an INTERP_KERNEL::Exception will be thrown).
1594  * This method differs from DataArrayChar::findIdFirstEqualTuple in that the position is internal raw data is not considered here contrary to DataArrayChar::findIdFirstEqualTuple.
1595  * \sa DataArrayChar::findIdFirstEqualTuple
1596  */
1597 int DataArrayChar::findIdSequence(const std::vector<char>& vals) const
1598 {
1599   checkAllocated();
1600   int nbOfCompo=getNumberOfComponents();
1601   if(nbOfCompo!=1)
1602     throw INTERP_KERNEL::Exception("DataArrayChar::findIdSequence : works only for DataArrayChar instance with one component !");
1603   const char *cptr=getConstPointer();
1604   std::size_t nbOfVals=getNbOfElems();
1605   const char *loc=std::search(cptr,cptr+nbOfVals,vals.begin(),vals.end());
1606   if(loc!=cptr+nbOfVals)
1607     return std::distance(cptr,loc);
1608   return -1;
1609 }
1610
1611 /*!
1612  * This method is an extension of DataArrayChar::findIdFirstEqual method because this method works for DataArrayChar with
1613  * any number of components excepted 0 (an INTERP_KERNEL::Exception is thrown in this case).
1614  * This method searches in \b this is there is a tuple that matched the input parameter \b tupl.
1615  * If any the tuple id is returned. If not -1 is returned.
1616  * 
1617  * This method throws an INTERP_KERNEL::Exception if the number of components in \b this mismatches with the size of
1618  * the input vector. An INTERP_KERNEL::Exception is thrown too if \b this is not allocated.
1619  *
1620  * \return tuple id where \b tupl is. -1 if no such tuple exists in \b this.
1621  * \sa DataArrayChar::findIdSequence.
1622  */
1623 int DataArrayChar::findIdFirstEqualTuple(const std::vector<char>& tupl) const
1624 {
1625   checkAllocated();
1626   int nbOfCompo=getNumberOfComponents();
1627   if(nbOfCompo==0)
1628     throw INTERP_KERNEL::Exception("DataArrayChar::findIdFirstEqualTuple : 0 components in 'this' !");
1629   if(nbOfCompo!=(int)tupl.size())
1630     {
1631       std::ostringstream oss; oss << "DataArrayChar::findIdFirstEqualTuple : 'this' contains " << nbOfCompo << " components and searching for a tuple of length " << tupl.size() << " !";
1632       throw INTERP_KERNEL::Exception(oss.str().c_str());
1633     }
1634   const char *cptr=getConstPointer();
1635   std::size_t nbOfVals=getNbOfElems();
1636   for(const char *work=cptr;work!=cptr+nbOfVals;)
1637     {
1638       work=std::search(work,cptr+nbOfVals,tupl.begin(),tupl.end());
1639       if(work!=cptr+nbOfVals)
1640         {
1641           if(std::distance(cptr,work)%nbOfCompo!=0)
1642             work++;
1643           else
1644             return std::distance(cptr,work)/nbOfCompo;
1645         }
1646     }
1647   return -1;
1648 }
1649
1650 /*!
1651  * This method is an extension of DataArrayChar::presenceOfValue method because this method works for DataArrayChar with
1652  * any number of components excepted 0 (an INTERP_KERNEL::Exception is thrown in this case).
1653  * This method searches in \b this is there is a tuple that matched the input parameter \b tupl.
1654  * This method throws an INTERP_KERNEL::Exception if the number of components in \b this mismatches with the size of
1655  * the input vector. An INTERP_KERNEL::Exception is thrown too if \b this is not allocated.
1656  * \sa DataArrayChar::findIdFirstEqualTuple
1657  */
1658 bool DataArrayChar::presenceOfTuple(const std::vector<char>& tupl) const
1659 {
1660   return findIdFirstEqualTuple(tupl)!=-1;
1661 }
1662
1663 /*!
1664  * Returns \a true if a given value is present within \a this one-dimensional array.
1665  *  \param [in] value - the value to find within \a this array.
1666  *  \return bool - \a true in case if \a value is present within \a this array.
1667  *  \throw If \a this is not allocated.
1668  *  \throw If \a this->getNumberOfComponents() != 1.
1669  *  \sa findIdFirstEqual()
1670  */
1671 bool DataArrayChar::presenceOfValue(char value) const
1672 {
1673   return findIdFirstEqual(value)!=-1;
1674 }
1675
1676 /*!
1677  * This method expects to be called when number of components of this is equal to one.
1678  * This method returns true if it exists a tuple so that the value is contained in \b vals.
1679  * If not any tuple contains one of the values contained in 'vals' false is returned.
1680  * \sa DataArrayChar::findIdFirstEqual
1681  */
1682 bool DataArrayChar::presenceOfValue(const std::vector<char>& vals) const
1683 {
1684   return findIdFirstEqual(vals)!=-1;
1685 }
1686
1687 /*!
1688  * This method expects to be called when number of components of this is equal to one.
1689  * This method returns the tuple id, if it exists, of the first tuple equal to \b value.
1690  * If not any tuple contains \b value -1 is returned.
1691  * \sa DataArrayChar::presenceOfValue
1692  */
1693 int DataArrayChar::findIdFirstEqual(char value) const
1694 {
1695   checkAllocated();
1696   if(getNumberOfComponents()!=1)
1697     throw INTERP_KERNEL::Exception("DataArrayChar::presenceOfValue : the array must have only one component, you can call 'rearrange' method before !");
1698   const char *cptr=getConstPointer();
1699   int nbOfTuples=getNumberOfTuples();
1700   const char *ret=std::find(cptr,cptr+nbOfTuples,value);
1701   if(ret!=cptr+nbOfTuples)
1702     return std::distance(cptr,ret);
1703   return -1;
1704 }
1705
1706 /*!
1707  * This method expects to be called when number of components of this is equal to one.
1708  * This method returns the tuple id, if it exists, of the first tuple so that the value is contained in \b vals.
1709  * If not any tuple contains one of the values contained in 'vals' false is returned.
1710  * \sa DataArrayChar::presenceOfValue
1711  */
1712 int DataArrayChar::findIdFirstEqual(const std::vector<char>& vals) const
1713 {
1714   checkAllocated();
1715   if(getNumberOfComponents()!=1)
1716     throw INTERP_KERNEL::Exception("DataArrayInt::presenceOfValue : the array must have only one component, you can call 'rearrange' method before !");
1717   std::set<char> vals2(vals.begin(),vals.end());
1718   const char *cptr=getConstPointer();
1719   int nbOfTuples=getNumberOfTuples();
1720   for(const char *w=cptr;w!=cptr+nbOfTuples;w++)
1721     if(vals2.find(*w)!=vals2.end())
1722       return std::distance(cptr,w);
1723   return -1;
1724 }
1725
1726 /*!
1727  * Returns the maximal value and its location within \a this one-dimensional array.
1728  *  \param [out] tupleId - index of the tuple holding the maximal value.
1729  *  \return char - the maximal value among all values of \a this array.
1730  *  \throw If \a this->getNumberOfComponents() != 1
1731  *  \throw If \a this->getNumberOfTuples() < 1
1732  */
1733 char DataArrayChar::getMaxValue(int& tupleId) const
1734 {
1735   checkAllocated();
1736   if(getNumberOfComponents()!=1)
1737     throw INTERP_KERNEL::Exception("DataArrayChar::getMaxValue : must be applied on DataArrayChar with only one component !");
1738   int nbOfTuples=getNumberOfTuples();
1739   if(nbOfTuples<=0)
1740     throw INTERP_KERNEL::Exception("DataArrayChar::getMaxValue : array exists but number of tuples must be > 0 !");
1741   const char *vals=getConstPointer();
1742   const char *loc=std::max_element(vals,vals+nbOfTuples);
1743   tupleId=(int)std::distance(vals,loc);
1744   return *loc;
1745 }
1746
1747 /*!
1748  * Returns the maximal value within \a this array that is allowed to have more than
1749  *  one component.
1750  *  \return char - the maximal value among all values of \a this array.
1751  *  \throw If \a this is not allocated.
1752  */
1753 char DataArrayChar::getMaxValueInArray() const
1754 {
1755   checkAllocated();
1756   const char *loc=std::max_element(begin(),end());
1757   return *loc;
1758 }
1759
1760 /*!
1761  * Returns the minimal value and its location within \a this one-dimensional array.
1762  *  \param [out] tupleId - index of the tuple holding the minimal value.
1763  *  \return char - the minimal value among all values of \a this array.
1764  *  \throw If \a this->getNumberOfComponents() != 1
1765  *  \throw If \a this->getNumberOfTuples() < 1
1766  */
1767 char DataArrayChar::getMinValue(int& tupleId) const
1768 {
1769   checkAllocated();
1770   if(getNumberOfComponents()!=1)
1771     throw INTERP_KERNEL::Exception("DataArrayChar::getMaxValue : must be applied on DataArrayChar with only one component !");
1772   int nbOfTuples=getNumberOfTuples();
1773   if(nbOfTuples<=0)
1774     throw INTERP_KERNEL::Exception("DataArrayChar::getMaxValue : array exists but number of tuples must be > 0 !");
1775   const char *vals=getConstPointer();
1776   const char *loc=std::min_element(vals,vals+nbOfTuples);
1777   tupleId=(int)std::distance(vals,loc);
1778   return *loc;
1779 }
1780
1781 /*!
1782  * Returns the minimal value within \a this array that is allowed to have more than
1783  *  one component.
1784  *  \return char - the minimal value among all values of \a this array.
1785  *  \throw If \a this is not allocated.
1786  */
1787 char DataArrayChar::getMinValueInArray() const
1788 {
1789   checkAllocated();
1790   const char *loc=std::min_element(begin(),end());
1791   return *loc;
1792 }
1793
1794 /*!
1795  * This method works only on data array with one component.
1796  * This method returns a newly allocated array storing stored ascendantly tuple ids in \b this so that
1797  * this[*id] in [\b vmin,\b vmax)
1798  * 
1799  * \param [in] vmin begin of range. This value is included in range.
1800  * \param [in] vmax end of range. This value is \b not included in range.
1801  * \return a newly allocated data array that the caller should deal with.
1802  */
1803 DataArrayInt *DataArrayChar::findIdsInRange(char vmin, char vmax) const
1804 {
1805   checkAllocated();
1806   if(getNumberOfComponents()!=1)
1807     throw INTERP_KERNEL::Exception("DataArrayChar::findIdsInRange : this must have exactly one component !");
1808   const char *cptr=getConstPointer();
1809   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
1810   int nbOfTuples=getNumberOfTuples();
1811   for(int i=0;i<nbOfTuples;i++,cptr++)
1812     if(*cptr>=vmin && *cptr<vmax)
1813       ret->pushBackSilent(i);
1814   return ret.retn();
1815 }
1816
1817 /*!
1818  * Returns a new DataArrayChar by concatenating two given arrays, so that (1) the number
1819  * of tuples in the result array is <em> a1->getNumberOfTuples() + a2->getNumberOfTuples() -
1820  * offsetA2</em> and (2)
1821  * the number of component in the result array is same as that of each of given arrays.
1822  * First \a offsetA2 tuples of \a a2 are skipped and thus are missing from the result array.
1823  * Info on components is copied from the first of the given arrays. Number of components
1824  * in the given arrays must be the same.
1825  *  \param [in] a1 - an array to include in the result array.
1826  *  \param [in] a2 - another array to include in the result array.
1827  *  \param [in] offsetA2 - number of tuples of \a a2 to skip.
1828  *  \return DataArrayChar * - the new instance of DataArrayChar.
1829  *          The caller is to delete this result array using decrRef() as it is no more
1830  *          needed.
1831  *  \throw If either \a a1 or \a a2 is NULL.
1832  *  \throw If \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents().
1833  */
1834 DataArrayChar *DataArrayChar::Aggregate(const DataArrayChar *a1, const DataArrayChar *a2)
1835 {
1836   if(!a1 || !a2)
1837     throw INTERP_KERNEL::Exception("DataArrayChar::Aggregate : input DataArrayChar instance is NULL !");
1838   std::vector<const DataArrayChar *> v(2); v[0]=a1; v[1]=a2;
1839   return Aggregate(v);
1840 }
1841
1842 /*!
1843  * Returns a new DataArrayChar by concatenating all given arrays, so that (1) the number
1844  * of tuples in the result array is a sum of the number of tuples of given arrays and (2)
1845  * the number of component in the result array is same as that of each of given arrays.
1846  * Info on components is copied from the first of the given arrays. Number of components
1847  * in the given arrays must be  the same.
1848  *  \param [in] arr - a sequence of arrays to include in the result array.
1849  *  \return DataArrayChar * - the new instance of DataArrayChar.
1850  *          The caller is to delete this result array using decrRef() as it is no more
1851  *          needed.
1852  *  \throw If all arrays within \a arr are NULL.
1853  *  \throw If getNumberOfComponents() of arrays within \a arr.
1854  */
1855 DataArrayChar *DataArrayChar::Aggregate(const std::vector<const DataArrayChar *>& arr)
1856 {
1857   std::vector<const DataArrayChar *> a;
1858   for(std::vector<const DataArrayChar *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
1859     if(*it4)
1860       a.push_back(*it4);
1861   if(a.empty())
1862     throw INTERP_KERNEL::Exception("DataArrayChar::Aggregate : input list must be NON EMPTY !");
1863   std::vector<const DataArrayChar *>::const_iterator it=a.begin();
1864   int nbOfComp=(*it)->getNumberOfComponents();
1865   int nbt=(*it++)->getNumberOfTuples();
1866   for(int i=1;it!=a.end();it++,i++)
1867     {
1868       if((*it)->getNumberOfComponents()!=nbOfComp)
1869         throw INTERP_KERNEL::Exception("DataArrayChar::Aggregate : Nb of components mismatch for array aggregation !");
1870       nbt+=(*it)->getNumberOfTuples();
1871     }
1872   MCAuto<DataArrayChar> ret=a[0]->buildEmptySpecializedDAChar();
1873   ret->alloc(nbt,nbOfComp);
1874   char *pt=ret->getPointer();
1875   for(it=a.begin();it!=a.end();it++)
1876     pt=std::copy((*it)->getConstPointer(),(*it)->getConstPointer()+(*it)->getNbOfElems(),pt);
1877   ret->copyStringInfoFrom(*(a[0]));
1878   return ret.retn();
1879 }
1880
1881 /*!
1882  * Returns a new DataArrayChar by aggregating two given arrays, so that (1) the number
1883  * of components in the result array is a sum of the number of components of given arrays
1884  * and (2) the number of tuples in the result array is same as that of each of given
1885  * arrays. In other words the i-th tuple of result array includes all components of
1886  * i-th tuples of all given arrays.
1887  * Number of tuples in the given arrays must be the same.
1888  *  \param [in] a1 - an array to include in the result array.
1889  *  \param [in] a2 - another array to include in the result array.
1890  *  \return DataArrayChar * - the new instance of DataArrayChar.
1891  *          The caller is to delete this result array using decrRef() as it is no more
1892  *          needed.
1893  *  \throw If both \a a1 and \a a2 are NULL.
1894  *  \throw If any given array is not allocated.
1895  *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples()
1896  */
1897 DataArrayChar *DataArrayChar::Meld(const DataArrayChar *a1, const DataArrayChar *a2)
1898 {
1899   std::vector<const DataArrayChar *> arr(2);
1900   arr[0]=a1; arr[1]=a2;
1901   return Meld(arr);
1902 }
1903
1904 /*!
1905  * Returns a new DataArrayChar by aggregating all given arrays, so that (1) the number
1906  * of components in the result array is a sum of the number of components of given arrays
1907  * and (2) the number of tuples in the result array is same as that of each of given
1908  * arrays. In other words the i-th tuple of result array includes all components of
1909  * i-th tuples of all given arrays.
1910  * Number of tuples in the given arrays must be  the same.
1911  *  \param [in] arr - a sequence of arrays to include in the result array.
1912  *  \return DataArrayChar * - the new instance of DataArrayChar.
1913  *          The caller is to delete this result array using decrRef() as it is no more
1914  *          needed.
1915  *  \throw If all arrays within \a arr are NULL.
1916  *  \throw If any given array is not allocated.
1917  *  \throw If getNumberOfTuples() of arrays within \a arr is different.
1918  */
1919 DataArrayChar *DataArrayChar::Meld(const std::vector<const DataArrayChar *>& arr)
1920 {
1921   std::vector<const DataArrayChar *> a;
1922   for(std::vector<const DataArrayChar *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
1923     if(*it4)
1924       a.push_back(*it4);
1925   if(a.empty())
1926     throw INTERP_KERNEL::Exception("DataArrayChar::Meld : array must be NON empty !");
1927   std::vector<const DataArrayChar *>::const_iterator it;
1928   for(it=a.begin();it!=a.end();it++)
1929     (*it)->checkAllocated();
1930   it=a.begin();
1931   int nbOfTuples=(*it)->getNumberOfTuples();
1932   std::vector<int> nbc(a.size());
1933   std::vector<const char *> pts(a.size());
1934   nbc[0]=(*it)->getNumberOfComponents();
1935   pts[0]=(*it++)->getConstPointer();
1936   for(int i=1;it!=a.end();it++,i++)
1937     {
1938       if(nbOfTuples!=(*it)->getNumberOfTuples())
1939         throw INTERP_KERNEL::Exception("DataArrayChar::meld : mismatch of number of tuples !");
1940       nbc[i]=(*it)->getNumberOfComponents();
1941       pts[i]=(*it)->getConstPointer();
1942     }
1943   int totalNbOfComp=std::accumulate(nbc.begin(),nbc.end(),0);
1944   DataArrayChar *ret=a[0]->buildEmptySpecializedDAChar();
1945   ret->alloc(nbOfTuples,totalNbOfComp);
1946   char *retPtr=ret->getPointer();
1947   for(int i=0;i<nbOfTuples;i++)
1948     for(int j=0;j<(int)a.size();j++)
1949       {
1950         retPtr=std::copy(pts[j],pts[j]+nbc[j],retPtr);
1951         pts[j]+=nbc[j];
1952       }
1953   int k=0;
1954   for(int i=0;i<(int)a.size();i++)
1955     for(int j=0;j<nbc[i];j++,k++)
1956       ret->setInfoOnComponent(k,a[i]->getInfoOnComponent(j));
1957   return ret;
1958 }
1959
1960 /*!
1961  * Sets a C array to be used as raw data of \a this. The previously set info
1962  *  of components is retained and re-sized. 
1963  * For more info see \ref MEDCouplingArraySteps1.
1964  *  \param [in] array - the C array to be used as raw data of \a this.
1965  *  \param [in] ownership - if \a true, \a array will be deallocated at destruction of \a this.
1966  *  \param [in] type - specifies how to deallocate \a array. If \a type == MEDCoupling::CPP_DEALLOC,
1967  *                     \c delete [] \c array; will be called. If \a type == MEDCoupling::C_DEALLOC,
1968  *                     \c free(\c array ) will be called.
1969  *  \param [in] nbOfTuple - new number of tuples in \a this.
1970  *  \param [in] nbOfCompo - new number of components in \a this.
1971  */
1972 void DataArrayChar::useArray(const char *array, bool ownership,  DeallocType type, int nbOfTuple, int nbOfCompo)
1973 {
1974   _info_on_compo.resize(nbOfCompo);
1975   _mem.useArray(array,ownership,type,(std::size_t)nbOfTuple*nbOfCompo);
1976   declareAsNew();
1977 }
1978
1979 void DataArrayChar::useExternalArrayWithRWAccess(const char *array, int nbOfTuple, int nbOfCompo)
1980 {
1981   _info_on_compo.resize(nbOfCompo);
1982   _mem.useExternalArrayWithRWAccess(array,(std::size_t)nbOfTuple*nbOfCompo);
1983   declareAsNew();
1984 }
1985
1986 /*!
1987  * Returns a new instance of DataArrayByte. The caller is to delete this array
1988  * using decrRef() as it is no more needed. 
1989  */
1990 DataArrayByte *DataArrayByte::New()
1991 {
1992   return new DataArrayByte;
1993 }
1994
1995 DataArrayByteIterator *DataArrayByte::iterator()
1996 {
1997   return new DataArrayByteIterator(this);
1998 }
1999
2000 /*!
2001  * Returns a full copy of \a this. For more info on copying data arrays see
2002  * \ref MEDCouplingArrayBasicsCopyDeep.
2003  *  \return DataArrayByte * - a new instance of DataArrayByte.
2004  */
2005 DataArrayByte *DataArrayByte::deepCopy() const
2006 {
2007   return new DataArrayByte(*this);
2008 }
2009
2010 /*!
2011  * Returns either a \a deep or \a shallow copy of this array. For more info see
2012  * \ref MEDCouplingArrayBasicsCopyDeep and \ref MEDCouplingArrayBasicsCopyShallow.
2013  *  \param [in] dCpy - if \a true, a deep copy is returned, else, a shallow one.
2014  *  \return DataArrayByte * - either a new instance of DataArrayByte (if \a dCpy
2015  *          == \a true) or \a this instance (if \a dCpy == \a false).
2016  */
2017 DataArrayByte *DataArrayByte::performCopyOrIncrRef(bool dCpy) const
2018 {
2019   if(dCpy)
2020     return deepCopy();
2021   else
2022     {
2023       incrRef();
2024       return const_cast<DataArrayByte *>(this);
2025     }
2026 }
2027
2028 /*!
2029  * Returns the only one value in \a this, if and only if number of elements
2030  * (nb of tuples * nb of components) is equal to 1, and that \a this is allocated.
2031  *  \return char - the sole value stored in \a this array.
2032  *  \throw If at least one of conditions stated above is not fulfilled.
2033  */
2034 char DataArrayByte::byteValue() const
2035 {
2036   if(isAllocated())
2037     {
2038       if(getNbOfElems()==1)
2039         {
2040           return *getConstPointer();
2041         }
2042       else
2043         throw INTERP_KERNEL::Exception("DataArrayByte::byteValue : DataArrayByte instance is allocated but number of elements is not equal to 1 !");
2044     }
2045   else
2046     throw INTERP_KERNEL::Exception("DataArrayByte::byteValue : DataArrayByte instance is not allocated !");
2047 }
2048
2049 DataArrayChar *DataArrayByte::buildEmptySpecializedDAChar() const
2050 {
2051   return DataArrayByte::New();
2052 }
2053
2054 void DataArrayByte::reprStream(std::ostream& stream) const
2055 {
2056   stream << "Name of byte array : \"" << _name << "\"\n";
2057   reprWithoutNameStream(stream);
2058 }
2059
2060 void DataArrayByte::reprZipStream(std::ostream& stream) const
2061 {
2062   stream << "Name of byte array : \"" << _name << "\"\n";
2063   reprZipWithoutNameStream(stream);
2064 }
2065
2066 void DataArrayByte::reprWithoutNameStream(std::ostream& stream) const
2067 {
2068   DataArray::reprWithoutNameStream(stream);
2069   if(_mem.reprHeader(getNumberOfComponents(),stream))
2070     {
2071       const char *data=begin();
2072       int nbOfTuples=getNumberOfTuples();
2073       int nbCompo=getNumberOfComponents();
2074       for(int i=0;i<nbOfTuples;i++,data+=nbCompo)
2075         {
2076           stream << "Tuple #" << i << " : ";
2077           std::copy(data,data+nbCompo,std::ostream_iterator<int>(stream," "));//it is not a bug int here not char because it is not ASCII here contrary to DataArrayAsciiChar
2078           stream << "\n";
2079         }
2080     }
2081 }
2082
2083 void DataArrayByte::reprZipWithoutNameStream(std::ostream& stream) const
2084 {
2085   DataArray::reprWithoutNameStream(stream);
2086   _mem.reprZip(getNumberOfComponents(),stream);
2087 }
2088
2089 void DataArrayByte::reprCppStream(const std::string& varName, std::ostream& stream) const
2090 {
2091   int nbTuples=getNumberOfTuples(),nbComp=getNumberOfComponents();
2092   const char *data=getConstPointer();
2093   stream << "DataArrayByte *" << varName << "=DataArrayByte::New();" << std::endl;
2094   if(nbTuples*nbComp>=1)
2095     {
2096       stream << "const char " << varName << "Data[" << nbTuples*nbComp << "]={";
2097       std::copy(data,data+nbTuples*nbComp-1,std::ostream_iterator<char>(stream,","));
2098       stream << data[nbTuples*nbComp-1] << "};" << std::endl;
2099       stream << varName << "->useArray(" << varName << "Data,false,CPP_DEALLOC," << nbTuples << "," << nbComp << ");" << std::endl;
2100     }
2101   else
2102     stream << varName << "->alloc(" << nbTuples << "," << nbComp << ");" << std::endl;
2103   stream << varName << "->setName(\"" << getName() << "\");" << std::endl;
2104 }
2105
2106 /*!
2107  * Method that gives a quick overvien of \a this for python.
2108  */
2109 void DataArrayByte::reprQuickOverview(std::ostream& stream) const
2110 {
2111   static const std::size_t MAX_NB_OF_BYTE_IN_REPR=300;
2112   stream << "DataArrayByte C++ instance at " << this << ". ";
2113   if(isAllocated())
2114     {
2115       int nbOfCompo=(int)_info_on_compo.size();
2116       if(nbOfCompo>=1)
2117         {
2118           int nbOfTuples=getNumberOfTuples();
2119           stream << "Number of tuples : " << nbOfTuples << ". Number of components : " << nbOfCompo << "." << std::endl;
2120           reprQuickOverviewData(stream,MAX_NB_OF_BYTE_IN_REPR);
2121         }
2122       else
2123         stream << "Number of components : 0.";
2124     }
2125   else
2126     stream << "*** No data allocated ****";
2127 }
2128
2129 void DataArrayByte::reprQuickOverviewData(std::ostream& stream, std::size_t maxNbOfByteInRepr) const
2130 {
2131   const char *data=begin();
2132   int nbOfTuples=getNumberOfTuples();
2133   int nbOfCompo=(int)_info_on_compo.size();
2134   std::ostringstream oss2; oss2 << "[";
2135   std::string oss2Str(oss2.str());
2136   bool isFinished=true;
2137   for(int i=0;i<nbOfTuples && isFinished;i++)
2138     {
2139       if(nbOfCompo>1)
2140         {
2141           oss2 << "(";
2142           for(int j=0;j<nbOfCompo;j++,data++)
2143             {
2144               oss2 << (int)*data;
2145               if(j!=nbOfCompo-1) oss2 << ", ";
2146             }
2147           oss2 << ")";
2148         }
2149       else
2150         { oss2 << (int)*data; data++; }
2151       if(i!=nbOfTuples-1) oss2 << ", ";
2152       std::string oss3Str(oss2.str());
2153       if(oss3Str.length()<maxNbOfByteInRepr)
2154         oss2Str=oss3Str;
2155       else
2156         isFinished=false;
2157     }
2158   stream << oss2Str;
2159   if(!isFinished)
2160     stream << "... ";
2161   stream << "]";
2162 }
2163
2164 bool DataArrayByte::isEqualIfNotWhy(const DataArrayChar& other, std::string& reason) const
2165 {
2166   const DataArrayByte *otherC=dynamic_cast<const DataArrayByte *>(&other);
2167   if(!otherC)
2168     { reason="this is of type DataArrayByte whereas other is not a DataArrayByte instance"; return false; }
2169   return DataArrayChar::isEqualIfNotWhy(other,reason);
2170 }
2171
2172 /*!
2173  * This method is \b NOT wrapped into python because it can be useful only for performance reasons in C++ context.
2174  * \throw if \a this is not allocated.
2175  * \throw if \a this has not exactly one component.
2176  */
2177 std::vector<bool> DataArrayByte::toVectorOfBool() const
2178 {
2179   checkAllocated();
2180   if(getNumberOfComponents()!=1)
2181     throw INTERP_KERNEL::Exception("DataArrayByte::toVectorOfBool : this method can be used only if this has one component !");
2182   int nbt(getNumberOfTuples());
2183   std::vector<bool> ret(nbt,false);
2184   const char *pt(begin());
2185   for(int i=0;i<nbt;i++,pt++)
2186     if(*pt!=0)
2187       ret[i]=true;
2188   return ret;
2189 }
2190
2191 DataArrayByteIterator::DataArrayByteIterator(DataArrayByte *da):_da(da),_pt(0),_tuple_id(0),_nb_comp(0),_nb_tuple(0)
2192 {
2193   if(_da)
2194     {
2195       _da->incrRef();
2196       if(_da->isAllocated())
2197         {
2198           _nb_comp=da->getNumberOfComponents();
2199           _nb_tuple=da->getNumberOfTuples();
2200           _pt=da->getPointer();
2201         }
2202     }
2203 }
2204
2205 DataArrayByteIterator::~DataArrayByteIterator()
2206 {
2207   if(_da)
2208     _da->decrRef();
2209 }
2210
2211 DataArrayByteTuple *DataArrayByteIterator::nextt()
2212 {
2213   if(_tuple_id<_nb_tuple)
2214     {
2215       _tuple_id++;
2216       DataArrayByteTuple *ret=new DataArrayByteTuple(_pt,_nb_comp);
2217       _pt+=_nb_comp;
2218       return ret;
2219     }
2220   else
2221     return 0;
2222 }
2223
2224 DataArrayByteTuple::DataArrayByteTuple(char *pt, int nbOfComp):_pt(pt),_nb_of_compo(nbOfComp)
2225 {
2226 }
2227
2228 std::string DataArrayByteTuple::repr() const
2229 {
2230   std::ostringstream oss; oss << "(";
2231   for(int i=0;i<_nb_of_compo-1;i++)
2232     oss << (int)_pt[i] << ", ";
2233   oss << _pt[_nb_of_compo-1] << ")";
2234   return oss.str();
2235 }
2236
2237 char DataArrayByteTuple::byteValue() const
2238 {
2239   if(_nb_of_compo==1)
2240     return *_pt;
2241   throw INTERP_KERNEL::Exception("DataArrayByteTuple::byteValue : DataArrayByteTuple instance has not exactly 1 component -> Not possible to convert it into an character !");
2242 }
2243
2244 /*!
2245  * This method returns a newly allocated instance the caller should dealed with by a MEDCoupling::DataArrayByte::decrRef.
2246  * This method performs \b no copy of data. The content is only referenced using MEDCoupling::DataArrayByte::useArray with ownership set to \b false.
2247  * This method throws an INTERP_KERNEL::Exception is it is impossible to match sizes of \b this that is too say \b nbOfCompo=this->_nb_of_elem and \bnbOfTuples==1 or
2248  * \b nbOfCompo=1 and \bnbOfTuples==this->_nb_of_elem.
2249  */
2250 DataArrayByte *DataArrayByteTuple::buildDAByte(int nbOfTuples, int nbOfCompo) const
2251 {
2252   if((_nb_of_compo==nbOfCompo && nbOfTuples==1) || (_nb_of_compo==nbOfTuples && nbOfCompo==1))
2253     {
2254       DataArrayByte *ret=DataArrayByte::New();
2255       ret->useExternalArrayWithRWAccess(_pt,nbOfTuples,nbOfCompo);
2256       return ret;
2257     }
2258   else
2259     {
2260       std::ostringstream oss; oss << "DataArrayByteTuple::buildDAByte : unable to build a requested DataArrayByte instance with nbofTuple=" << nbOfTuples << " and nbOfCompo=" << nbOfCompo;
2261       oss << ".\nBecause the number of elements in this is " << _nb_of_compo << " !";
2262       throw INTERP_KERNEL::Exception(oss.str().c_str());
2263     }
2264 }
2265
2266 /*!
2267  * Returns a new instance of DataArrayAsciiChar. The caller is to delete this array
2268  * using decrRef() as it is no more needed. 
2269  */
2270 DataArrayAsciiChar *DataArrayAsciiChar::New()
2271 {
2272   return new DataArrayAsciiChar;
2273 }
2274
2275 /*!
2276  * Returns a new instance of DataArrayAsciiChar. The caller is to delete this array
2277  * using decrRef() as it is no more needed. 
2278  * \param [in] st the string. This input string should have a length greater than 0. If not an excpetion will be thrown.
2279  */
2280 DataArrayAsciiChar *DataArrayAsciiChar::New(const std::string& st)
2281 {
2282   return new DataArrayAsciiChar(st);
2283 }
2284
2285 /*!
2286  * \param [in] st the string. This input string should have a length greater than 0. If not an excpetion will be thrown.
2287  */
2288 DataArrayAsciiChar::DataArrayAsciiChar(const std::string& st)
2289 {
2290   std::size_t lgth=st.length();
2291   if(lgth==0)
2292     throw INTERP_KERNEL::Exception("DataArrayAsciiChar contructor with string ! Size of input string is null !");
2293   alloc(1,lgth);
2294   std::copy(st.begin(),st.begin()+lgth,getPointer());
2295 }
2296
2297 /*!
2298  * Returns a new instance of DataArrayAsciiChar. The caller is to delete this array
2299  * using decrRef() as it is no more needed. 
2300  * This constructor uses \a vst input vector of strings to initialize itself. For all strings whose length is lower than max length of strings in
2301  * \a vst the remaining locations in memory will be set to character \a defaultChar.
2302  *
2303  * \param [in] defaultChar the default character used to fill not defined locations in \a this
2304  * \param [in] vst vector of strings. This input vector must be non empty. \a this will have its component size set to the max lgth of strings contained
2305  *             in \a vst. If all strings are empty an INTERP_KERNEL::Exception will be thrown.
2306  *
2307  * \throw If input \a vst is empty.
2308  * \throw If all strings in \a vst are empty.
2309  */
2310 DataArrayAsciiChar *DataArrayAsciiChar::New(const std::vector<std::string>& vst, char defaultChar)
2311 {
2312   return new DataArrayAsciiChar(vst,defaultChar);
2313 }
2314
2315 /*!
2316  * This constructor uses \a vst input vector of strings to initialize itself. For all strings whose length is lower than max length of strings in
2317  * \a vst the remaining locations in memory will be set to character \a defaultChar.
2318  *
2319  * \param [in] defaultChar the default character used to fill not defined locations in \a this
2320  * \param [in] vst vector of strings. This input vector must be non empty. \a this will have its component size set to the max lgth of strings contained
2321  *             in \a vst. If all strings are empty an INTERP_KERNEL::Exception will be thrown.
2322  *
2323  * \throw If input \a vst is empty.
2324  * \throw If all strings in \a vst are empty.
2325  */
2326 DataArrayAsciiChar::DataArrayAsciiChar(const std::vector<std::string>& vst, char defaultChar)
2327 {
2328   if(vst.empty())
2329     throw INTERP_KERNEL::Exception("DataArrayAsciiChar contructor with vector of strings ! Empty array !");
2330   std::size_t nbCompo=0;
2331   for(std::vector<std::string>::const_iterator it=vst.begin();it!=vst.end();it++)
2332     nbCompo=std::max(nbCompo,(*it).length());
2333   if(nbCompo==0)
2334     throw INTERP_KERNEL::Exception("DataArrayAsciiChar contructor with vector of strings ! All strings in not empty vector are empty !");
2335   int nbTuples=(int)vst.size();
2336   alloc(nbTuples,(int)nbCompo);
2337   char *pt=getPointer();
2338   for(int i=0;i<nbTuples;i++,pt+=nbCompo)
2339     {
2340       const std::string& tmp=vst[i];
2341       std::size_t sz=tmp.length();
2342       std::copy(tmp.begin(),tmp.begin()+sz,pt);
2343       std::fill(pt+sz,pt+nbCompo,defaultChar);
2344     }
2345 }
2346
2347 DataArrayAsciiCharIterator *DataArrayAsciiChar::iterator()
2348 {
2349   return new DataArrayAsciiCharIterator(this);
2350 }
2351
2352 /*!
2353  * Returns a full copy of \a this. For more info on copying data arrays see
2354  * \ref MEDCouplingArrayBasicsCopyDeep.
2355  *  \return DataArrayAsciiChar * - a new instance of DataArrayAsciiChar.
2356  */
2357 DataArrayAsciiChar *DataArrayAsciiChar::deepCopy() const
2358 {
2359   return new DataArrayAsciiChar(*this);
2360 }
2361
2362 /*!
2363  * Returns either a \a deep or \a shallow copy of this array. For more info see
2364  * \ref MEDCouplingArrayBasicsCopyDeep and \ref MEDCouplingArrayBasicsCopyShallow.
2365  *  \param [in] dCpy - if \a true, a deep copy is returned, else, a shallow one.
2366  *  \return DataArrayAsciiChar * - either a new instance of DataArrayAsciiChar (if \a dCpy
2367  *          == \a true) or \a this instance (if \a dCpy == \a false).
2368  */
2369 DataArrayAsciiChar *DataArrayAsciiChar::performCopyOrIncrRef(bool dCpy) const
2370 {
2371   if(dCpy)
2372     return deepCopy();
2373   else
2374     {
2375       incrRef();
2376       return const_cast<DataArrayAsciiChar *>(this);
2377     }
2378 }
2379
2380 /*!
2381  * Returns the only one value in \a this, if and only if number of elements
2382  * (nb of tuples * nb of components) is equal to 1, and that \a this is allocated.
2383  *  \return char - the sole value stored in \a this array.
2384  *  \throw If at least one of conditions stated above is not fulfilled.
2385  */
2386 char DataArrayAsciiChar::asciiCharValue() const
2387 {
2388   if(isAllocated())
2389     {
2390       if(getNbOfElems()==1)
2391         {
2392           return *getConstPointer();
2393         }
2394       else
2395         throw INTERP_KERNEL::Exception("DataArrayAsciiChar::asciiCharValue : DataArrayAsciiChar instance is allocated but number of elements is not equal to 1 !");
2396     }
2397   else
2398     throw INTERP_KERNEL::Exception("DataArrayAsciiChar::asciiCharValue : DataArrayAsciiChar instance is not allocated !");
2399 }
2400
2401 DataArrayChar *DataArrayAsciiChar::buildEmptySpecializedDAChar() const
2402 {
2403   return DataArrayAsciiChar::New();
2404 }
2405
2406 void DataArrayAsciiChar::reprStream(std::ostream& stream) const
2407 {
2408   stream << "Name of ASCII char array : \"" << _name << "\"\n";
2409   reprWithoutNameStream(stream);
2410 }
2411
2412 void DataArrayAsciiChar::reprZipStream(std::ostream& stream) const
2413 {
2414   stream << "Name of ASCII char array : \"" << _name << "\"\n";
2415   reprZipWithoutNameStream(stream);
2416 }
2417
2418 void DataArrayAsciiChar::reprWithoutNameStream(std::ostream& stream) const
2419 {
2420   DataArray::reprWithoutNameStream(stream);
2421   if(_mem.reprHeader(getNumberOfComponents(),stream))
2422     {
2423       const char *data=begin();
2424       int nbOfTuples=getNumberOfTuples();
2425       int nbCompo=getNumberOfComponents();
2426       for(int i=0;i<nbOfTuples;i++,data+=nbCompo)
2427         {
2428           stream << "Tuple #" << i << " : \"";
2429           std::copy(data,data+nbCompo,std::ostream_iterator<char>(stream));
2430           stream << "\"\n";
2431         }
2432     }
2433 }
2434
2435 void DataArrayAsciiChar::reprZipWithoutNameStream(std::ostream& stream) const
2436 {
2437   reprWithoutNameStream(stream);
2438 }
2439
2440 void DataArrayAsciiChar::reprCppStream(const std::string& varName, std::ostream& stream) const
2441 {
2442   int nbTuples=getNumberOfTuples(),nbComp=getNumberOfComponents();
2443   const char *data=getConstPointer();
2444   stream << "DataArrayAsciiChar *" << varName << "=DataArrayAsciiChar::New();" << std::endl;
2445   if(nbTuples*nbComp>=1)
2446     {
2447       stream << "const char " << varName << "Data[" << nbTuples*nbComp << "]={";
2448       std::copy(data,data+nbTuples*nbComp-1,std::ostream_iterator<char>(stream,","));
2449       stream << data[nbTuples*nbComp-1] << "};" << std::endl;
2450       stream << varName << "->useArray(" << varName << "Data,false,CPP_DEALLOC," << nbTuples << "," << nbComp << ");" << std::endl;
2451     }
2452   else
2453     stream << varName << "->alloc(" << nbTuples << "," << nbComp << ");" << std::endl;
2454   stream << varName << "->setName(\"" << getName() << "\");" << std::endl;
2455 }
2456
2457 /*!
2458  * Method that gives a quick overvien of \a this for python.
2459  */
2460 void DataArrayAsciiChar::reprQuickOverview(std::ostream& stream) const
2461 {
2462   static const std::size_t MAX_NB_OF_BYTE_IN_REPR=300;
2463   stream << "DataArrayAsciiChar C++ instance at " << this << ". ";
2464   if(isAllocated())
2465     {
2466       int nbOfCompo=(int)_info_on_compo.size();
2467       if(nbOfCompo>=1)
2468         {
2469           int nbOfTuples=getNumberOfTuples();
2470           stream << "Number of tuples : " << nbOfTuples << ". Number of components : " << nbOfCompo << "." << std::endl;
2471           reprQuickOverviewData(stream,MAX_NB_OF_BYTE_IN_REPR);
2472         }
2473       else
2474         stream << "Number of components : 0.";
2475     }
2476   else
2477     stream << "*** No data allocated ****";
2478 }
2479
2480 void DataArrayAsciiChar::reprQuickOverviewData(std::ostream& stream, std::size_t maxNbOfByteInRepr) const
2481 {
2482   const char *data=begin();
2483   int nbOfTuples=getNumberOfTuples();
2484   int nbOfCompo=(int)_info_on_compo.size();
2485   std::ostringstream oss2; oss2 << "[";
2486   std::string oss2Str(oss2.str());
2487   bool isFinished=true;
2488   for(int i=0;i<nbOfTuples && isFinished;i++)
2489     {
2490       bool isAscii=true;
2491       for(int j=0;j<nbOfCompo;j++)
2492         if(data[j]<32) isAscii=false;
2493       if(isAscii)
2494         {
2495           oss2 << "\'";
2496           for(int j=0;j<nbOfCompo;j++,data++)
2497             oss2 << *data;
2498           oss2 << "\'";
2499         }
2500       else
2501         {
2502           oss2 << "(";
2503           for(int j=0;j<nbOfCompo;j++,data++)
2504             {
2505               oss2 << (int)*data;
2506               if(j!=nbOfCompo-1) oss2 << ", ";
2507             }
2508           oss2 << ")";
2509         }
2510       if(i!=nbOfTuples-1) oss2 << ", ";
2511       std::string oss3Str(oss2.str());
2512       if(oss3Str.length()<maxNbOfByteInRepr)
2513         oss2Str=oss3Str;
2514       else
2515         isFinished=false;
2516     }
2517   stream << oss2Str;
2518   if(!isFinished)
2519     stream << "... ";
2520   stream << "]";
2521 }
2522
2523 bool DataArrayAsciiChar::isEqualIfNotWhy(const DataArrayChar& other, std::string& reason) const
2524 {
2525   const DataArrayAsciiChar *otherC=dynamic_cast<const DataArrayAsciiChar *>(&other);
2526   if(!otherC)
2527     { reason="this is of type DataArrayAsciiChar whereas other is not a DataArrayAsciiChar instance"; return false; }
2528   return DataArrayChar::isEqualIfNotWhy(other,reason);
2529 }
2530
2531 DataArrayAsciiCharIterator::DataArrayAsciiCharIterator(DataArrayAsciiChar *da):_da(da),_pt(0),_tuple_id(0),_nb_comp(0),_nb_tuple(0)
2532 {
2533   if(_da)
2534     {
2535       _da->incrRef();
2536       if(_da->isAllocated())
2537         {
2538           _nb_comp=da->getNumberOfComponents();
2539           _nb_tuple=da->getNumberOfTuples();
2540           _pt=da->getPointer();
2541         }
2542     }
2543 }
2544
2545 DataArrayAsciiCharIterator::~DataArrayAsciiCharIterator()
2546 {
2547   if(_da)
2548     _da->decrRef();
2549 }
2550
2551 DataArrayAsciiCharTuple *DataArrayAsciiCharIterator::nextt()
2552 {
2553   if(_tuple_id<_nb_tuple)
2554     {
2555       _tuple_id++;
2556       DataArrayAsciiCharTuple *ret=new DataArrayAsciiCharTuple(_pt,_nb_comp);
2557       _pt+=_nb_comp;
2558       return ret;
2559     }
2560   else
2561     return 0;
2562 }
2563
2564 DataArrayAsciiCharTuple::DataArrayAsciiCharTuple(char *pt, int nbOfComp):_pt(pt),_nb_of_compo(nbOfComp)
2565 {
2566 }
2567
2568 std::string DataArrayAsciiCharTuple::repr() const
2569 {
2570   std::ostringstream oss;
2571   std::copy(_pt,_pt+_nb_of_compo,std::ostream_iterator<char>(oss));
2572   return oss.str();
2573 }
2574
2575 char DataArrayAsciiCharTuple::asciiCharValue() const
2576 {
2577   if(_nb_of_compo==1)
2578     return *_pt;
2579   throw INTERP_KERNEL::Exception("DataArrayAsciiCharTuple::asciiCharValue : DataArrayAsciiCharTuple instance has not exactly 1 component -> Not possible to convert it into an character !");
2580 }
2581
2582 /*!
2583  * This method returns a newly allocated instance the caller should dealed with by a MEDCoupling::DataArrayAsciiChar::decrRef.
2584  * This method performs \b no copy of data. The content is only referenced using MEDCoupling::DataArrayAsciiChar::useArray with ownership set to \b false.
2585  * This method throws an INTERP_KERNEL::Exception is it is impossible to match sizes of \b this that is too say \b nbOfCompo=this->_nb_of_elem and \bnbOfTuples==1 or
2586  * \b nbOfCompo=1 and \bnbOfTuples==this->_nb_of_elem.
2587  */
2588 DataArrayAsciiChar *DataArrayAsciiCharTuple::buildDAAsciiChar(int nbOfTuples, int nbOfCompo) const
2589 {
2590   if((_nb_of_compo==nbOfCompo && nbOfTuples==1) || (_nb_of_compo==nbOfTuples && nbOfCompo==1))
2591     {
2592       DataArrayAsciiChar *ret=DataArrayAsciiChar::New();
2593       ret->useExternalArrayWithRWAccess(_pt,nbOfTuples,nbOfCompo);
2594       return ret;
2595     }
2596   else
2597     {
2598       std::ostringstream oss; oss << "DataArrayAsciiCharTuple::buildDAAsciiChar : unable to build a requested DataArrayAsciiChar instance with nbofTuple=" << nbOfTuples << " and nbOfCompo=" << nbOfCompo;
2599       oss << ".\nBecause the number of elements in this is " << _nb_of_compo << " !";
2600       throw INTERP_KERNEL::Exception(oss.str().c_str());
2601     }
2602 }