Salome HOME
MED file loading on demand.
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingMemArrayChar.cxx
1 // Copyright (C) 2007-2013  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.
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 "MEDCouplingAutoRefCountObjectPtr.hxx"
23
24 #include <set>
25 #include <cmath>
26 #include <limits>
27 #include <numeric>
28 #include <algorithm>
29 #include <functional>
30
31 using namespace ParaMEDMEM;
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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() throw(INTERP_KERNEL::Exception)
59 {
60   _mem.destroy();
61 }
62
63 std::size_t DataArrayChar::getHeapMemorySize() const
64 {
65   std::size_t sz=_mem.getNbOfElemAllocated();
66   return DataArray::getHeapMemorySize()+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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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::cpyFrom(const DataArrayChar& other) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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() throw(INTERP_KERNEL::Exception)
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::getHeapMemorySize, DataArrayChar::reserve
208  */
209 void DataArrayChar::pack() const throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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() throw(INTERP_KERNEL::Exception)
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() throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
331 {
332   std::ostringstream ret;
333   reprStream(ret);
334   return ret.str();
335 }
336
337 std::string DataArrayChar::reprZip() const throw(INTERP_KERNEL::Exception)
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) throw(INTERP_KERNEL::Exception)
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 throw(INTERP_KERNEL::Exception)
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, substr() or selectByTupleId() should be used.
383  * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
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) throw(INTERP_KERNEL::Exception)
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 MEDCouplingArrayRenumbering.
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) throw(INTERP_KERNEL::Exception)
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 MEDCouplingArrayRenumbering.
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 throw(INTERP_KERNEL::Exception)
436 {
437   checkAllocated();
438   int nbTuples=getNumberOfTuples();
439   int nbOfCompo=getNumberOfComponents();
440   MEDCouplingAutoRefCountObjectPtr<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, substr() or selectByTupleId() should be used.
456  * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
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 throw(INTERP_KERNEL::Exception)
463 {
464   checkAllocated();
465   int nbTuples=getNumberOfTuples();
466   int nbOfCompo=getNumberOfComponents();
467   MEDCouplingAutoRefCountObjectPtr<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 MEDCouplingArrayRenumbering.
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 throw(INTERP_KERNEL::Exception)
492 {
493   checkAllocated();
494   int nbTuples=getNumberOfTuples();
495   int nbOfCompo=getNumberOfComponents();
496   MEDCouplingAutoRefCountObjectPtr<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  * This method is equivalent to selectByTupleId() except that it prevents coping data
518  * from behind the end of \a this array.
519  * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
520  *  \param [in] new2OldBg - pointer to the beginning of a permutation array that gives a
521  *              tuple index in \a this array to fill the i-th tuple in the new array.
522  *  \param [in] new2OldEnd - specifies the end of the permutation array that starts at
523  *              \a new2OldBg, so that pointer to a tuple index (\a pi) varies as this:
524  *              \a new2OldBg <= \a pi < \a new2OldEnd.
525  *  \return DataArrayChar * - the new instance of DataArrayChar that the caller
526  *          is to delete using decrRef() as it is no more needed.
527  *  \throw If \a new2OldEnd - \a new2OldBg > \a this->getNumberOfTuples().
528  */
529 DataArrayChar *DataArrayChar::selectByTupleIdSafe(const int *new2OldBg, const int *new2OldEnd) const throw(INTERP_KERNEL::Exception)
530 {
531   checkAllocated();
532   MEDCouplingAutoRefCountObjectPtr<DataArrayChar> ret=buildEmptySpecializedDAChar();
533   int nbComp=getNumberOfComponents();
534   int oldNbOfTuples=getNumberOfTuples();
535   ret->alloc((int)std::distance(new2OldBg,new2OldEnd),nbComp);
536   ret->copyStringInfoFrom(*this);
537   char *pt=ret->getPointer();
538   const char *srcPt=getConstPointer();
539   int i=0;
540   for(const int *w=new2OldBg;w!=new2OldEnd;w++,i++)
541     if(*w>=0 && *w<oldNbOfTuples)
542       std::copy(srcPt+(*w)*nbComp,srcPt+((*w)+1)*nbComp,pt+i*nbComp);
543     else
544       throw INTERP_KERNEL::Exception("DataArrayChar::selectByTupleIdSafe : some ids has been detected to be out of [0,this->getNumberOfTuples) !");
545   ret->copyStringInfoFrom(*this);
546   return ret.retn();
547 }
548
549 /*!
550  * Returns a shorten copy of \a this array. The new DataArrayChar contains every
551  * (\a bg + \c i * \a step)-th tuple of \a this array located before the \a end2-th
552  * tuple. Indices of the selected tuples are the same as ones returned by the Python
553  * command \c range( \a bg, \a end2, \a step ).
554  * This method is equivalent to selectByTupleIdSafe() except that the input array is
555  * not constructed explicitly.
556  * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
557  *  \param [in] bg - index of the first tuple to copy from \a this array.
558  *  \param [in] end2 - index of the tuple before which the tuples to copy are located.
559  *  \param [in] step - index increment to get index of the next tuple to copy.
560  *  \return DataArrayChar * - the new instance of DataArrayChar that the caller
561  *          is to delete using decrRef() as it is no more needed.
562  *  \throw If (\a end2 < \a bg) or (\a step <= 0).
563  *  \sa DataArrayChar::substr.
564  */
565 DataArrayChar *DataArrayChar::selectByTupleId2(int bg, int end2, int step) const throw(INTERP_KERNEL::Exception)
566 {
567   checkAllocated();
568   MEDCouplingAutoRefCountObjectPtr<DataArrayChar> ret=buildEmptySpecializedDAChar();
569   int nbComp=getNumberOfComponents();
570   int newNbOfTuples=GetNumberOfItemGivenBESRelative(bg,end2,step,"DataArrayInt::selectByTupleId2 : ");
571   ret->alloc(newNbOfTuples,nbComp);
572   char *pt=ret->getPointer();
573   const char *srcPt=getConstPointer()+bg*nbComp;
574   for(int i=0;i<newNbOfTuples;i++,srcPt+=step*nbComp)
575     std::copy(srcPt,srcPt+nbComp,pt+i*nbComp);
576   ret->copyStringInfoFrom(*this);
577   return ret.retn();
578 }
579
580 /*!
581  * Checks if all values in \a this array are equal to \a val.
582  *  \param [in] val - value to check equality of array values to.
583  *  \return bool - \a true if all values are \a val.
584  *  \throw If \a this is not allocated.
585  *  \throw If \a this->getNumberOfComponents() != 1
586  */
587 bool DataArrayChar::isUniform(char val) const throw(INTERP_KERNEL::Exception)
588 {
589   checkAllocated();
590   if(getNumberOfComponents()!=1)
591     throw INTERP_KERNEL::Exception("DataArrayChar::isUniform : must be applied on DataArrayChar with only one component, you can call 'rearrange' method before !");
592   int nbOfTuples=getNumberOfTuples();
593   const char *w=getConstPointer();
594   const char *end2=w+nbOfTuples;
595   for(;w!=end2;w++)
596     if(*w!=val)
597       return false;
598   return true;
599 }
600
601 /*!
602  * Changes the number of components within \a this array so that its raw data **does
603  * not** change, instead splitting this data into tuples changes.
604  *  \param [in] newNbOfComp - number of components for \a this array to have.
605  *  \throw If \a this is not allocated
606  *  \throw If getNbOfElems() % \a newNbOfCompo != 0.
607  *  \throw If \a newNbOfCompo is lower than 1.
608  *  \throw If the rearrange method would lead to a number of tuples higher than 2147483647 (maximal capacity of int32 !).
609  *  \warning This method erases all (name and unit) component info set before!
610  */
611 void DataArrayChar::rearrange(int newNbOfCompo) throw(INTERP_KERNEL::Exception)
612 {
613   checkAllocated();
614   if(newNbOfCompo<1)
615     throw INTERP_KERNEL::Exception("DataArrayChar::rearrange : input newNbOfCompo must be > 0 !");
616   std::size_t nbOfElems=getNbOfElems();
617   if(nbOfElems%newNbOfCompo!=0)
618     throw INTERP_KERNEL::Exception("DataArrayChar::rearrange : nbOfElems%newNbOfCompo!=0 !");
619   if(nbOfElems/newNbOfCompo>(std::size_t)std::numeric_limits<int>::max())
620     throw INTERP_KERNEL::Exception("DataArrayChar::rearrange : the rearrangement leads to too high number of tuples (> 2147483647) !");
621   _info_on_compo.clear();
622   _info_on_compo.resize(newNbOfCompo);
623   declareAsNew();
624 }
625
626 /*!
627  * Returns a shorten copy of \a this array. The new DataArrayChar contains all
628  * tuples starting from the \a tupleIdBg-th tuple and including all tuples located before
629  * the \a tupleIdEnd-th one. This methods has a similar behavior as std::string::substr().
630  * This method is a specialization of selectByTupleId2().
631  *  \param [in] tupleIdBg - index of the first tuple to copy from \a this array.
632  *  \param [in] tupleIdEnd - index of the tuple before which the tuples to copy are located.
633  *          If \a tupleIdEnd == -1, all the tuples till the end of \a this array are copied.
634  *  \return DataArrayChar * - the new instance of DataArrayChar that the caller
635  *          is to delete using decrRef() as it is no more needed.
636  *  \throw If \a tupleIdBg < 0.
637  *  \throw If \a tupleIdBg > \a this->getNumberOfTuples().
638     \throw If \a tupleIdEnd != -1 && \a tupleIdEnd < \a this->getNumberOfTuples().
639  *  \sa DataArrayChar::selectByTupleId2
640  */
641 DataArrayChar *DataArrayChar::substr(int tupleIdBg, int tupleIdEnd) const throw(INTERP_KERNEL::Exception)
642 {
643   checkAllocated();
644   int nbt=getNumberOfTuples();
645   if(tupleIdBg<0)
646     throw INTERP_KERNEL::Exception("DataArrayChar::substr : The tupleIdBg parameter must be greater than 0 !");
647   if(tupleIdBg>nbt)
648     throw INTERP_KERNEL::Exception("DataArrayChar::substr : The tupleIdBg parameter is greater than number of tuples !");
649   int trueEnd=tupleIdEnd;
650   if(tupleIdEnd!=-1)
651     {
652       if(tupleIdEnd>nbt)
653         throw INTERP_KERNEL::Exception("DataArrayChar::substr : The tupleIdBg parameter is greater or equal than number of tuples !");
654     }
655   else
656     trueEnd=nbt;
657   int nbComp=getNumberOfComponents();
658   MEDCouplingAutoRefCountObjectPtr<DataArrayChar> ret=buildEmptySpecializedDAChar();
659   ret->alloc(trueEnd-tupleIdBg,nbComp);
660   ret->copyStringInfoFrom(*this);
661   std::copy(getConstPointer()+tupleIdBg*nbComp,getConstPointer()+trueEnd*nbComp,ret->getPointer());
662   return ret.retn();
663 }
664
665 /*!
666  * Returns a shorten or extended copy of \a this array. If \a newNbOfComp is less
667  * than \a this->getNumberOfComponents() then the result array is shorten as each tuple
668  * is truncated to have \a newNbOfComp components, keeping first components. If \a
669  * newNbOfComp is more than \a this->getNumberOfComponents() then the result array is
670  * expanded as each tuple is populated with \a dftValue to have \a newNbOfComp
671  * components.  
672  *  \param [in] newNbOfComp - number of components for the new array to have.
673  *  \param [in] dftValue - value assigned to new values added to the new array.
674  *  \return DataArrayDouble * - the new instance of DataArrayDouble that the caller
675  *          is to delete using decrRef() as it is no more needed.
676  *  \throw If \a this is not allocated.
677  */
678 DataArrayChar *DataArrayChar::changeNbOfComponents(int newNbOfComp, char dftValue) const throw(INTERP_KERNEL::Exception)
679 {
680   checkAllocated();
681   MEDCouplingAutoRefCountObjectPtr<DataArrayChar> ret=buildEmptySpecializedDAChar();
682   ret->alloc(getNumberOfTuples(),newNbOfComp);
683   const char *oldc=getConstPointer();
684   char *nc=ret->getPointer();
685   int nbOfTuples=getNumberOfTuples();
686   int oldNbOfComp=getNumberOfComponents();
687   int dim=std::min(oldNbOfComp,newNbOfComp);
688   for(int i=0;i<nbOfTuples;i++)
689     {
690       int j=0;
691       for(;j<dim;j++)
692         nc[newNbOfComp*i+j]=oldc[i*oldNbOfComp+j];
693       for(;j<newNbOfComp;j++)
694         nc[newNbOfComp*i+j]=dftValue;
695     }
696   ret->setName(getName().c_str());
697   for(int i=0;i<dim;i++)
698     ret->setInfoOnComponent(i,getInfoOnComponent(i).c_str());
699   ret->setName(getName().c_str());
700   return ret.retn();
701 }
702
703 /*!
704  * Returns a copy of \a this array composed of selected components.
705  * The new DataArrayChar has the same number of tuples but includes components
706  * specified by \a compoIds parameter. So that getNbOfElems() of the result array
707  * can be either less, same or more than \a this->getNbOfElems().
708  *  \param [in] compoIds - sequence of zero based indices of components to include
709  *              into the new array.
710  *  \return DataArrayChar * - the new instance of DataArrayChar that the caller
711  *          is to delete using decrRef() as it is no more needed.
712  *  \throw If \a this is not allocated.
713  *  \throw If a component index (\a i) is not valid: 
714  *         \a i < 0 || \a i >= \a this->getNumberOfComponents().
715  *
716  *  \ref py_mcdataarrayint_keepselectedcomponents "Here is a Python example".
717  */
718 DataArray *DataArrayChar::keepSelectedComponents(const std::vector<int>& compoIds) const throw(INTERP_KERNEL::Exception)
719 {
720   checkAllocated();
721   MEDCouplingAutoRefCountObjectPtr<DataArrayChar> ret(buildEmptySpecializedDAChar());
722   int newNbOfCompo=(int)compoIds.size();
723   int oldNbOfCompo=getNumberOfComponents();
724   for(std::vector<int>::const_iterator it=compoIds.begin();it!=compoIds.end();it++)
725     DataArray::CheckValueInRange(oldNbOfCompo,(*it),"keepSelectedComponents invalid requested component");
726   int nbOfTuples=getNumberOfTuples();
727   ret->alloc(nbOfTuples,newNbOfCompo);
728   ret->copyPartOfStringInfoFrom(*this,compoIds);
729   const char *oldc=getConstPointer();
730   char *nc=ret->getPointer();
731   for(int i=0;i<nbOfTuples;i++)
732     for(int j=0;j<newNbOfCompo;j++,nc++)
733       *nc=oldc[i*oldNbOfCompo+compoIds[j]];
734   return ret.retn();
735 }
736
737 /*!
738  * Appends components of another array to components of \a this one, tuple by tuple.
739  * So that the number of tuples of \a this array remains the same and the number of 
740  * components increases.
741  *  \param [in] other - the DataArrayChar to append to \a this one.
742  *  \throw If \a this is not allocated.
743  *  \throw If \a this and \a other arrays have different number of tuples.
744  *
745  *  \ref cpp_mcdataarrayint_meldwith "Here is a C++ example".
746  *
747  *  \ref py_mcdataarrayint_meldwith "Here is a Python example".
748  */
749 void DataArrayChar::meldWith(const DataArrayChar *other) throw(INTERP_KERNEL::Exception)
750 {
751   if(!other)
752     throw INTERP_KERNEL::Exception("DataArrayChar::meldWith : DataArrayChar pointer in input is NULL !");
753   checkAllocated();
754   other->checkAllocated();
755   int nbOfTuples=getNumberOfTuples();
756   if(nbOfTuples!=other->getNumberOfTuples())
757     throw INTERP_KERNEL::Exception("DataArrayChar::meldWith : mismatch of number of tuples !");
758   int nbOfComp1=getNumberOfComponents();
759   int nbOfComp2=other->getNumberOfComponents();
760   char *newArr=(char *)malloc(nbOfTuples*(nbOfComp1+nbOfComp2)*sizeof(char));
761   char *w=newArr;
762   const char *inp1=getConstPointer();
763   const char *inp2=other->getConstPointer();
764   for(int i=0;i<nbOfTuples;i++,inp1+=nbOfComp1,inp2+=nbOfComp2)
765     {
766       w=std::copy(inp1,inp1+nbOfComp1,w);
767       w=std::copy(inp2,inp2+nbOfComp2,w);
768     }
769   useArray(newArr,true,C_DEALLOC,nbOfTuples,nbOfComp1+nbOfComp2);
770   std::vector<int> compIds(nbOfComp2);
771   for(int i=0;i<nbOfComp2;i++)
772     compIds[i]=nbOfComp1+i;
773   copyPartOfStringInfoFrom2(compIds,*other);
774 }
775
776 /*!
777  * Copy all values from another DataArrayChar into specified tuples and components
778  * of \a this array. Textual data is not copied.
779  * The tree parameters defining set of indices of tuples and components are similar to
780  * the tree parameters of the Python function \c range(\c start,\c stop,\c step).
781  *  \param [in] a - the array to copy values from.
782  *  \param [in] bgTuples - index of the first tuple of \a this array to assign values to.
783  *  \param [in] endTuples - index of the tuple before which the tuples to assign to
784  *              are located.
785  *  \param [in] stepTuples - index increment to get index of the next tuple to assign to.
786  *  \param [in] bgComp - index of the first component of \a this array to assign values to.
787  *  \param [in] endComp - index of the component before which the components to assign
788  *              to are located.
789  *  \param [in] stepComp - index increment to get index of the next component to assign to.
790  *  \param [in] strictCompoCompare - if \a true (by default), then \a a->getNumberOfComponents() 
791  *              must be equal to the number of columns to assign to, else an
792  *              exception is thrown; if \a false, then it is only required that \a
793  *              a->getNbOfElems() equals to number of values to assign to (this condition
794  *              must be respected even if \a strictCompoCompare is \a true). The number of 
795  *              values to assign to is given by following Python expression:
796  *              \a nbTargetValues = 
797  *              \c len(\c range(\a bgTuples,\a endTuples,\a stepTuples)) *
798  *              \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
799  *  \throw If \a a is NULL.
800  *  \throw If \a a is not allocated.
801  *  \throw If \a this is not allocated.
802  *  \throw If parameters specifying tuples and components to assign to do not give a
803  *            non-empty range of increasing indices.
804  *  \throw If \a a->getNbOfElems() != \a nbTargetValues.
805  *  \throw If \a strictCompoCompare == \a true && \a a->getNumberOfComponents() !=
806  *            \c len(\c range(\a bgComp,\a endComp,\a stepComp)).
807  *
808  *  \ref py_mcdataarrayint_setpartofvalues1 "Here is a Python example".
809  */
810 void DataArrayChar::setPartOfValues1(const DataArrayChar *a, int bgTuples, int endTuples, int stepTuples, int bgComp, int endComp, int stepComp, bool strictCompoCompare) throw(INTERP_KERNEL::Exception)
811 {
812   if(!a)
813     throw INTERP_KERNEL::Exception("DataArrayChar::setPartOfValues1 : DataArrayChar pointer in input is NULL !");
814   const char msg[]="DataArrayChar::setPartOfValues1";
815   checkAllocated();
816   a->checkAllocated();
817   int newNbOfTuples=DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg);
818   int newNbOfComp=DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg);
819   int nbComp=getNumberOfComponents();
820   int nbOfTuples=getNumberOfTuples();
821   DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
822   DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
823   bool assignTech=true;
824   if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
825     {
826       if(strictCompoCompare)
827         a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
828     }
829   else
830     {
831       a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
832       assignTech=false;
833     }
834   char *pt=getPointer()+bgTuples*nbComp+bgComp;
835   const char *srcPt=a->getConstPointer();
836   if(assignTech)
837     {
838       for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
839         for(int j=0;j<newNbOfComp;j++,srcPt++)
840           pt[j*stepComp]=*srcPt;
841     }
842   else
843     {
844       for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
845         {
846           const char *srcPt2=srcPt;
847           for(int j=0;j<newNbOfComp;j++,srcPt2++)
848             pt[j*stepComp]=*srcPt2;
849         }
850     }
851 }
852
853 /*!
854  * Assign a given value to values at specified tuples and components of \a this array.
855  * The tree parameters defining set of indices of tuples and components are similar to
856  * the tree parameters of the Python function \c range(\c start,\c stop,\c step)..
857  *  \param [in] a - the value to assign.
858  *  \param [in] bgTuples - index of the first tuple of \a this array to assign to.
859  *  \param [in] endTuples - index of the tuple before which the tuples to assign to
860  *              are located.
861  *  \param [in] stepTuples - index increment to get index of the next tuple to assign to.
862  *  \param [in] bgComp - index of the first component of \a this array to assign to.
863  *  \param [in] endComp - index of the component before which the components to assign
864  *              to are located.
865  *  \param [in] stepComp - index increment to get index of the next component to assign to.
866  *  \throw If \a this is not allocated.
867  *  \throw If parameters specifying tuples and components to assign to, do not give a
868  *            non-empty range of increasing indices or indices are out of a valid range
869  *            for \this array.
870  *
871  *  \ref py_mcdataarrayint_setpartofvaluessimple1 "Here is a Python example".
872  */
873 void DataArrayChar::setPartOfValuesSimple1(char a, int bgTuples, int endTuples, int stepTuples, int bgComp, int endComp, int stepComp) throw(INTERP_KERNEL::Exception)
874 {
875   const char msg[]="DataArrayChar::setPartOfValuesSimple1";
876   checkAllocated();
877   int newNbOfTuples=DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg);
878   int newNbOfComp=DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg);
879   int nbComp=getNumberOfComponents();
880   int nbOfTuples=getNumberOfTuples();
881   DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
882   DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
883   char *pt=getPointer()+bgTuples*nbComp+bgComp;
884   for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
885     for(int j=0;j<newNbOfComp;j++)
886       pt[j*stepComp]=a;
887 }
888
889
890 /*!
891  * Copy all values from another DataArrayChar (\a a) into specified tuples and 
892  * components of \a this array. Textual data is not copied.
893  * The tuples and components to assign to are defined by C arrays of indices.
894  * There are two *modes of usage*:
895  * - If \a a->getNbOfElems() equals to number of values to assign to, then every value
896  *   of \a a is assigned to its own location within \a this array. 
897  * - If \a a includes one tuple, then all values of \a a are assigned to the specified
898  *   components of every specified tuple of \a this array. In this mode it is required
899  *   that \a a->getNumberOfComponents() equals to the number of specified components.
900  * 
901  *  \param [in] a - the array to copy values from.
902  *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
903  *              assign values of \a a to.
904  *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
905  *              pointer to a tuple index <em>(pi)</em> varies as this: 
906  *              \a bgTuples <= \a pi < \a endTuples.
907  *  \param [in] bgComp - pointer to an array of component indices of \a this array to
908  *              assign values of \a a to.
909  *  \param [in] endComp - specifies the end of the array \a bgTuples, so that
910  *              pointer to a component index <em>(pi)</em> varies as this: 
911  *              \a bgComp <= \a pi < \a endComp.
912  *  \param [in] strictCompoCompare - this parameter is checked only if the
913  *               *mode of usage* is the first; if it is \a true (default), 
914  *               then \a a->getNumberOfComponents() must be equal 
915  *               to the number of specified columns, else this is not required.
916  *  \throw If \a a is NULL.
917  *  \throw If \a a is not allocated.
918  *  \throw If \a this is not allocated.
919  *  \throw If any index of tuple/component given by <em>bgTuples / bgComp</em> is
920  *         out of a valid range for \a this array.
921  *  \throw In the first *mode of usage*, if <em>strictCompoCompare == true </em> and
922  *         if <em> a->getNumberOfComponents() != (endComp - bgComp) </em>.
923  *  \throw In the second *mode of usage*, if \a a->getNumberOfTuples() != 1 or
924  *         <em> a->getNumberOfComponents() != (endComp - bgComp)</em>.
925  *
926  *  \ref py_mcdataarrayint_setpartofvalues2 "Here is a Python example".
927  */
928 void DataArrayChar::setPartOfValues2(const DataArrayChar *a, const int *bgTuples, const int *endTuples, const int *bgComp, const int *endComp, bool strictCompoCompare) throw(INTERP_KERNEL::Exception)
929 {
930   if(!a)
931     throw INTERP_KERNEL::Exception("DataArrayChar::setPartOfValues2 : DataArrayChar pointer in input is NULL !");
932   const char msg[]="DataArrayChar::setPartOfValues2";
933   checkAllocated();
934   a->checkAllocated();
935   int nbComp=getNumberOfComponents();
936   int nbOfTuples=getNumberOfTuples();
937   for(const int *z=bgComp;z!=endComp;z++)
938     DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
939   int newNbOfTuples=(int)std::distance(bgTuples,endTuples);
940   int newNbOfComp=(int)std::distance(bgComp,endComp);
941   bool assignTech=true;
942   if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
943     {
944       if(strictCompoCompare)
945         a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
946     }
947   else
948     {
949       a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
950       assignTech=false;
951     }
952   char *pt=getPointer();
953   const char *srcPt=a->getConstPointer();
954   if(assignTech)
955     {    
956       for(const int *w=bgTuples;w!=endTuples;w++)
957         {
958           DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
959           for(const int *z=bgComp;z!=endComp;z++,srcPt++)
960             {    
961               pt[(std::size_t)(*w)*nbComp+(*z)]=*srcPt;
962             }
963         }
964     }
965   else
966     {
967       for(const int *w=bgTuples;w!=endTuples;w++)
968         {
969           const char *srcPt2=srcPt;
970           DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
971           for(const int *z=bgComp;z!=endComp;z++,srcPt2++)
972             {    
973               pt[(std::size_t)(*w)*nbComp+(*z)]=*srcPt2;
974             }
975         }
976     }
977 }
978
979 /*!
980  * Assign a given value to values at specified tuples and components of \a this array.
981  * The tuples and components to assign to are defined by C arrays of indices.
982  *  \param [in] a - the value to assign.
983  *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
984  *              assign \a a to.
985  *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
986  *              pointer to a tuple index (\a pi) varies as this: 
987  *              \a bgTuples <= \a pi < \a endTuples.
988  *  \param [in] bgComp - pointer to an array of component indices of \a this array to
989  *              assign \a a to.
990  *  \param [in] endComp - specifies the end of the array \a bgTuples, so that
991  *              pointer to a component index (\a pi) varies as this: 
992  *              \a bgComp <= \a pi < \a endComp.
993  *  \throw If \a this is not allocated.
994  *  \throw If any index of tuple/component given by <em>bgTuples / bgComp</em> is
995  *         out of a valid range for \a this array.
996  *
997  *  \ref py_mcdataarrayint_setpartofvaluessimple2 "Here is a Python example".
998  */
999 void DataArrayChar::setPartOfValuesSimple2(char a, const int *bgTuples, const int *endTuples, const int *bgComp, const int *endComp) throw(INTERP_KERNEL::Exception)
1000 {
1001   checkAllocated();
1002   int nbComp=getNumberOfComponents();
1003   int nbOfTuples=getNumberOfTuples();
1004   for(const int *z=bgComp;z!=endComp;z++)
1005     DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
1006   char *pt=getPointer();
1007   for(const int *w=bgTuples;w!=endTuples;w++)
1008     for(const int *z=bgComp;z!=endComp;z++)
1009       {
1010         DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1011         pt[(std::size_t)(*w)*nbComp+(*z)]=a;
1012       }
1013 }
1014
1015 /*!
1016  * Copy all values from another DataArrayChar (\a a) into specified tuples and 
1017  * components of \a this array. Textual data is not copied.
1018  * The tuples to assign to are defined by a C array of indices.
1019  * The components to assign to are defined by three values similar to parameters of
1020  * the Python function \c range(\c start,\c stop,\c step).
1021  * There are two *modes of usage*:
1022  * - If \a a->getNbOfElems() equals to number of values to assign to, then every value
1023  *   of \a a is assigned to its own location within \a this array. 
1024  * - If \a a includes one tuple, then all values of \a a are assigned to the specified
1025  *   components of every specified tuple of \a this array. In this mode it is required
1026  *   that \a a->getNumberOfComponents() equals to the number of specified components.
1027  *
1028  *  \param [in] a - the array to copy values from.
1029  *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1030  *              assign values of \a a to.
1031  *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1032  *              pointer to a tuple index <em>(pi)</em> varies as this: 
1033  *              \a bgTuples <= \a pi < \a endTuples.
1034  *  \param [in] bgComp - index of the first component of \a this array to assign to.
1035  *  \param [in] endComp - index of the component before which the components to assign
1036  *              to are located.
1037  *  \param [in] stepComp - index increment to get index of the next component to assign to.
1038  *  \param [in] strictCompoCompare - this parameter is checked only in the first
1039  *               *mode of usage*; if \a strictCompoCompare is \a true (default), 
1040  *               then \a a->getNumberOfComponents() must be equal 
1041  *               to the number of specified columns, else this is not required.
1042  *  \throw If \a a is NULL.
1043  *  \throw If \a a is not allocated.
1044  *  \throw If \a this is not allocated.
1045  *  \throw If any index of tuple given by \a bgTuples is out of a valid range for 
1046  *         \a this array.
1047  *  \throw In the first *mode of usage*, if <em>strictCompoCompare == true </em> and
1048  *         if <em> a->getNumberOfComponents()</em> is unequal to the number of components
1049  *         defined by <em>(bgComp,endComp,stepComp)</em>.
1050  *  \throw In the second *mode of usage*, if \a a->getNumberOfTuples() != 1 or
1051  *         <em> a->getNumberOfComponents()</em> is unequal to the number of components
1052  *         defined by <em>(bgComp,endComp,stepComp)</em>.
1053  *  \throw If parameters specifying components to assign to, do not give a
1054  *            non-empty range of increasing indices or indices are out of a valid range
1055  *            for \this array.
1056  *
1057  *  \ref py_mcdataarrayint_setpartofvalues3 "Here is a Python example".
1058  */
1059 void DataArrayChar::setPartOfValues3(const DataArrayChar *a, const int *bgTuples, const int *endTuples, int bgComp, int endComp, int stepComp, bool strictCompoCompare) throw(INTERP_KERNEL::Exception)
1060 {
1061   if(!a)
1062     throw INTERP_KERNEL::Exception("DataArrayChar::setPartOfValues3 : DataArrayChar pointer in input is NULL !");
1063   const char msg[]="DataArrayChar::setPartOfValues3";
1064   checkAllocated();
1065   a->checkAllocated();
1066   int newNbOfComp=DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg);
1067   int nbComp=getNumberOfComponents();
1068   int nbOfTuples=getNumberOfTuples();
1069   DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
1070   int newNbOfTuples=(int)std::distance(bgTuples,endTuples);
1071   bool assignTech=true;
1072   if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
1073     {
1074       if(strictCompoCompare)
1075         a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1076     }
1077   else
1078     {
1079       a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1080       assignTech=false;
1081     }
1082   char *pt=getPointer()+bgComp;
1083   const char *srcPt=a->getConstPointer();
1084   if(assignTech)
1085     {
1086       for(const int *w=bgTuples;w!=endTuples;w++)
1087         for(int j=0;j<newNbOfComp;j++,srcPt++)
1088           {
1089             DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1090             pt[(std::size_t)(*w)*nbComp+j*stepComp]=*srcPt;
1091           }
1092     }
1093   else
1094     {
1095       for(const int *w=bgTuples;w!=endTuples;w++)
1096         {
1097           const char *srcPt2=srcPt;
1098           for(int j=0;j<newNbOfComp;j++,srcPt2++)
1099             {
1100               DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1101               pt[(std::size_t)(*w)*nbComp+j*stepComp]=*srcPt2;
1102             }
1103         }
1104     }
1105 }
1106
1107 /*!
1108  * Assign a given value to values at specified tuples and components of \a this array.
1109  * The tuples to assign to are defined by a C array of indices.
1110  * The components to assign to are defined by three values similar to parameters of
1111  * the Python function \c range(\c start,\c stop,\c step).
1112  *  \param [in] a - the value to assign.
1113  *  \param [in] bgTuples - pointer to an array of tuple indices of \a this array to
1114  *              assign \a a to.
1115  *  \param [in] endTuples - specifies the end of the array \a bgTuples, so that
1116  *              pointer to a tuple index <em>(pi)</em> varies as this: 
1117  *              \a bgTuples <= \a pi < \a endTuples.
1118  *  \param [in] bgComp - index of the first component of \a this array to assign to.
1119  *  \param [in] endComp - index of the component before which the components to assign
1120  *              to are located.
1121  *  \param [in] stepComp - index increment to get index of the next component to assign to.
1122  *  \throw If \a this is not allocated.
1123  *  \throw If any index of tuple given by \a bgTuples is out of a valid range for 
1124  *         \a this array.
1125  *  \throw If parameters specifying components to assign to, do not give a
1126  *            non-empty range of increasing indices or indices are out of a valid range
1127  *            for \this array.
1128  *
1129  *  \ref py_mcdataarrayint_setpartofvaluessimple3 "Here is a Python example".
1130  */
1131 void DataArrayChar::setPartOfValuesSimple3(char a, const int *bgTuples, const int *endTuples, int bgComp, int endComp, int stepComp) throw(INTERP_KERNEL::Exception)
1132 {
1133   const char msg[]="DataArrayChar::setPartOfValuesSimple3";
1134   checkAllocated();
1135   int newNbOfComp=DataArray::GetNumberOfItemGivenBES(bgComp,endComp,stepComp,msg);
1136   int nbComp=getNumberOfComponents();
1137   int nbOfTuples=getNumberOfTuples();
1138   DataArray::CheckValueInRangeEx(nbComp,bgComp,endComp,"invalid component value");
1139   char *pt=getPointer()+bgComp;
1140   for(const int *w=bgTuples;w!=endTuples;w++)
1141     for(int j=0;j<newNbOfComp;j++)
1142       {
1143         DataArray::CheckValueInRange(nbOfTuples,*w,"invalid tuple id");
1144         pt[(*w)*nbComp+j*stepComp]=a;
1145       }
1146 }
1147
1148 void DataArrayChar::setPartOfValues4(const DataArrayChar *a, int bgTuples, int endTuples, int stepTuples, const int *bgComp, const int *endComp, bool strictCompoCompare) throw(INTERP_KERNEL::Exception)
1149 {
1150   if(!a)
1151     throw INTERP_KERNEL::Exception("DataArrayInt::setPartOfValues4 : input DataArrayInt is NULL !");
1152   const char msg[]="DataArrayInt::setPartOfValues4";
1153   checkAllocated();
1154   a->checkAllocated();
1155   int newNbOfTuples=DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg);
1156   int newNbOfComp=(int)std::distance(bgComp,endComp);
1157   int nbComp=getNumberOfComponents();
1158   for(const int *z=bgComp;z!=endComp;z++)
1159     DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
1160   int nbOfTuples=getNumberOfTuples();
1161   DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1162   bool assignTech=true;
1163   if(a->getNbOfElems()==(std::size_t)newNbOfTuples*newNbOfComp)
1164     {
1165       if(strictCompoCompare)
1166         a->checkNbOfTuplesAndComp(newNbOfTuples,newNbOfComp,msg);
1167     }
1168   else
1169     {
1170       a->checkNbOfTuplesAndComp(1,newNbOfComp,msg);
1171       assignTech=false;
1172     }
1173   const char *srcPt=a->getConstPointer();
1174   char *pt=getPointer()+bgTuples*nbComp;
1175   if(assignTech)
1176     {
1177       for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1178         for(const int *z=bgComp;z!=endComp;z++,srcPt++)
1179           pt[*z]=*srcPt;
1180     }
1181   else
1182     {
1183       for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1184         {
1185           const char *srcPt2=srcPt;
1186           for(const int *z=bgComp;z!=endComp;z++,srcPt2++)
1187             pt[*z]=*srcPt2;
1188         }
1189     }
1190 }
1191
1192 void DataArrayChar::setPartOfValuesSimple4(char a, int bgTuples, int endTuples, int stepTuples, const int *bgComp, const int *endComp) throw(INTERP_KERNEL::Exception)
1193 {
1194   const char msg[]="DataArrayInt::setPartOfValuesSimple4";
1195   checkAllocated();
1196   int newNbOfTuples=DataArray::GetNumberOfItemGivenBES(bgTuples,endTuples,stepTuples,msg);
1197   int nbComp=getNumberOfComponents();
1198   for(const int *z=bgComp;z!=endComp;z++)
1199     DataArray::CheckValueInRange(nbComp,*z,"invalid component id");
1200   int nbOfTuples=getNumberOfTuples();
1201   DataArray::CheckValueInRangeEx(nbOfTuples,bgTuples,endTuples,"invalid tuple value");
1202   char *pt=getPointer()+bgTuples*nbComp;
1203   for(int i=0;i<newNbOfTuples;i++,pt+=stepTuples*nbComp)
1204     for(const int *z=bgComp;z!=endComp;z++)
1205       pt[*z]=a;
1206 }
1207
1208 /*!
1209  * Copy some tuples from another DataArrayChar into specified tuples
1210  * of \a this array. Textual data is not copied. Both arrays must have equal number of
1211  * components.
1212  * Both the tuples to assign and the tuples to assign to are defined by a DataArrayChar.
1213  * All components of selected tuples are copied.
1214  *  \param [in] a - the array to copy values from.
1215  *  \param [in] tuplesSelec - the array specifying both source tuples of \a a and
1216  *              target tuples of \a this. \a tuplesSelec has two components, and the
1217  *              first component specifies index of the source tuple and the second
1218  *              one specifies index of the target tuple.
1219  *  \throw If \a this is not allocated.
1220  *  \throw If \a a is NULL.
1221  *  \throw If \a a is not allocated.
1222  *  \throw If \a tuplesSelec is NULL.
1223  *  \throw If \a tuplesSelec is not allocated.
1224  *  \throw If <em>this->getNumberOfComponents() != a->getNumberOfComponents()</em>.
1225  *  \throw If \a tuplesSelec->getNumberOfComponents() != 2.
1226  *  \throw If any tuple index given by \a tuplesSelec is out of a valid range for 
1227  *         the corresponding (\a this or \a a) array.
1228  */
1229 void DataArrayChar::setPartOfValuesAdv(const DataArrayChar *a, const DataArrayChar *tuplesSelec) throw(INTERP_KERNEL::Exception)
1230 {
1231   if(!a || !tuplesSelec)
1232     throw INTERP_KERNEL::Exception("DataArrayChar::setPartOfValuesAdv : DataArrayChar pointer in input is NULL !");
1233   checkAllocated();
1234   a->checkAllocated();
1235   tuplesSelec->checkAllocated();
1236   int nbOfComp=getNumberOfComponents();
1237   if(nbOfComp!=a->getNumberOfComponents())
1238     throw INTERP_KERNEL::Exception("DataArrayChar::setPartOfValuesAdv : This and a do not have the same number of components !");
1239   if(tuplesSelec->getNumberOfComponents()!=2)
1240     throw INTERP_KERNEL::Exception("DataArrayChar::setPartOfValuesAdv : Expecting to have a tuple selector DataArrayChar instance with exactly 2 components !");
1241   int thisNt=getNumberOfTuples();
1242   int aNt=a->getNumberOfTuples();
1243   char *valsToSet=getPointer();
1244   const char *valsSrc=a->getConstPointer();
1245   for(const char *tuple=tuplesSelec->begin();tuple!=tuplesSelec->end();tuple+=2)
1246     {
1247       if(tuple[1]>=0 && tuple[1]<aNt)
1248         {
1249           if(tuple[0]>=0 && tuple[0]<thisNt)
1250             std::copy(valsSrc+nbOfComp*tuple[1],valsSrc+nbOfComp*(tuple[1]+1),valsToSet+nbOfComp*tuple[0]);
1251           else
1252             {
1253               std::ostringstream oss; oss << "DataArrayChar::setPartOfValuesAdv : Tuple #" << std::distance(tuplesSelec->begin(),tuple)/2;
1254               oss << " of 'tuplesSelec' request of tuple id #" << tuple[0] << " in 'this' ! It should be in [0," << thisNt << ") !";
1255               throw INTERP_KERNEL::Exception(oss.str().c_str());
1256             }
1257         }
1258       else
1259         {
1260           std::ostringstream oss; oss << "DataArrayChar::setPartOfValuesAdv : Tuple #" << std::distance(tuplesSelec->begin(),tuple)/2;
1261           oss << " of 'tuplesSelec' request of tuple id #" << tuple[1] << " in 'a' ! It should be in [0," << aNt << ") !";
1262           throw INTERP_KERNEL::Exception(oss.str().c_str());
1263         }
1264     }
1265 }
1266
1267 /*!
1268  * Copy some tuples from another DataArrayChar (\a a) into contiguous tuples
1269  * of \a this array. Textual data is not copied. Both arrays must have equal number of
1270  * components.
1271  * The tuples to assign to are defined by index of the first tuple, and
1272  * their number is defined by \a tuplesSelec->getNumberOfTuples().
1273  * The tuples to copy are defined by values of a DataArrayChar.
1274  * All components of selected tuples are copied.
1275  *  \param [in] tupleIdStart - index of the first tuple of \a this array to assign
1276  *              values to.
1277  *  \param [in] a - the array to copy values from.
1278  *  \param [in] tuplesSelec - the array specifying tuples of \a a to copy.
1279  *  \throw If \a this is not allocated.
1280  *  \throw If \a a is NULL.
1281  *  \throw If \a a is not allocated.
1282  *  \throw If \a tuplesSelec is NULL.
1283  *  \throw If \a tuplesSelec is not allocated.
1284  *  \throw If <em>this->getNumberOfComponents() != a->getNumberOfComponents()</em>.
1285  *  \throw If \a tuplesSelec->getNumberOfComponents() != 1.
1286  *  \throw If <em>tupleIdStart + tuplesSelec->getNumberOfTuples() > this->getNumberOfTuples().</em>
1287  *  \throw If any tuple index given by \a tuplesSelec is out of a valid range for 
1288  *         \a a array.
1289  */
1290 void DataArrayChar::setContigPartOfSelectedValues(int tupleIdStart, const DataArray *aBase, const DataArrayInt *tuplesSelec) throw(INTERP_KERNEL::Exception)
1291 {
1292   if(!aBase || !tuplesSelec)
1293     throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues : input DataArray is NULL !");
1294   const DataArrayChar *a=dynamic_cast<const DataArrayChar *>(aBase);
1295   if(!a)
1296     throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues : input DataArray aBase is not a DataArrayChar !");
1297   checkAllocated();
1298   a->checkAllocated();
1299   tuplesSelec->checkAllocated();
1300   int nbOfComp=getNumberOfComponents();
1301   if(nbOfComp!=a->getNumberOfComponents())
1302     throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues : This and a do not have the same number of components !");
1303   if(tuplesSelec->getNumberOfComponents()!=1)
1304     throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues : Expecting to have a tuple selector DataArrayChar instance with exactly 1 component !");
1305   int thisNt=getNumberOfTuples();
1306   int aNt=a->getNumberOfTuples();
1307   int nbOfTupleToWrite=tuplesSelec->getNumberOfTuples();
1308   char *valsToSet=getPointer()+tupleIdStart*nbOfComp;
1309   if(tupleIdStart+nbOfTupleToWrite>thisNt)
1310     throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues : invalid number range of values to write !");
1311   const char *valsSrc=a->getConstPointer();
1312   for(const int *tuple=tuplesSelec->begin();tuple!=tuplesSelec->end();tuple++,valsToSet+=nbOfComp)
1313     {
1314       if(*tuple>=0 && *tuple<aNt)
1315         {
1316           std::copy(valsSrc+nbOfComp*(*tuple),valsSrc+nbOfComp*(*tuple+1),valsToSet);
1317         }
1318       else
1319         {
1320           std::ostringstream oss; oss << "DataArrayChar::setContigPartOfSelectedValues : Tuple #" << std::distance(tuplesSelec->begin(),tuple);
1321           oss << " of 'tuplesSelec' request of tuple id #" << *tuple << " in 'a' ! It should be in [0," << aNt << ") !";
1322           throw INTERP_KERNEL::Exception(oss.str().c_str());
1323         }
1324     }
1325 }
1326
1327 /*!
1328  * Copy some tuples from another DataArrayChar (\a a) into contiguous tuples
1329  * of \a this array. Textual data is not copied. Both arrays must have equal number of
1330  * components.
1331  * The tuples to copy are defined by three values similar to parameters of
1332  * the Python function \c range(\c start,\c stop,\c step).
1333  * The tuples to assign to are defined by index of the first tuple, and
1334  * their number is defined by number of tuples to copy.
1335  * All components of selected tuples are copied.
1336  *  \param [in] tupleIdStart - index of the first tuple of \a this array to assign
1337  *              values to.
1338  *  \param [in] a - the array to copy values from.
1339  *  \param [in] bg - index of the first tuple to copy of the array \a a.
1340  *  \param [in] end2 - index of the tuple of \a a before which the tuples to copy
1341  *              are located.
1342  *  \param [in] step - index increment to get index of the next tuple to copy.
1343  *  \throw If \a this is not allocated.
1344  *  \throw If \a a is NULL.
1345  *  \throw If \a a is not allocated.
1346  *  \throw If <em>this->getNumberOfComponents() != a->getNumberOfComponents()</em>.
1347  *  \throw If <em>tupleIdStart + len(range(bg,end2,step)) > this->getNumberOfTuples().</em>
1348  *  \throw If parameters specifying tuples to copy, do not give a
1349  *            non-empty range of increasing indices or indices are out of a valid range
1350  *            for the array \a a.
1351  */
1352 void DataArrayChar::setContigPartOfSelectedValues2(int tupleIdStart, const DataArray *aBase, int bg, int end2, int step) throw(INTERP_KERNEL::Exception)
1353 {
1354   if(!aBase)
1355     throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues2 : input DataArray is NULL !");
1356   const DataArrayChar *a=dynamic_cast<const DataArrayChar *>(aBase);
1357   if(!a)
1358     throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues2 : input DataArray aBase is not a DataArrayChar !");
1359   checkAllocated();
1360   a->checkAllocated();
1361   int nbOfComp=getNumberOfComponents();
1362   const char msg[]="DataArrayChar::setContigPartOfSelectedValues2";
1363   int nbOfTupleToWrite=DataArray::GetNumberOfItemGivenBES(bg,end2,step,msg);
1364   if(nbOfComp!=a->getNumberOfComponents())
1365     throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues2 : This and a do not have the same number of components !");
1366   int thisNt=getNumberOfTuples();
1367   int aNt=a->getNumberOfTuples();
1368   char *valsToSet=getPointer()+tupleIdStart*nbOfComp;
1369   if(tupleIdStart+nbOfTupleToWrite>thisNt)
1370     throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues2 : invalid number range of values to write !");
1371   if(end2>aNt)
1372     throw INTERP_KERNEL::Exception("DataArrayChar::setContigPartOfSelectedValues2 : invalid range of values to read !");
1373   const char *valsSrc=a->getConstPointer()+bg*nbOfComp;
1374   for(int i=0;i<nbOfTupleToWrite;i++,valsToSet+=nbOfComp,valsSrc+=step*nbOfComp)
1375     {
1376       std::copy(valsSrc,valsSrc+nbOfComp,valsToSet);
1377     }
1378 }
1379
1380 /*!
1381  * Returns a shorten copy of \a this array. The new DataArrayChar contains ranges
1382  * of tuples specified by \a ranges parameter.
1383  * For more info on renumbering see \ref MEDCouplingArrayRenumbering.
1384  *  \param [in] ranges - std::vector of std::pair's each of which defines a range
1385  *              of tuples in [\c begin,\c end) format.
1386  *  \return DataArrayChar * - the new instance of DataArrayChar that the caller
1387  *          is to delete using decrRef() as it is no more needed.
1388  *  \throw If \a end < \a begin.
1389  *  \throw If \a end > \a this->getNumberOfTuples().
1390  *  \throw If \a this is not allocated.
1391  */
1392 DataArray *DataArrayChar::selectByTupleRanges(const std::vector<std::pair<int,int> >& ranges) const throw(INTERP_KERNEL::Exception)
1393 {
1394   checkAllocated();
1395   int nbOfComp=getNumberOfComponents();
1396   int nbOfTuplesThis=getNumberOfTuples();
1397   if(ranges.empty())
1398     {
1399       MEDCouplingAutoRefCountObjectPtr<DataArrayChar> ret=buildEmptySpecializedDAChar();
1400       ret->alloc(0,nbOfComp);
1401       ret->copyStringInfoFrom(*this);
1402       return ret.retn();
1403     }
1404   int ref=ranges.front().first;
1405   int nbOfTuples=0;
1406   bool isIncreasing=true;
1407   for(std::vector<std::pair<int,int> >::const_iterator it=ranges.begin();it!=ranges.end();it++)
1408     {
1409       if((*it).first<=(*it).second)
1410         {
1411           if((*it).first>=0 && (*it).second<=nbOfTuplesThis)
1412             {
1413               nbOfTuples+=(*it).second-(*it).first;
1414               if(isIncreasing)
1415                 isIncreasing=ref<=(*it).first;
1416               ref=(*it).second;
1417             }
1418           else
1419             {
1420               std::ostringstream oss; oss << "DataArrayChar::selectByTupleRanges : on range #" << std::distance(ranges.begin(),it);
1421               oss << " (" << (*it).first << "," << (*it).second << ") is greater than number of tuples of this :" << nbOfTuples << " !";
1422               throw INTERP_KERNEL::Exception(oss.str().c_str());
1423             }
1424         }
1425       else
1426         {
1427           std::ostringstream oss; oss << "DataArrayChar::selectByTupleRanges : on range #" << std::distance(ranges.begin(),it);
1428           oss << " (" << (*it).first << "," << (*it).second << ") end is before begin !";
1429           throw INTERP_KERNEL::Exception(oss.str().c_str());
1430         }
1431     }
1432   if(isIncreasing && nbOfTuplesThis==nbOfTuples)
1433     return deepCpy();
1434   MEDCouplingAutoRefCountObjectPtr<DataArrayChar> ret=buildEmptySpecializedDAChar();
1435   ret->alloc(nbOfTuples,nbOfComp);
1436   ret->copyStringInfoFrom(*this);
1437   const char *src=getConstPointer();
1438   char *work=ret->getPointer();
1439   for(std::vector<std::pair<int,int> >::const_iterator it=ranges.begin();it!=ranges.end();it++)
1440     work=std::copy(src+(*it).first*nbOfComp,src+(*it).second*nbOfComp,work);
1441   return ret.retn();
1442 }
1443
1444 /*!
1445  * Returns a value located at specified tuple and component.
1446  * This method is equivalent to DataArrayChar::getIJ() except that validity of
1447  * parameters is checked. So this method is safe but expensive if used to go through
1448  * all values of \a this.
1449  *  \param [in] tupleId - index of tuple of interest.
1450  *  \param [in] compoId - index of component of interest.
1451  *  \return double - value located by \a tupleId and \a compoId.
1452  *  \throw If \a this is not allocated.
1453  *  \throw If condition <em>( 0 <= tupleId < this->getNumberOfTuples() )</em> is violated.
1454  *  \throw If condition <em>( 0 <= compoId < this->getNumberOfComponents() )</em> is violated.
1455  */
1456 char DataArrayChar::getIJSafe(int tupleId, int compoId) const throw(INTERP_KERNEL::Exception)
1457 {
1458   checkAllocated();
1459   if(tupleId<0 || tupleId>=getNumberOfTuples())
1460     {
1461       std::ostringstream oss; oss << "DataArrayChar::getIJSafe : request for tupleId " << tupleId << " should be in [0," << getNumberOfTuples() << ") !";
1462       throw INTERP_KERNEL::Exception(oss.str().c_str());
1463     }
1464   if(compoId<0 || compoId>=getNumberOfComponents())
1465     {
1466       std::ostringstream oss; oss << "DataArrayChar::getIJSafe : request for compoId " << compoId << " should be in [0," << getNumberOfComponents() << ") !";
1467       throw INTERP_KERNEL::Exception(oss.str().c_str());
1468     }
1469   return _mem[tupleId*_info_on_compo.size()+compoId];
1470 }
1471
1472 /*!
1473  * Returns the first value of \a this. 
1474  *  \return char - the last value of \a this array.
1475  *  \throw If \a this is not allocated.
1476  *  \throw If \a this->getNumberOfComponents() != 1.
1477  *  \throw If \a this->getNumberOfTuples() < 1.
1478  */
1479 char DataArrayChar::front() const throw(INTERP_KERNEL::Exception)
1480 {
1481   checkAllocated();
1482   if(getNumberOfComponents()!=1)
1483     throw INTERP_KERNEL::Exception("DataArrayChar::front : number of components not equal to one !");
1484   int nbOfTuples=getNumberOfTuples();
1485   if(nbOfTuples<1)
1486     throw INTERP_KERNEL::Exception("DataArrayChar::front : number of tuples must be >= 1 !");
1487   return *(getConstPointer());
1488 }
1489
1490 /*!
1491  * Returns the last value of \a this. 
1492  *  \return char - the last value of \a this array.
1493  *  \throw If \a this is not allocated.
1494  *  \throw If \a this->getNumberOfComponents() != 1.
1495  *  \throw If \a this->getNumberOfTuples() < 1.
1496  */
1497 char DataArrayChar::back() const throw(INTERP_KERNEL::Exception)
1498 {
1499   checkAllocated();
1500   if(getNumberOfComponents()!=1)
1501     throw INTERP_KERNEL::Exception("DataArrayChar::back : number of components not equal to one !");
1502   int nbOfTuples=getNumberOfTuples();
1503   if(nbOfTuples<1)
1504     throw INTERP_KERNEL::Exception("DataArrayChar::back : number of tuples must be >= 1 !");
1505   return *(getConstPointer()+nbOfTuples-1);
1506 }
1507
1508 /*!
1509  * Creates a new DataArrayChar containing IDs (indices) of tuples holding value equal to a
1510  * given one.
1511  *  \param [in] val - the value to find within \a this.
1512  *  \return DataArrayChar * - a new instance of DataArrayChar. The caller is to delete this
1513  *          array using decrRef() as it is no more needed.
1514  *  \throw If \a this is not allocated.
1515  *  \throw If \a this->getNumberOfComponents() != 1.
1516  */
1517 DataArrayInt *DataArrayChar::getIdsEqual(char val) const throw(INTERP_KERNEL::Exception)
1518 {
1519   checkAllocated();
1520   if(getNumberOfComponents()!=1)
1521     throw INTERP_KERNEL::Exception("DataArrayChar::getIdsEqual : the array must have only one component, you can call 'rearrange' method before !");
1522   const char *cptr=getConstPointer();
1523   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
1524   int nbOfTuples=getNumberOfTuples();
1525   for(int i=0;i<nbOfTuples;i++,cptr++)
1526     if(*cptr==val)
1527       ret->pushBackSilent(i);
1528   return ret.retn();
1529 }
1530
1531 /*!
1532  * Creates a new DataArrayChar containing IDs (indices) of tuples holding value \b not
1533  * equal to a given one. 
1534  *  \param [in] val - the value to ignore within \a this.
1535  *  \return DataArrayChar * - a new instance of DataArrayChar. The caller is to delete this
1536  *          array using decrRef() as it is no more needed.
1537  *  \throw If \a this is not allocated.
1538  *  \throw If \a this->getNumberOfComponents() != 1.
1539  */
1540 DataArrayInt *DataArrayChar::getIdsNotEqual(char val) const throw(INTERP_KERNEL::Exception)
1541 {
1542   checkAllocated();
1543   if(getNumberOfComponents()!=1)
1544     throw INTERP_KERNEL::Exception("DataArrayChar::getIdsNotEqual : the array must have only one component, you can call 'rearrange' method before !");
1545   const char *cptr=getConstPointer();
1546   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
1547   int nbOfTuples=getNumberOfTuples();
1548   for(int i=0;i<nbOfTuples;i++,cptr++)
1549     if(*cptr!=val)
1550       ret->pushBackSilent(i);
1551   return ret.retn();
1552 }
1553
1554 /*!
1555  * This method searches the sequence specified in input parameter \b vals in \b this.
1556  * This works only for DataArrayChar having number of components equal to one (if not an INTERP_KERNEL::Exception will be thrown).
1557  * This method differs from DataArrayChar::locateTuple in that the position is internal raw data is not considered here contrary to DataArrayChar::locateTuple.
1558  * \sa DataArrayChar::locateTuple
1559  */
1560 int DataArrayChar::search(const std::vector<char>& vals) const throw(INTERP_KERNEL::Exception)
1561 {
1562   checkAllocated();
1563   int nbOfCompo=getNumberOfComponents();
1564   if(nbOfCompo!=1)
1565     throw INTERP_KERNEL::Exception("DataArrayChar::search : works only for DataArrayChar instance with one component !");
1566   const char *cptr=getConstPointer();
1567   std::size_t nbOfVals=getNbOfElems();
1568   const char *loc=std::search(cptr,cptr+nbOfVals,vals.begin(),vals.end());
1569   if(loc!=cptr+nbOfVals)
1570     return std::distance(cptr,loc);
1571   return -1;
1572 }
1573
1574 /*!
1575  * This method is an extension of DataArrayChar::locateValue method because this method works for DataArrayChar with
1576  * any number of components excepted 0 (an INTERP_KERNEL::Exception is thrown in this case).
1577  * This method searches in \b this is there is a tuple that matched the input parameter \b tupl.
1578  * If any the tuple id is returned. If not -1 is returned.
1579  * 
1580  * This method throws an INTERP_KERNEL::Exception if the number of components in \b this mismatches with the size of
1581  * the input vector. An INTERP_KERNEL::Exception is thrown too if \b this is not allocated.
1582  *
1583  * \return tuple id where \b tupl is. -1 if no such tuple exists in \b this.
1584  * \sa DataArrayChar::search.
1585  */
1586 int DataArrayChar::locateTuple(const std::vector<char>& tupl) const throw(INTERP_KERNEL::Exception)
1587 {
1588   checkAllocated();
1589   int nbOfCompo=getNumberOfComponents();
1590   if(nbOfCompo==0)
1591     throw INTERP_KERNEL::Exception("DataArrayChar::locateTuple : 0 components in 'this' !");
1592   if(nbOfCompo!=(int)tupl.size())
1593     {
1594       std::ostringstream oss; oss << "DataArrayChar::locateTuple : 'this' contains " << nbOfCompo << " components and searching for a tuple of length " << tupl.size() << " !";
1595       throw INTERP_KERNEL::Exception(oss.str().c_str());
1596     }
1597   const char *cptr=getConstPointer();
1598   std::size_t nbOfVals=getNbOfElems();
1599   for(const char *work=cptr;work!=cptr+nbOfVals;)
1600     {
1601       work=std::search(work,cptr+nbOfVals,tupl.begin(),tupl.end());
1602       if(work!=cptr+nbOfVals)
1603         {
1604           if(std::distance(cptr,work)%nbOfCompo!=0)
1605             work++;
1606           else
1607             return std::distance(cptr,work)/nbOfCompo;
1608         }
1609     }
1610   return -1;
1611 }
1612
1613 /*!
1614  * This method is an extension of DataArrayChar::presenceOfValue method because this method works for DataArrayChar with
1615  * any number of components excepted 0 (an INTERP_KERNEL::Exception is thrown in this case).
1616  * This method searches in \b this is there is a tuple that matched the input parameter \b tupl.
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  * \sa DataArrayChar::locateTuple
1620  */
1621 bool DataArrayChar::presenceOfTuple(const std::vector<char>& tupl) const throw(INTERP_KERNEL::Exception)
1622 {
1623   return locateTuple(tupl)!=-1;
1624 }
1625
1626 /*!
1627  * Returns \a true if a given value is present within \a this one-dimensional array.
1628  *  \param [in] value - the value to find within \a this array.
1629  *  \return bool - \a true in case if \a value is present within \a this array.
1630  *  \throw If \a this is not allocated.
1631  *  \throw If \a this->getNumberOfComponents() != 1.
1632  *  \sa locateValue()
1633  */
1634 bool DataArrayChar::presenceOfValue(char value) const throw(INTERP_KERNEL::Exception)
1635 {
1636   return locateValue(value)!=-1;
1637 }
1638
1639 /*!
1640  * This method expects to be called when number of components of this is equal to one.
1641  * This method returns true if it exists a tuple so that the value is contained in \b vals.
1642  * If not any tuple contains one of the values contained in 'vals' false is returned.
1643  * \sa DataArrayChar::locateValue
1644  */
1645 bool DataArrayChar::presenceOfValue(const std::vector<char>& vals) const throw(INTERP_KERNEL::Exception)
1646 {
1647   return locateValue(vals)!=-1;
1648 }
1649
1650 /*!
1651  * This method expects to be called when number of components of this is equal to one.
1652  * This method returns the tuple id, if it exists, of the first tuple equal to \b value.
1653  * If not any tuple contains \b value -1 is returned.
1654  * \sa DataArrayChar::presenceOfValue
1655  */
1656 int DataArrayChar::locateValue(char value) const throw(INTERP_KERNEL::Exception)
1657 {
1658   checkAllocated();
1659   if(getNumberOfComponents()!=1)
1660     throw INTERP_KERNEL::Exception("DataArrayChar::presenceOfValue : the array must have only one component, you can call 'rearrange' method before !");
1661   const char *cptr=getConstPointer();
1662   int nbOfTuples=getNumberOfTuples();
1663   const char *ret=std::find(cptr,cptr+nbOfTuples,value);
1664   if(ret!=cptr+nbOfTuples)
1665     return std::distance(cptr,ret);
1666   return -1;
1667 }
1668
1669 /*!
1670  * This method expects to be called when number of components of this is equal to one.
1671  * This method returns the tuple id, if it exists, of the first tuple so that the value is contained in \b vals.
1672  * If not any tuple contains one of the values contained in 'vals' false is returned.
1673  * \sa DataArrayChar::presenceOfValue
1674  */
1675 int DataArrayChar::locateValue(const std::vector<char>& vals) const throw(INTERP_KERNEL::Exception)
1676 {
1677   checkAllocated();
1678   if(getNumberOfComponents()!=1)
1679     throw INTERP_KERNEL::Exception("DataArrayInt::presenceOfValue : the array must have only one component, you can call 'rearrange' method before !");
1680   std::set<char> vals2(vals.begin(),vals.end());
1681   const char *cptr=getConstPointer();
1682   int nbOfTuples=getNumberOfTuples();
1683   for(const char *w=cptr;w!=cptr+nbOfTuples;w++)
1684     if(vals2.find(*w)!=vals2.end())
1685       return std::distance(cptr,w);
1686   return -1;
1687 }
1688
1689 /*!
1690  * Returns the maximal value and its location within \a this one-dimensional array.
1691  *  \param [out] tupleId - index of the tuple holding the maximal value.
1692  *  \return double - the maximal value among all values of \a this array.
1693  *  \throw If \a this->getNumberOfComponents() != 1
1694  *  \throw If \a this->getNumberOfTuples() < 1
1695  */
1696 char DataArrayChar::getMaxValue(int& tupleId) const throw(INTERP_KERNEL::Exception)
1697 {
1698   checkAllocated();
1699   if(getNumberOfComponents()!=1)
1700     throw INTERP_KERNEL::Exception("DataArrayChar::getMaxValue : must be applied on DataArrayChar with only one component !");
1701   int nbOfTuples=getNumberOfTuples();
1702   if(nbOfTuples<=0)
1703     throw INTERP_KERNEL::Exception("DataArrayChar::getMaxValue : array exists but number of tuples must be > 0 !");
1704   const char *vals=getConstPointer();
1705   const char *loc=std::max_element(vals,vals+nbOfTuples);
1706   tupleId=(int)std::distance(vals,loc);
1707   return *loc;
1708 }
1709
1710 /*!
1711  * Returns the maximal value within \a this array that is allowed to have more than
1712  *  one component.
1713  *  \return char - the maximal value among all values of \a this array.
1714  *  \throw If \a this is not allocated.
1715  */
1716 char DataArrayChar::getMaxValueInArray() const throw(INTERP_KERNEL::Exception)
1717 {
1718   checkAllocated();
1719   const char *loc=std::max_element(begin(),end());
1720   return *loc;
1721 }
1722
1723 /*!
1724  * Returns the minimal value and its location within \a this one-dimensional array.
1725  *  \param [out] tupleId - index of the tuple holding the minimal value.
1726  *  \return char - the minimal value among all values of \a this array.
1727  *  \throw If \a this->getNumberOfComponents() != 1
1728  *  \throw If \a this->getNumberOfTuples() < 1
1729  */
1730 char DataArrayChar::getMinValue(int& tupleId) const throw(INTERP_KERNEL::Exception)
1731 {
1732   checkAllocated();
1733   if(getNumberOfComponents()!=1)
1734     throw INTERP_KERNEL::Exception("DataArrayChar::getMaxValue : must be applied on DataArrayChar with only one component !");
1735   int nbOfTuples=getNumberOfTuples();
1736   if(nbOfTuples<=0)
1737     throw INTERP_KERNEL::Exception("DataArrayChar::getMaxValue : array exists but number of tuples must be > 0 !");
1738   const char *vals=getConstPointer();
1739   const char *loc=std::min_element(vals,vals+nbOfTuples);
1740   tupleId=(int)std::distance(vals,loc);
1741   return *loc;
1742 }
1743
1744 /*!
1745  * Returns the minimal value within \a this array that is allowed to have more than
1746  *  one component.
1747  *  \return char - the minimal value among all values of \a this array.
1748  *  \throw If \a this is not allocated.
1749  */
1750 char DataArrayChar::getMinValueInArray() const throw(INTERP_KERNEL::Exception)
1751 {
1752   checkAllocated();
1753   const char *loc=std::min_element(begin(),end());
1754   return *loc;
1755 }
1756
1757 /*!
1758  * This method works only on data array with one component.
1759  * This method returns a newly allocated array storing stored ascendantly tuple ids in \b this so that
1760  * this[*id] in [\b vmin,\b vmax)
1761  * 
1762  * \param [in] vmin begin of range. This value is included in range.
1763  * \param [in] vmax end of range. This value is \b not included in range.
1764  * \return a newly allocated data array that the caller should deal with.
1765  */
1766 DataArrayInt *DataArrayChar::getIdsInRange(char vmin, char vmax) const throw(INTERP_KERNEL::Exception)
1767 {
1768   checkAllocated();
1769   if(getNumberOfComponents()!=1)
1770     throw INTERP_KERNEL::Exception("DataArrayChar::getIdsInRange : this must have exactly one component !");
1771   const char *cptr=getConstPointer();
1772   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
1773   int nbOfTuples=getNumberOfTuples();
1774   for(int i=0;i<nbOfTuples;i++,cptr++)
1775     if(*cptr>=vmin && *cptr<vmax)
1776       ret->pushBackSilent(i);
1777   return ret.retn();
1778 }
1779
1780 /*!
1781  * Returns a new DataArrayChar by concatenating two given arrays, so that (1) the number
1782  * of tuples in the result array is <em> a1->getNumberOfTuples() + a2->getNumberOfTuples() -
1783  * offsetA2</em> and (2)
1784  * the number of component in the result array is same as that of each of given arrays.
1785  * First \a offsetA2 tuples of \a a2 are skipped and thus are missing from the result array.
1786  * Info on components is copied from the first of the given arrays. Number of components
1787  * in the given arrays must be the same.
1788  *  \param [in] a1 - an array to include in the result array.
1789  *  \param [in] a2 - another array to include in the result array.
1790  *  \param [in] offsetA2 - number of tuples of \a a2 to skip.
1791  *  \return DataArrayChar * - the new instance of DataArrayChar.
1792  *          The caller is to delete this result array using decrRef() as it is no more
1793  *          needed.
1794  *  \throw If either \a a1 or \a a2 is NULL.
1795  *  \throw If \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents().
1796  */
1797 DataArrayChar *DataArrayChar::Aggregate(const DataArrayChar *a1, const DataArrayChar *a2)
1798 {
1799   if(!a1 || !a2)
1800     throw INTERP_KERNEL::Exception("DataArrayChar::Aggregate : input DataArrayChar instance is NULL !");
1801   std::vector<const DataArrayChar *> v(2); v[0]=a1; v[1]=a2;
1802   return Aggregate(v);
1803 }
1804
1805 /*!
1806  * Returns a new DataArrayChar by concatenating all given arrays, so that (1) the number
1807  * of tuples in the result array is a sum of the number of tuples of given arrays and (2)
1808  * the number of component in the result array is same as that of each of given arrays.
1809  * Info on components is copied from the first of the given arrays. Number of components
1810  * in the given arrays must be  the same.
1811  *  \param [in] arr - a sequence of arrays to include in the result array.
1812  *  \return DataArrayChar * - the new instance of DataArrayChar.
1813  *          The caller is to delete this result array using decrRef() as it is no more
1814  *          needed.
1815  *  \throw If all arrays within \a arr are NULL.
1816  *  \throw If getNumberOfComponents() of arrays within \a arr.
1817  */
1818 DataArrayChar *DataArrayChar::Aggregate(const std::vector<const DataArrayChar *>& arr) throw(INTERP_KERNEL::Exception)
1819 {
1820   std::vector<const DataArrayChar *> a;
1821   for(std::vector<const DataArrayChar *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
1822     if(*it4)
1823       a.push_back(*it4);
1824   if(a.empty())
1825     throw INTERP_KERNEL::Exception("DataArrayChar::Aggregate : input list must be NON EMPTY !");
1826   std::vector<const DataArrayChar *>::const_iterator it=a.begin();
1827   int nbOfComp=(*it)->getNumberOfComponents();
1828   int nbt=(*it++)->getNumberOfTuples();
1829   for(int i=1;it!=a.end();it++,i++)
1830     {
1831       if((*it)->getNumberOfComponents()!=nbOfComp)
1832         throw INTERP_KERNEL::Exception("DataArrayChar::Aggregate : Nb of components mismatch for array aggregation !");
1833       nbt+=(*it)->getNumberOfTuples();
1834     }
1835   MEDCouplingAutoRefCountObjectPtr<DataArrayChar> ret=a[0]->buildEmptySpecializedDAChar();
1836   ret->alloc(nbt,nbOfComp);
1837   char *pt=ret->getPointer();
1838   for(it=a.begin();it!=a.end();it++)
1839     pt=std::copy((*it)->getConstPointer(),(*it)->getConstPointer()+(*it)->getNbOfElems(),pt);
1840   ret->copyStringInfoFrom(*(a[0]));
1841   return ret.retn();
1842 }
1843
1844 /*!
1845  * Returns a new DataArrayChar by aggregating two given arrays, so that (1) the number
1846  * of components in the result array is a sum of the number of components of given arrays
1847  * and (2) the number of tuples in the result array is same as that of each of given
1848  * arrays. In other words the i-th tuple of result array includes all components of
1849  * i-th tuples of all given arrays.
1850  * Number of tuples in the given arrays must be the same.
1851  *  \param [in] a1 - an array to include in the result array.
1852  *  \param [in] a2 - another array to include in the result array.
1853  *  \return DataArrayChar * - the new instance of DataArrayChar.
1854  *          The caller is to delete this result array using decrRef() as it is no more
1855  *          needed.
1856  *  \throw If both \a a1 and \a a2 are NULL.
1857  *  \throw If any given array is not allocated.
1858  *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples()
1859  */
1860 DataArrayChar *DataArrayChar::Meld(const DataArrayChar *a1, const DataArrayChar *a2) throw(INTERP_KERNEL::Exception)
1861 {
1862   std::vector<const DataArrayChar *> arr(2);
1863   arr[0]=a1; arr[1]=a2;
1864   return Meld(arr);
1865 }
1866
1867 /*!
1868  * Returns a new DataArrayChar by aggregating all given arrays, so that (1) the number
1869  * of components in the result array is a sum of the number of components of given arrays
1870  * and (2) the number of tuples in the result array is same as that of each of given
1871  * arrays. In other words the i-th tuple of result array includes all components of
1872  * i-th tuples of all given arrays.
1873  * Number of tuples in the given arrays must be  the same.
1874  *  \param [in] arr - a sequence of arrays to include in the result array.
1875  *  \return DataArrayChar * - the new instance of DataArrayChar.
1876  *          The caller is to delete this result array using decrRef() as it is no more
1877  *          needed.
1878  *  \throw If all arrays within \a arr are NULL.
1879  *  \throw If any given array is not allocated.
1880  *  \throw If getNumberOfTuples() of arrays within \a arr is different.
1881  */
1882 DataArrayChar *DataArrayChar::Meld(const std::vector<const DataArrayChar *>& arr) throw(INTERP_KERNEL::Exception)
1883 {
1884   std::vector<const DataArrayChar *> a;
1885   for(std::vector<const DataArrayChar *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
1886     if(*it4)
1887       a.push_back(*it4);
1888   if(a.empty())
1889     throw INTERP_KERNEL::Exception("DataArrayChar::Meld : array must be NON empty !");
1890   std::vector<const DataArrayChar *>::const_iterator it;
1891   for(it=a.begin();it!=a.end();it++)
1892     (*it)->checkAllocated();
1893   it=a.begin();
1894   int nbOfTuples=(*it)->getNumberOfTuples();
1895   std::vector<int> nbc(a.size());
1896   std::vector<const char *> pts(a.size());
1897   nbc[0]=(*it)->getNumberOfComponents();
1898   pts[0]=(*it++)->getConstPointer();
1899   for(int i=1;it!=a.end();it++,i++)
1900     {
1901       if(nbOfTuples!=(*it)->getNumberOfTuples())
1902         throw INTERP_KERNEL::Exception("DataArrayChar::meld : mismatch of number of tuples !");
1903       nbc[i]=(*it)->getNumberOfComponents();
1904       pts[i]=(*it)->getConstPointer();
1905     }
1906   int totalNbOfComp=std::accumulate(nbc.begin(),nbc.end(),0);
1907   DataArrayChar *ret=a[0]->buildEmptySpecializedDAChar();
1908   ret->alloc(nbOfTuples,totalNbOfComp);
1909   char *retPtr=ret->getPointer();
1910   for(int i=0;i<nbOfTuples;i++)
1911     for(int j=0;j<(int)a.size();j++)
1912       {
1913         retPtr=std::copy(pts[j],pts[j]+nbc[j],retPtr);
1914         pts[j]+=nbc[j];
1915       }
1916   int k=0;
1917   for(int i=0;i<(int)a.size();i++)
1918     for(int j=0;j<nbc[i];j++,k++)
1919       ret->setInfoOnComponent(k,a[i]->getInfoOnComponent(j).c_str());
1920   return ret;
1921 }
1922
1923 /*!
1924  * Sets a C array to be used as raw data of \a this. The previously set info
1925  *  of components is retained and re-sized. 
1926  * For more info see \ref MEDCouplingArraySteps1.
1927  *  \param [in] array - the C array to be used as raw data of \a this.
1928  *  \param [in] ownership - if \a true, \a array will be deallocated at destruction of \a this.
1929  *  \param [in] type - specifies how to deallocate \a array. If \a type == ParaMEDMEM::CPP_DEALLOC,
1930  *                     \c delete [] \c array; will be called. If \a type == ParaMEDMEM::C_DEALLOC,
1931  *                     \c free(\c array ) will be called.
1932  *  \param [in] nbOfTuple - new number of tuples in \a this.
1933  *  \param [in] nbOfCompo - new number of components in \a this.
1934  */
1935 void DataArrayChar::useArray(const char *array, bool ownership,  DeallocType type, int nbOfTuple, int nbOfCompo) throw(INTERP_KERNEL::Exception)
1936 {
1937   _info_on_compo.resize(nbOfCompo);
1938   _mem.useArray(array,ownership,type,(std::size_t)nbOfTuple*nbOfCompo);
1939   declareAsNew();
1940 }
1941
1942 void DataArrayChar::useExternalArrayWithRWAccess(const char *array, int nbOfTuple, int nbOfCompo) throw(INTERP_KERNEL::Exception)
1943 {
1944   _info_on_compo.resize(nbOfCompo);
1945   _mem.useExternalArrayWithRWAccess(array,(std::size_t)nbOfTuple*nbOfCompo);
1946   declareAsNew();
1947 }
1948
1949 /*!
1950  * Returns a new instance of DataArrayByte. The caller is to delete this array
1951  * using decrRef() as it is no more needed. 
1952  */
1953 DataArrayByte *DataArrayByte::New()
1954 {
1955   return new DataArrayByte;
1956 }
1957
1958 DataArrayByteIterator *DataArrayByte::iterator()
1959 {
1960   return new DataArrayByteIterator(this);
1961 }
1962
1963 /*!
1964  * Returns a full copy of \a this. For more info on copying data arrays see
1965  * \ref MEDCouplingArrayBasicsCopyDeep.
1966  *  \return DataArrayByte * - a new instance of DataArrayByte.
1967  */
1968 DataArrayByte *DataArrayByte::deepCpy() const
1969 {
1970   return new DataArrayByte(*this);
1971 }
1972
1973 /*!
1974  * Returns either a \a deep or \a shallow copy of this array. For more info see
1975  * \ref MEDCouplingArrayBasicsCopyDeep and \ref MEDCouplingArrayBasicsCopyShallow.
1976  *  \param [in] dCpy - if \a true, a deep copy is returned, else, a shallow one.
1977  *  \return DataArrayByte * - either a new instance of DataArrayByte (if \a dCpy
1978  *          == \a true) or \a this instance (if \a dCpy == \a false).
1979  */
1980 DataArrayByte *DataArrayByte::performCpy(bool dCpy) const
1981 {
1982   if(dCpy)
1983     return deepCpy();
1984   else
1985     {
1986       incrRef();
1987       return const_cast<DataArrayByte *>(this);
1988     }
1989 }
1990
1991 /*!
1992  * Returns the only one value in \a this, if and only if number of elements
1993  * (nb of tuples * nb of components) is equal to 1, and that \a this is allocated.
1994  *  \return double - the sole value stored in \a this array.
1995  *  \throw If at least one of conditions stated above is not fulfilled.
1996  */
1997 char DataArrayByte::byteValue() const throw(INTERP_KERNEL::Exception)
1998 {
1999   if(isAllocated())
2000     {
2001       if(getNbOfElems()==1)
2002         {
2003           return *getConstPointer();
2004         }
2005       else
2006         throw INTERP_KERNEL::Exception("DataArrayByte::byteValue : DataArrayByte instance is allocated but number of elements is not equal to 1 !");
2007     }
2008   else
2009     throw INTERP_KERNEL::Exception("DataArrayByte::byteValue : DataArrayByte instance is not allocated !");
2010 }
2011
2012 DataArrayChar *DataArrayByte::buildEmptySpecializedDAChar() const throw(INTERP_KERNEL::Exception)
2013 {
2014   return DataArrayByte::New();
2015 }
2016
2017 void DataArrayByte::reprStream(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
2018 {
2019   stream << "Name of byte array : \"" << _name << "\"\n";
2020   reprWithoutNameStream(stream);
2021 }
2022
2023 void DataArrayByte::reprZipStream(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
2024 {
2025   stream << "Name of byte array : \"" << _name << "\"\n";
2026   reprZipWithoutNameStream(stream);
2027 }
2028
2029 void DataArrayByte::reprWithoutNameStream(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
2030 {
2031   DataArray::reprWithoutNameStream(stream);
2032   if(_mem.reprHeader(getNumberOfComponents(),stream))
2033     {
2034       const char *data=begin();
2035       int nbOfTuples=getNumberOfTuples();
2036       int nbCompo=getNumberOfComponents();
2037       for(int i=0;i<nbOfTuples;i++,data+=nbCompo)
2038         {
2039           stream << "Tuple #" << i << " : ";
2040           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
2041           stream << "\n";
2042         }
2043     }
2044 }
2045
2046 void DataArrayByte::reprZipWithoutNameStream(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
2047 {
2048   DataArray::reprWithoutNameStream(stream);
2049   _mem.reprZip(getNumberOfComponents(),stream);
2050 }
2051
2052 void DataArrayByte::reprCppStream(const char *varName, std::ostream& stream) const throw(INTERP_KERNEL::Exception)
2053 {
2054   int nbTuples=getNumberOfTuples(),nbComp=getNumberOfComponents();
2055   const char *data=getConstPointer();
2056   stream << "DataArrayByte *" << varName << "=DataArrayByte::New();" << std::endl;
2057   if(nbTuples*nbComp>=1)
2058     {
2059       stream << "const char " << varName << "Data[" << nbTuples*nbComp << "]={";
2060       std::copy(data,data+nbTuples*nbComp-1,std::ostream_iterator<char>(stream,","));
2061       stream << data[nbTuples*nbComp-1] << "};" << std::endl;
2062       stream << varName << "->useArray(" << varName << "Data,false,CPP_DEALLOC," << nbTuples << "," << nbComp << ");" << std::endl;
2063     }
2064   else
2065     stream << varName << "->alloc(" << nbTuples << "," << nbComp << ");" << std::endl;
2066   stream << varName << "->setName(\"" << getName() << "\");" << std::endl;
2067 }
2068
2069 /*!
2070  * Method that gives a quick overvien of \a this for python.
2071  */
2072 void DataArrayByte::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
2073 {
2074   static const std::size_t MAX_NB_OF_BYTE_IN_REPR=300;
2075   stream << "DataArrayByte C++ instance at " << this << ". ";
2076   if(isAllocated())
2077     {
2078       int nbOfCompo=(int)_info_on_compo.size();
2079       if(nbOfCompo>=1)
2080         {
2081           int nbOfTuples=getNumberOfTuples();
2082           stream << "Number of tuples : " << nbOfTuples << ". Number of components : " << nbOfCompo << "." << std::endl;
2083           reprQuickOverviewData(stream,MAX_NB_OF_BYTE_IN_REPR);
2084         }
2085       else
2086         stream << "Number of components : 0.";
2087     }
2088   else
2089     stream << "*** No data allocated ****";
2090 }
2091
2092 void DataArrayByte::reprQuickOverviewData(std::ostream& stream, std::size_t maxNbOfByteInRepr) const throw(INTERP_KERNEL::Exception)
2093 {
2094   const char *data=begin();
2095   int nbOfTuples=getNumberOfTuples();
2096   int nbOfCompo=(int)_info_on_compo.size();
2097   std::ostringstream oss2; oss2 << "[";
2098   std::string oss2Str(oss2.str());
2099   bool isFinished=true;
2100   for(int i=0;i<nbOfTuples && isFinished;i++)
2101     {
2102       if(nbOfCompo>1)
2103         {
2104           oss2 << "(";
2105           for(int j=0;j<nbOfCompo;j++,data++)
2106             {
2107               oss2 << (int)*data;
2108               if(j!=nbOfCompo-1) oss2 << ", ";
2109             }
2110           oss2 << ")";
2111         }
2112       else
2113         { oss2 << (int)*data; data++; }
2114       if(i!=nbOfTuples-1) oss2 << ", ";
2115       std::string oss3Str(oss2.str());
2116       if(oss3Str.length()<maxNbOfByteInRepr)
2117         oss2Str=oss3Str;
2118       else
2119         isFinished=false;
2120     }
2121   stream << oss2Str;
2122   if(!isFinished)
2123     stream << "... ";
2124   stream << "]";
2125 }
2126
2127 bool DataArrayByte::isEqualIfNotWhy(const DataArrayChar& other, std::string& reason) const throw(INTERP_KERNEL::Exception)
2128 {
2129   const DataArrayByte *otherC=dynamic_cast<const DataArrayByte *>(&other);
2130   if(!otherC)
2131     { reason="this is of type DataArrayByte whereas other is not a DataArrayByte instance"; return false; }
2132   return DataArrayChar::isEqualIfNotWhy(other,reason);
2133 }
2134
2135 DataArrayByteIterator::DataArrayByteIterator(DataArrayByte *da):_da(da),_pt(0),_tuple_id(0),_nb_comp(0),_nb_tuple(0)
2136 {
2137   if(_da)
2138     {
2139       _da->incrRef();
2140       if(_da->isAllocated())
2141         {
2142           _nb_comp=da->getNumberOfComponents();
2143           _nb_tuple=da->getNumberOfTuples();
2144           _pt=da->getPointer();
2145         }
2146     }
2147 }
2148
2149 DataArrayByteIterator::~DataArrayByteIterator()
2150 {
2151   if(_da)
2152     _da->decrRef();
2153 }
2154
2155 DataArrayByteTuple *DataArrayByteIterator::nextt() throw(INTERP_KERNEL::Exception)
2156 {
2157   if(_tuple_id<_nb_tuple)
2158     {
2159       _tuple_id++;
2160       DataArrayByteTuple *ret=new DataArrayByteTuple(_pt,_nb_comp);
2161       _pt+=_nb_comp;
2162       return ret;
2163     }
2164   else
2165     return 0;
2166 }
2167
2168 DataArrayByteTuple::DataArrayByteTuple(char *pt, int nbOfComp):_pt(pt),_nb_of_compo(nbOfComp)
2169 {
2170 }
2171
2172 std::string DataArrayByteTuple::repr() const throw(INTERP_KERNEL::Exception)
2173 {
2174   std::ostringstream oss; oss << "(";
2175   for(int i=0;i<_nb_of_compo-1;i++)
2176     oss << (int)_pt[i] << ", ";
2177   oss << _pt[_nb_of_compo-1] << ")";
2178   return oss.str();
2179 }
2180
2181 char DataArrayByteTuple::byteValue() const throw(INTERP_KERNEL::Exception)
2182 {
2183   if(_nb_of_compo==1)
2184     return *_pt;
2185   throw INTERP_KERNEL::Exception("DataArrayByteTuple::byteValue : DataArrayByteTuple instance has not exactly 1 component -> Not possible to convert it into an character !");
2186 }
2187
2188 /*!
2189  * This method returns a newly allocated instance the caller should dealed with by a ParaMEDMEM::DataArrayByte::decrRef.
2190  * This method performs \b no copy of data. The content is only referenced using ParaMEDMEM::DataArrayByte::useArray with ownership set to \b false.
2191  * 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
2192  * \b nbOfCompo=1 and \bnbOfTuples==this->_nb_of_elem.
2193  */
2194 DataArrayByte *DataArrayByteTuple::buildDAByte(int nbOfTuples, int nbOfCompo) const throw(INTERP_KERNEL::Exception)
2195 {
2196   if((_nb_of_compo==nbOfCompo && nbOfTuples==1) || (_nb_of_compo==nbOfTuples && nbOfCompo==1))
2197     {
2198       DataArrayByte *ret=DataArrayByte::New();
2199       ret->useExternalArrayWithRWAccess(_pt,nbOfTuples,nbOfCompo);
2200       return ret;
2201     }
2202   else
2203     {
2204       std::ostringstream oss; oss << "DataArrayByteTuple::buildDAByte : unable to build a requested DataArrayByte instance with nbofTuple=" << nbOfTuples << " and nbOfCompo=" << nbOfCompo;
2205       oss << ".\nBecause the number of elements in this is " << _nb_of_compo << " !";
2206       throw INTERP_KERNEL::Exception(oss.str().c_str());
2207     }
2208 }
2209
2210 /*!
2211  * Returns a new instance of DataArrayAsciiChar. The caller is to delete this array
2212  * using decrRef() as it is no more needed. 
2213  */
2214 DataArrayAsciiChar *DataArrayAsciiChar::New()
2215 {
2216   return new DataArrayAsciiChar;
2217 }
2218
2219 /*!
2220  * Returns a new instance of DataArrayAsciiChar. The caller is to delete this array
2221  * using decrRef() as it is no more needed. 
2222  * \param [in] st the string. This input string should have a length greater than 0. If not an excpetion will be thrown.
2223  */
2224 DataArrayAsciiChar *DataArrayAsciiChar::New(const std::string& st) throw(INTERP_KERNEL::Exception)
2225 {
2226   return new DataArrayAsciiChar(st);
2227 }
2228
2229 /*!
2230  * \param [in] st the string. This input string should have a length greater than 0. If not an excpetion will be thrown.
2231  */
2232 DataArrayAsciiChar::DataArrayAsciiChar(const std::string& st) throw(INTERP_KERNEL::Exception)
2233 {
2234   std::size_t lgth=st.length();
2235   if(lgth==0)
2236     throw INTERP_KERNEL::Exception("DataArrayAsciiChar contructor with string ! Size of input string is null !");
2237   alloc(1,lgth);
2238   std::copy(st.begin(),st.begin()+lgth,getPointer());
2239 }
2240
2241 /*!
2242  * Returns a new instance of DataArrayAsciiChar. The caller is to delete this array
2243  * using decrRef() as it is no more needed. 
2244  * 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
2245  * \a vst the remaining locations in memory will be set to character \a defaultChar.
2246  *
2247  * \param [in] defaultChar the default character used to fill not defined locations in \a this
2248  * \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
2249  *             in \a vst. If all strings are empty an INTERP_KERNEL::Exception will be thrown.
2250  *
2251  * \throw If input \a vst is empty.
2252  * \throw If all strings in \a vst are empty.
2253  */
2254 DataArrayAsciiChar *DataArrayAsciiChar::New(const std::vector<std::string>& vst, char defaultChar) throw(INTERP_KERNEL::Exception)
2255 {
2256   return new DataArrayAsciiChar(vst,defaultChar);
2257 }
2258
2259 /*!
2260  * 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
2261  * \a vst the remaining locations in memory will be set to character \a defaultChar.
2262  *
2263  * \param [in] defaultChar the default character used to fill not defined locations in \a this
2264  * \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
2265  *             in \a vst. If all strings are empty an INTERP_KERNEL::Exception will be thrown.
2266  *
2267  * \throw If input \a vst is empty.
2268  * \throw If all strings in \a vst are empty.
2269  */
2270 DataArrayAsciiChar::DataArrayAsciiChar(const std::vector<std::string>& vst, char defaultChar) throw(INTERP_KERNEL::Exception)
2271 {
2272   if(vst.empty())
2273     throw INTERP_KERNEL::Exception("DataArrayAsciiChar contructor with vector of strings ! Empty array !");
2274   std::size_t nbCompo=0;
2275   for(std::vector<std::string>::const_iterator it=vst.begin();it!=vst.end();it++)
2276     nbCompo=std::max(nbCompo,(*it).length());
2277   if(nbCompo==0)
2278     throw INTERP_KERNEL::Exception("DataArrayAsciiChar contructor with vector of strings ! All strings in not empty vector are empty !");
2279   int nbTuples=(int)vst.size();
2280   alloc(nbTuples,(int)nbCompo);
2281   char *pt=getPointer();
2282   for(int i=0;i<nbTuples;i++,pt+=nbCompo)
2283     {
2284       const std::string& tmp=vst[i];
2285       std::size_t sz=tmp.length();
2286       std::copy(tmp.begin(),tmp.begin()+sz,pt);
2287       std::fill(pt+sz,pt+nbCompo,defaultChar);
2288     }
2289 }
2290
2291 DataArrayAsciiCharIterator *DataArrayAsciiChar::iterator()
2292 {
2293   return new DataArrayAsciiCharIterator(this);
2294 }
2295
2296 /*!
2297  * Returns a full copy of \a this. For more info on copying data arrays see
2298  * \ref MEDCouplingArrayBasicsCopyDeep.
2299  *  \return DataArrayAsciiChar * - a new instance of DataArrayAsciiChar.
2300  */
2301 DataArrayAsciiChar *DataArrayAsciiChar::deepCpy() const
2302 {
2303   return new DataArrayAsciiChar(*this);
2304 }
2305
2306 /*!
2307  * Returns either a \a deep or \a shallow copy of this array. For more info see
2308  * \ref MEDCouplingArrayBasicsCopyDeep and \ref MEDCouplingArrayBasicsCopyShallow.
2309  *  \param [in] dCpy - if \a true, a deep copy is returned, else, a shallow one.
2310  *  \return DataArrayAsciiChar * - either a new instance of DataArrayAsciiChar (if \a dCpy
2311  *          == \a true) or \a this instance (if \a dCpy == \a false).
2312  */
2313 DataArrayAsciiChar *DataArrayAsciiChar::performCpy(bool dCpy) const
2314 {
2315   if(dCpy)
2316     return deepCpy();
2317   else
2318     {
2319       incrRef();
2320       return const_cast<DataArrayAsciiChar *>(this);
2321     }
2322 }
2323
2324 /*!
2325  * Returns the only one value in \a this, if and only if number of elements
2326  * (nb of tuples * nb of components) is equal to 1, and that \a this is allocated.
2327  *  \return double - the sole value stored in \a this array.
2328  *  \throw If at least one of conditions stated above is not fulfilled.
2329  */
2330 char DataArrayAsciiChar::asciiCharValue() const throw(INTERP_KERNEL::Exception)
2331 {
2332   if(isAllocated())
2333     {
2334       if(getNbOfElems()==1)
2335         {
2336           return *getConstPointer();
2337         }
2338       else
2339         throw INTERP_KERNEL::Exception("DataArrayAsciiChar::asciiCharValue : DataArrayAsciiChar instance is allocated but number of elements is not equal to 1 !");
2340     }
2341   else
2342     throw INTERP_KERNEL::Exception("DataArrayAsciiChar::asciiCharValue : DataArrayAsciiChar instance is not allocated !");
2343 }
2344
2345 DataArrayChar *DataArrayAsciiChar::buildEmptySpecializedDAChar() const throw(INTERP_KERNEL::Exception)
2346 {
2347   return DataArrayAsciiChar::New();
2348 }
2349
2350 void DataArrayAsciiChar::reprStream(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
2351 {
2352   stream << "Name of ASCII char array : \"" << _name << "\"\n";
2353   reprWithoutNameStream(stream);
2354 }
2355
2356 void DataArrayAsciiChar::reprZipStream(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
2357 {
2358   stream << "Name of ASCII char array : \"" << _name << "\"\n";
2359   reprZipWithoutNameStream(stream);
2360 }
2361
2362 void DataArrayAsciiChar::reprWithoutNameStream(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
2363 {
2364   DataArray::reprWithoutNameStream(stream);
2365   if(_mem.reprHeader(getNumberOfComponents(),stream))
2366     {
2367       const char *data=begin();
2368       int nbOfTuples=getNumberOfTuples();
2369       int nbCompo=getNumberOfComponents();
2370       for(int i=0;i<nbOfTuples;i++,data+=nbCompo)
2371         {
2372           stream << "Tuple #" << i << " : \"";
2373           std::copy(data,data+nbCompo,std::ostream_iterator<char>(stream));
2374           stream << "\"\n";
2375         }
2376     }
2377 }
2378
2379 void DataArrayAsciiChar::reprZipWithoutNameStream(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
2380 {
2381   reprWithoutNameStream(stream);
2382 }
2383
2384 void DataArrayAsciiChar::reprCppStream(const char *varName, std::ostream& stream) const throw(INTERP_KERNEL::Exception)
2385 {
2386   int nbTuples=getNumberOfTuples(),nbComp=getNumberOfComponents();
2387   const char *data=getConstPointer();
2388   stream << "DataArrayAsciiChar *" << varName << "=DataArrayAsciiChar::New();" << std::endl;
2389   if(nbTuples*nbComp>=1)
2390     {
2391       stream << "const char " << varName << "Data[" << nbTuples*nbComp << "]={";
2392       std::copy(data,data+nbTuples*nbComp-1,std::ostream_iterator<char>(stream,","));
2393       stream << data[nbTuples*nbComp-1] << "};" << std::endl;
2394       stream << varName << "->useArray(" << varName << "Data,false,CPP_DEALLOC," << nbTuples << "," << nbComp << ");" << std::endl;
2395     }
2396   else
2397     stream << varName << "->alloc(" << nbTuples << "," << nbComp << ");" << std::endl;
2398   stream << varName << "->setName(\"" << getName() << "\");" << std::endl;
2399 }
2400
2401 /*!
2402  * Method that gives a quick overvien of \a this for python.
2403  */
2404 void DataArrayAsciiChar::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
2405 {
2406   static const std::size_t MAX_NB_OF_BYTE_IN_REPR=300;
2407   stream << "DataArrayAsciiChar C++ instance at " << this << ". ";
2408   if(isAllocated())
2409     {
2410       int nbOfCompo=(int)_info_on_compo.size();
2411       if(nbOfCompo>=1)
2412         {
2413           int nbOfTuples=getNumberOfTuples();
2414           stream << "Number of tuples : " << nbOfTuples << ". Number of components : " << nbOfCompo << "." << std::endl;
2415           reprQuickOverviewData(stream,MAX_NB_OF_BYTE_IN_REPR);
2416         }
2417       else
2418         stream << "Number of components : 0.";
2419     }
2420   else
2421     stream << "*** No data allocated ****";
2422 }
2423
2424 void DataArrayAsciiChar::reprQuickOverviewData(std::ostream& stream, std::size_t maxNbOfByteInRepr) const throw(INTERP_KERNEL::Exception)
2425 {
2426   const char *data=begin();
2427   int nbOfTuples=getNumberOfTuples();
2428   int nbOfCompo=(int)_info_on_compo.size();
2429   std::ostringstream oss2; oss2 << "[";
2430   std::string oss2Str(oss2.str());
2431   bool isFinished=true;
2432   for(int i=0;i<nbOfTuples && isFinished;i++)
2433     {
2434       bool isAscii=true;
2435       for(int j=0;j<nbOfCompo;j++)
2436         if(data[j]<32) isAscii=false;
2437       if(isAscii)
2438         {
2439           oss2 << "\'";
2440           for(int j=0;j<nbOfCompo;j++,data++)
2441             oss2 << *data;
2442           oss2 << "\'";
2443         }
2444       else
2445         {
2446           oss2 << "(";
2447           for(int j=0;j<nbOfCompo;j++,data++)
2448             {
2449               oss2 << (int)*data;
2450               if(j!=nbOfCompo-1) oss2 << ", ";
2451             }
2452           oss2 << ")";
2453         }
2454       if(i!=nbOfTuples-1) oss2 << ", ";
2455       std::string oss3Str(oss2.str());
2456       if(oss3Str.length()<maxNbOfByteInRepr)
2457         oss2Str=oss3Str;
2458       else
2459         isFinished=false;
2460     }
2461   stream << oss2Str;
2462   if(!isFinished)
2463     stream << "... ";
2464   stream << "]";
2465 }
2466
2467 bool DataArrayAsciiChar::isEqualIfNotWhy(const DataArrayChar& other, std::string& reason) const throw(INTERP_KERNEL::Exception)
2468 {
2469   const DataArrayAsciiChar *otherC=dynamic_cast<const DataArrayAsciiChar *>(&other);
2470   if(!otherC)
2471     { reason="this is of type DataArrayAsciiChar whereas other is not a DataArrayAsciiChar instance"; return false; }
2472   return DataArrayChar::isEqualIfNotWhy(other,reason);
2473 }
2474
2475 DataArrayAsciiCharIterator::DataArrayAsciiCharIterator(DataArrayAsciiChar *da):_da(da),_pt(0),_tuple_id(0),_nb_comp(0),_nb_tuple(0)
2476 {
2477   if(_da)
2478     {
2479       _da->incrRef();
2480       if(_da->isAllocated())
2481         {
2482           _nb_comp=da->getNumberOfComponents();
2483           _nb_tuple=da->getNumberOfTuples();
2484           _pt=da->getPointer();
2485         }
2486     }
2487 }
2488
2489 DataArrayAsciiCharIterator::~DataArrayAsciiCharIterator()
2490 {
2491   if(_da)
2492     _da->decrRef();
2493 }
2494
2495 DataArrayAsciiCharTuple *DataArrayAsciiCharIterator::nextt() throw(INTERP_KERNEL::Exception)
2496 {
2497   if(_tuple_id<_nb_tuple)
2498     {
2499       _tuple_id++;
2500       DataArrayAsciiCharTuple *ret=new DataArrayAsciiCharTuple(_pt,_nb_comp);
2501       _pt+=_nb_comp;
2502       return ret;
2503     }
2504   else
2505     return 0;
2506 }
2507
2508 DataArrayAsciiCharTuple::DataArrayAsciiCharTuple(char *pt, int nbOfComp):_pt(pt),_nb_of_compo(nbOfComp)
2509 {
2510 }
2511
2512 std::string DataArrayAsciiCharTuple::repr() const throw(INTERP_KERNEL::Exception)
2513 {
2514   std::ostringstream oss;
2515   std::copy(_pt,_pt+_nb_of_compo,std::ostream_iterator<char>(oss));
2516   return oss.str();
2517 }
2518
2519 char DataArrayAsciiCharTuple::asciiCharValue() const throw(INTERP_KERNEL::Exception)
2520 {
2521   if(_nb_of_compo==1)
2522     return *_pt;
2523   throw INTERP_KERNEL::Exception("DataArrayAsciiCharTuple::asciiCharValue : DataArrayAsciiCharTuple instance has not exactly 1 component -> Not possible to convert it into an character !");
2524 }
2525
2526 /*!
2527  * This method returns a newly allocated instance the caller should dealed with by a ParaMEDMEM::DataArrayAsciiChar::decrRef.
2528  * This method performs \b no copy of data. The content is only referenced using ParaMEDMEM::DataArrayAsciiChar::useArray with ownership set to \b false.
2529  * 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
2530  * \b nbOfCompo=1 and \bnbOfTuples==this->_nb_of_elem.
2531  */
2532 DataArrayAsciiChar *DataArrayAsciiCharTuple::buildDAAsciiChar(int nbOfTuples, int nbOfCompo) const throw(INTERP_KERNEL::Exception)
2533 {
2534   if((_nb_of_compo==nbOfCompo && nbOfTuples==1) || (_nb_of_compo==nbOfTuples && nbOfCompo==1))
2535     {
2536       DataArrayAsciiChar *ret=DataArrayAsciiChar::New();
2537       ret->useExternalArrayWithRWAccess(_pt,nbOfTuples,nbOfCompo);
2538       return ret;
2539     }
2540   else
2541     {
2542       std::ostringstream oss; oss << "DataArrayAsciiCharTuple::buildDAAsciiChar : unable to build a requested DataArrayAsciiChar instance with nbofTuple=" << nbOfTuples << " and nbOfCompo=" << nbOfCompo;
2543       oss << ".\nBecause the number of elements in this is " << _nb_of_compo << " !";
2544       throw INTERP_KERNEL::Exception(oss.str().c_str());
2545     }
2546 }