Salome HOME
ada99dd756554407e38b0cd26f11160951b1aae2
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingMemArrayChar.cxx
1 // Copyright (C) 2007-2020  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingMemArray.txx"
22 #include "MCAuto.hxx"
23
24 #include <set>
25 #include <cmath>
26 #include <limits>
27 #include <numeric>
28 #include <algorithm>
29 #include <functional>
30
31 using namespace MEDCoupling;
32
33 template class MEDCoupling::MemArray<char>;
34 template class MEDCoupling::DataArrayTemplate<char>;
35
36 /*!
37  * Returns an integer value characterizing \a this array, which is useful for a quick
38  * comparison of many instances of DataArrayChar.
39  *  \return mcIdType - the hash value.
40  *  \throw If \a this is not allocated.
41  */
42 mcIdType DataArrayChar::getHashCode() const
43 {
44   checkAllocated();
45   std::size_t nbOfElems=getNbOfElems();
46   std::size_t ret=nbOfElems*65536;
47   std::size_t delta=3;
48   if(nbOfElems>48)
49     delta=nbOfElems/8;
50   mcIdType ret0=0;
51   const char *pt=begin();
52   for(std::size_t i=0;i<nbOfElems;i+=delta)
53     ret0+=pt[i];
54   return ToIdType(ret)+ret0;
55 }
56
57 /*!
58  * Checks if \a this and another DataArrayChar are fully equal. For more info see
59  * \ref MEDCouplingArrayBasicsCompare.
60  *  \param [in] other - an instance of DataArrayChar to compare with \a this one.
61  *  \return bool - \a true if the two arrays are equal, \a false else.
62  */
63 bool DataArrayChar::isEqual(const DataArrayChar& other) const
64 {
65   std::string tmp;
66   return isEqualIfNotWhy(other,tmp);
67 }
68
69 /*!
70  * Equivalent to DataArrayChar::isEqual except that if false the reason of
71  * mismatch is given.
72  * 
73  * \param [in] other the instance to be compared with \a this
74  * \param [out] reason In case of inequality returns the reason.
75  * \sa DataArrayChar::isEqual
76  */
77 bool DataArrayChar::isEqualIfNotWhy(const DataArrayChar& other, std::string& reason) const
78 {
79   if(!areInfoEqualsIfNotWhy(other,reason))
80     return false;
81   return _mem.isEqual(other._mem,0,reason);
82 }
83
84 /*!
85  * Checks if values of \a this and another DataArrayChar are equal. For more info see
86  * \ref MEDCouplingArrayBasicsCompare.
87  *  \param [in] other - an instance of DataArrayChar to compare with \a this one.
88  *  \return bool - \a true if the values of two arrays are equal, \a false else.
89  */
90 bool DataArrayChar::isEqualWithoutConsideringStr(const DataArrayChar& other) const
91 {
92   std::string tmp;
93   return _mem.isEqual(other._mem,0,tmp);
94 }
95
96 /*!
97  * Returns a textual and human readable representation of \a this instance of
98  * DataArrayChar. This text is shown when a DataArrayChar is printed in Python.
99  *  \return std::string - text describing \a this DataArrayChar.
100  */
101 std::string DataArrayChar::repr() const
102 {
103   std::ostringstream ret;
104   reprStream(ret);
105   return ret.str();
106 }
107
108 std::string DataArrayChar::reprZip() const
109 {
110   std::ostringstream ret;
111   reprZipStream(ret);
112   return ret.str();
113 }
114
115 /*!
116  * Creates a new DataArrayIdType and assigns all (textual and numerical) data of \a this
117  * array to the new one.
118  *  \return DataArrayIdType * - the new instance of DataArrayChar.
119  */
120 DataArrayInt *DataArrayChar::convertToIntArr() const
121 {
122   checkAllocated();
123   DataArrayInt *ret=DataArrayInt::New();
124   ret->alloc(getNumberOfTuples(),getNumberOfComponents());
125   std::size_t nbOfVals=getNbOfElems();
126   const char *src=getConstPointer();
127   int *dest=ret->getPointer();
128   std::copy(src,src+nbOfVals,dest);
129   ret->copyStringInfoFrom(*this);
130   return ret;
131 }
132
133 /*!
134  * Checks if all values in \a this array are equal to \a val.
135  *  \param [in] val - value to check equality of array values to.
136  *  \return bool - \a true if all values are \a val.
137  *  \throw If \a this is not allocated.
138  *  \throw If \a this->getNumberOfComponents() != 1
139  */
140 bool DataArrayChar::isUniform(char val) const
141 {
142   checkAllocated();
143   if(getNumberOfComponents()!=1)
144     throw INTERP_KERNEL::Exception("DataArrayChar::isUniform : must be applied on DataArrayChar with only one component, you can call 'rearrange' method before !");
145   mcIdType nbOfTuples=getNumberOfTuples();
146   const char *w=getConstPointer();
147   const char *end2=w+nbOfTuples;
148   for(;w!=end2;w++)
149     if(*w!=val)
150       return false;
151   return true;
152 }
153
154 /*!
155  * Appends components of another array to components of \a this one, tuple by tuple.
156  * So that the number of tuples of \a this array remains the same and the number of 
157  * components increases.
158  *  \param [in] other - the DataArrayChar to append to \a this one.
159  *  \throw If \a this is not allocated.
160  *  \throw If \a this and \a other arrays have different number of tuples.
161  *
162  *  \if ENABLE_EXAMPLES
163  *  \ref cpp_mcdataarrayint_meldwith "Here is a C++ example".
164  *
165  *  \ref py_mcdataarrayint_meldwith "Here is a Python example".
166  *  \endif
167  */
168 void DataArrayChar::meldWith(const DataArrayChar *other)
169 {
170   if(!other)
171     throw INTERP_KERNEL::Exception("DataArrayChar::meldWith : DataArrayChar pointer in input is NULL !");
172   checkAllocated();
173   other->checkAllocated();
174   mcIdType nbOfTuples=getNumberOfTuples();
175   if(nbOfTuples!=other->getNumberOfTuples())
176     throw INTERP_KERNEL::Exception("DataArrayChar::meldWith : mismatch of number of tuples !");
177   std::size_t nbOfComp1=getNumberOfComponents();
178   std::size_t nbOfComp2=other->getNumberOfComponents();
179   char *newArr=(char *)malloc(nbOfTuples*(nbOfComp1+nbOfComp2)*sizeof(char));
180   char *w=newArr;
181   const char *inp1=getConstPointer();
182   const char *inp2=other->getConstPointer();
183   for(mcIdType i=0;i<nbOfTuples;i++,inp1+=nbOfComp1,inp2+=nbOfComp2)
184     {
185       w=std::copy(inp1,inp1+nbOfComp1,w);
186       w=std::copy(inp2,inp2+nbOfComp2,w);
187     }
188   useArray(newArr,true,DeallocType::C_DEALLOC,nbOfTuples,nbOfComp1+nbOfComp2);
189   std::vector<std::size_t> compIds(nbOfComp2);
190   for(std::size_t i=0;i<nbOfComp2;i++)
191     compIds[i]=nbOfComp1+i;
192   copyPartOfStringInfoFrom2(compIds,*other);
193 }
194
195 /*!
196  * Creates a new DataArrayIdType containing IDs (indices) of tuples holding value equal to a
197  * given one.
198  *  \param [in] val - the value to find within \a this.
199  *  \return DataArrayIdType * - a new instance of DataArrayIdType. The caller is to delete this
200  *          array using decrRef() as it is no more needed.
201  *  \throw If \a this is not allocated.
202  *  \throw If \a this->getNumberOfComponents() != 1.
203  */
204 DataArrayIdType *DataArrayChar::findIdsEqual(char val) const
205 {
206   checkAllocated();
207   if(getNumberOfComponents()!=1)
208     throw INTERP_KERNEL::Exception("DataArrayChar::findIdsEqual : the array must have only one component, you can call 'rearrange' method before !");
209   const char *cptr=getConstPointer();
210   MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(0,1);
211   mcIdType nbOfTuples=getNumberOfTuples();
212   for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
213     if(*cptr==val)
214       ret->pushBackSilent(i);
215   return ret.retn();
216 }
217
218 /*!
219  * Creates a new DataArrayIdType containing IDs (indices) of tuples holding value \b not
220  * equal to a given one. 
221  *  \param [in] val - the value to ignore within \a this.
222  *  \return DataArrayChar * - a new instance of DataArrayChar. The caller is to delete this
223  *          array using decrRef() as it is no more needed.
224  *  \throw If \a this is not allocated.
225  *  \throw If \a this->getNumberOfComponents() != 1.
226  */
227 DataArrayIdType *DataArrayChar::findIdsNotEqual(char val) const
228 {
229   checkAllocated();
230   if(getNumberOfComponents()!=1)
231     throw INTERP_KERNEL::Exception("DataArrayChar::findIdsNotEqual : the array must have only one component, you can call 'rearrange' method before !");
232   const char *cptr=getConstPointer();
233   MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(0,1);
234   mcIdType nbOfTuples=getNumberOfTuples();
235   for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
236     if(*cptr!=val)
237       ret->pushBackSilent(i);
238   return ret.retn();
239 }
240
241 /*!
242  * This method searches the sequence specified in input parameter \b vals in \b this.
243  * This works only for DataArrayChar having number of components equal to one (if not an INTERP_KERNEL::Exception will be thrown).
244  * This method differs from DataArrayChar::findIdFirstEqualTuple in that the position is internal raw data is not considered here contrary to DataArrayChar::findIdFirstEqualTuple.
245  * \sa DataArrayChar::findIdFirstEqualTuple
246  */
247 mcIdType DataArrayChar::findIdSequence(const std::vector<char>& vals) const
248 {
249   checkAllocated();
250   if(getNumberOfComponents()!=1)
251     throw INTERP_KERNEL::Exception("DataArrayChar::findIdSequence : works only for DataArrayChar instance with one component !");
252   const char *cptr=getConstPointer();
253   std::size_t nbOfVals=getNbOfElems();
254   const char *loc=std::search(cptr,cptr+nbOfVals,vals.begin(),vals.end());
255   if(loc!=cptr+nbOfVals)
256     return ToIdType(std::distance(cptr,loc));
257   return -1;
258 }
259
260 /*!
261  * This method is an extension of DataArrayChar::findIdFirstEqual method because this method works for DataArrayChar with
262  * any number of components excepted 0 (an INTERP_KERNEL::Exception is thrown in this case).
263  * This method searches in \b this is there is a tuple that matched the input parameter \b tupl.
264  * If any the tuple id is returned. If not -1 is returned.
265  * 
266  * This method throws an INTERP_KERNEL::Exception if the number of components in \b this mismatches with the size of
267  * the input vector. An INTERP_KERNEL::Exception is thrown too if \b this is not allocated.
268  *
269  * \return tuple id where \b tupl is. -1 if no such tuple exists in \b this.
270  * \sa DataArrayChar::findIdSequence.
271  */
272 mcIdType DataArrayChar::findIdFirstEqualTuple(const std::vector<char>& tupl) const
273 {
274   checkAllocated();
275   std::size_t nbOfCompo=getNumberOfComponents();
276   if(nbOfCompo==0)
277     throw INTERP_KERNEL::Exception("DataArrayChar::findIdFirstEqualTuple : 0 components in 'this' !");
278   if(nbOfCompo!=tupl.size())
279     {
280       std::ostringstream oss; oss << "DataArrayChar::findIdFirstEqualTuple : 'this' contains " << nbOfCompo << " components and searching for a tuple of length " << tupl.size() << " !";
281       throw INTERP_KERNEL::Exception(oss.str().c_str());
282     }
283   const char *cptr=getConstPointer();
284   std::size_t nbOfVals=getNbOfElems();
285   for(const char *work=cptr;work!=cptr+nbOfVals;)
286     {
287       work=std::search(work,cptr+nbOfVals,tupl.begin(),tupl.end());
288       if(work!=cptr+nbOfVals)
289         {
290           if(std::distance(cptr,work)%nbOfCompo!=0)
291             work++;
292           else
293             return ToIdType(std::distance(cptr,work)/nbOfCompo);
294         }
295     }
296   return -1;
297 }
298
299 /*!
300  * This method is an extension of DataArrayChar::presenceOfValue method because this method works for DataArrayChar with
301  * any number of components excepted 0 (an INTERP_KERNEL::Exception is thrown in this case).
302  * This method searches in \b this is there is a tuple that matched the input parameter \b tupl.
303  * This method throws an INTERP_KERNEL::Exception if the number of components in \b this mismatches with the size of
304  * the input vector. An INTERP_KERNEL::Exception is thrown too if \b this is not allocated.
305  * \sa DataArrayChar::findIdFirstEqualTuple
306  */
307 bool DataArrayChar::presenceOfTuple(const std::vector<char>& tupl) const
308 {
309   return findIdFirstEqualTuple(tupl)!=-1;
310 }
311
312 /*!
313  * Returns \a true if a given value is present within \a this one-dimensional array.
314  *  \param [in] value - the value to find within \a this array.
315  *  \return bool - \a true in case if \a value is present within \a this array.
316  *  \throw If \a this is not allocated.
317  *  \throw If \a this->getNumberOfComponents() != 1.
318  *  \sa findIdFirstEqual()
319  */
320 bool DataArrayChar::presenceOfValue(char value) const
321 {
322   return findIdFirstEqual(value)!=-1;
323 }
324
325 /*!
326  * This method expects to be called when number of components of this is equal to one.
327  * This method returns true if it exists a tuple so that the value is contained in \b vals.
328  * If not any tuple contains one of the values contained in 'vals' false is returned.
329  * \sa DataArrayChar::findIdFirstEqual
330  */
331 bool DataArrayChar::presenceOfValue(const std::vector<char>& vals) const
332 {
333   return findIdFirstEqual(vals)!=-1;
334 }
335
336 /*!
337  * This method expects to be called when number of components of this is equal to one.
338  * This method returns the tuple id, if it exists, of the first tuple equal to \b value.
339  * If not any tuple contains \b value -1 is returned.
340  * \sa DataArrayChar::presenceOfValue
341  */
342 mcIdType DataArrayChar::findIdFirstEqual(char value) const
343 {
344   checkAllocated();
345   if(getNumberOfComponents()!=1)
346     throw INTERP_KERNEL::Exception("DataArrayChar::presenceOfValue : the array must have only one component, you can call 'rearrange' method before !");
347   const char *cptr=getConstPointer();
348   mcIdType nbOfTuples=getNumberOfTuples();
349   const char *ret=std::find(cptr,cptr+nbOfTuples,value);
350   if(ret!=cptr+nbOfTuples)
351     return ToIdType(std::distance(cptr,ret));
352   return -1;
353 }
354
355 /*!
356  * This method expects to be called when number of components of this is equal to one.
357  * This method returns the tuple id, if it exists, of the first tuple so that the value is contained in \b vals.
358  * If not any tuple contains one of the values contained in 'vals' false is returned.
359  * \sa DataArrayChar::presenceOfValue
360  */
361 mcIdType DataArrayChar::findIdFirstEqual(const std::vector<char>& vals) const
362 {
363   checkAllocated();
364   if(getNumberOfComponents()!=1)
365     throw INTERP_KERNEL::Exception("DataArrayChar::findIdFirstEqual : the array must have only one component, you can call 'rearrange' method before !");
366   std::set<char> vals2(vals.begin(),vals.end());
367   const char *cptr=getConstPointer();
368   mcIdType nbOfTuples=getNumberOfTuples();
369   for(const char *w=cptr;w!=cptr+nbOfTuples;w++)
370     if(vals2.find(*w)!=vals2.end())
371       return ToIdType(std::distance(cptr,w));
372   return -1;
373 }
374
375 /*!
376  * This method works only on data array with one component.
377  * This method returns a newly allocated array storing stored ascendantly tuple ids in \b this so that
378  * this[*id] in [\b vmin,\b vmax)
379  * 
380  * \param [in] vmin begin of range. This value is included in range.
381  * \param [in] vmax end of range. This value is \b not included in range.
382  * \return a newly allocated data array that the caller should deal with.
383  */
384 DataArrayIdType *DataArrayChar::findIdsInRange(char vmin, char vmax) const
385 {
386   checkAllocated();
387   if(getNumberOfComponents()!=1)
388     throw INTERP_KERNEL::Exception("DataArrayChar::findIdsInRange : this must have exactly one component !");
389   const char *cptr=getConstPointer();
390   MCAuto<DataArrayIdType> ret=DataArrayIdType::New(); ret->alloc(0,1);
391   mcIdType nbOfTuples=getNumberOfTuples();
392   for(mcIdType i=0;i<nbOfTuples;i++,cptr++)
393     if(*cptr>=vmin && *cptr<vmax)
394       ret->pushBackSilent(i);
395   return ret.retn();
396 }
397
398 /*!
399  * Returns a new DataArrayChar by concatenating two given arrays, so that (1) the number
400  * of tuples in the result array is <em> a1->getNumberOfTuples() + a2->getNumberOfTuples() </em> and (2)
401  * the number of component in the result array is same as that of each of given arrays.
402  * Info on components is copied from the first of the given arrays. Number of components
403  * in the given arrays must be the same.
404  *  \param [in] a1 - an array to include in the result array.
405  *  \param [in] a2 - another array to include in the result array.
406  *  \return DataArrayChar * - the new instance of DataArrayChar.
407  *          The caller is to delete this result array using decrRef() as it is no more
408  *          needed.
409  *  \throw If either \a a1 or \a a2 is NULL.
410  *  \throw If \a a1->getNumberOfComponents() != \a a2->getNumberOfComponents().
411  */
412 DataArrayChar *DataArrayChar::Aggregate(const DataArrayChar *a1, const DataArrayChar *a2)
413 {
414   if(!a1 || !a2)
415     throw INTERP_KERNEL::Exception("DataArrayChar::Aggregate : input DataArrayChar instance is NULL !");
416   std::vector<const DataArrayChar *> v(2); v[0]=a1; v[1]=a2;
417   return Aggregate(v);
418 }
419
420 /*!
421  * Returns a new DataArrayChar by concatenating all given arrays, so that (1) the number
422  * of tuples in the result array is a sum of the number of tuples of given arrays and (2)
423  * the number of component in the result array is same as that of each of given arrays.
424  * Info on components is copied from the first of the given arrays. Number of components
425  * in the given arrays must be  the same.
426  *  \param [in] arr - a sequence of arrays to include in the result array.
427  *  \return DataArrayChar * - the new instance of DataArrayChar.
428  *          The caller is to delete this result array using decrRef() as it is no more
429  *          needed.
430  *  \throw If all arrays within \a arr are NULL.
431  *  \throw If getNumberOfComponents() of arrays within \a arr.
432  */
433 DataArrayChar *DataArrayChar::Aggregate(const std::vector<const DataArrayChar *>& arr)
434 {
435   std::vector<const DataArrayChar *> a;
436   for(std::vector<const DataArrayChar *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
437     if(*it4)
438       a.push_back(*it4);
439   if(a.empty())
440     throw INTERP_KERNEL::Exception("DataArrayChar::Aggregate : input list must be NON EMPTY !");
441   std::vector<const DataArrayChar *>::const_iterator it=a.begin();
442   std::size_t nbOfComp((*it)->getNumberOfComponents());
443   mcIdType nbt=(*it++)->getNumberOfTuples();
444   for(;it!=a.end();it++)
445     {
446       if((*it)->getNumberOfComponents()!=nbOfComp)
447         throw INTERP_KERNEL::Exception("DataArrayChar::Aggregate : Nb of components mismatch for array aggregation !");
448       nbt+=(*it)->getNumberOfTuples();
449     }
450   MCAuto<DataArrayChar> ret=a[0]->buildEmptySpecializedDAChar();
451   ret->alloc(nbt,nbOfComp);
452   char *pt=ret->getPointer();
453   for(it=a.begin();it!=a.end();it++)
454     pt=std::copy((*it)->getConstPointer(),(*it)->getConstPointer()+(*it)->getNbOfElems(),pt);
455   ret->copyStringInfoFrom(*(a[0]));
456   return ret.retn();
457 }
458
459 /*!
460  * Returns a new DataArrayChar by aggregating two given arrays, so that (1) the number
461  * of components in the result array is a sum of the number of components of given arrays
462  * and (2) the number of tuples in the result array is same as that of each of given
463  * arrays. In other words the i-th tuple of result array includes all components of
464  * i-th tuples of all given arrays.
465  * Number of tuples in the given arrays must be the same.
466  *  \param [in] a1 - an array to include in the result array.
467  *  \param [in] a2 - another array to include in the result array.
468  *  \return DataArrayChar * - the new instance of DataArrayChar.
469  *          The caller is to delete this result array using decrRef() as it is no more
470  *          needed.
471  *  \throw If both \a a1 and \a a2 are NULL.
472  *  \throw If any given array is not allocated.
473  *  \throw If \a a1->getNumberOfTuples() != \a a2->getNumberOfTuples()
474  */
475 DataArrayChar *DataArrayChar::Meld(const DataArrayChar *a1, const DataArrayChar *a2)
476 {
477   std::vector<const DataArrayChar *> arr(2);
478   arr[0]=a1; arr[1]=a2;
479   return Meld(arr);
480 }
481
482 /*!
483  * Returns a new DataArrayChar by aggregating all given arrays, so that (1) the number
484  * of components in the result array is a sum of the number of components of given arrays
485  * and (2) the number of tuples in the result array is same as that of each of given
486  * arrays. In other words the i-th tuple of result array includes all components of
487  * i-th tuples of all given arrays.
488  * Number of tuples in the given arrays must be  the same.
489  *  \param [in] arr - a sequence of arrays to include in the result array.
490  *  \return DataArrayChar * - the new instance of DataArrayChar.
491  *          The caller is to delete this result array using decrRef() as it is no more
492  *          needed.
493  *  \throw If all arrays within \a arr are NULL.
494  *  \throw If any given array is not allocated.
495  *  \throw If getNumberOfTuples() of arrays within \a arr is different.
496  */
497 DataArrayChar *DataArrayChar::Meld(const std::vector<const DataArrayChar *>& arr)
498 {
499   std::vector<const DataArrayChar *> a;
500   for(std::vector<const DataArrayChar *>::const_iterator it4=arr.begin();it4!=arr.end();it4++)
501     if(*it4)
502       a.push_back(*it4);
503   if(a.empty())
504     throw INTERP_KERNEL::Exception("DataArrayChar::Meld : array must be NON empty !");
505   std::vector<const DataArrayChar *>::const_iterator it;
506   for(it=a.begin();it!=a.end();it++)
507     (*it)->checkAllocated();
508   it=a.begin();
509   mcIdType nbOfTuples=(*it)->getNumberOfTuples();
510   std::vector<std::size_t> nbc(a.size());
511   std::vector<const char *> pts(a.size());
512   nbc[0]=(*it)->getNumberOfComponents();
513   pts[0]=(*it++)->getConstPointer();
514   for(std::size_t i=1;it!=a.end();it++,i++)
515     {
516       if(nbOfTuples!=(*it)->getNumberOfTuples())
517         throw INTERP_KERNEL::Exception("DataArrayChar::meld : mismatch of number of tuples !");
518       nbc[i]=(*it)->getNumberOfComponents();
519       pts[i]=(*it)->getConstPointer();
520     }
521   std::size_t totalNbOfComp=std::accumulate(nbc.begin(),nbc.end(),(std::size_t)0);
522   DataArrayChar *ret=a[0]->buildEmptySpecializedDAChar();
523   ret->alloc(nbOfTuples,totalNbOfComp);
524   char *retPtr=ret->getPointer();
525   for(mcIdType i=0;i<nbOfTuples;i++)
526     for(std::size_t j=0;j<a.size();j++)
527       {
528         retPtr=std::copy(pts[j],pts[j]+nbc[j],retPtr);
529         pts[j]+=nbc[j];
530       }
531   std::size_t k=0;
532   for(std::size_t i=0;i<a.size();i++)
533     for(std::size_t j=0;j<nbc[i];j++,k++)
534       ret->setInfoOnComponent(k,a[i]->getInfoOnComponent(j));
535   return ret;
536 }
537
538 /*!
539  * Returns a new instance of DataArrayByte. The caller is to delete this array
540  * using decrRef() as it is no more needed. 
541  */
542 DataArrayByte *DataArrayByte::New()
543 {
544   return new DataArrayByte;
545 }
546
547 DataArrayByteIterator *DataArrayByte::iterator()
548 {
549   return new DataArrayByteIterator(this);
550 }
551
552 /*!
553  * Returns a full copy of \a this. For more info on copying data arrays see
554  * \ref MEDCouplingArrayBasicsCopyDeep.
555  *  \return DataArrayByte * - a new instance of DataArrayByte.
556  */
557 DataArrayByte *DataArrayByte::deepCopy() const
558 {
559   return new DataArrayByte(*this);
560 }
561
562 /*!
563  * Returns either a \a deep or \a shallow copy of this array. For more info see
564  * \ref MEDCouplingArrayBasicsCopyDeep and \ref MEDCouplingArrayBasicsCopyShallow.
565  *  \param [in] dCpy - if \a true, a deep copy is returned, else, a shallow one.
566  *  \return DataArrayByte * - either a new instance of DataArrayByte (if \a dCpy
567  *          == \a true) or \a this instance (if \a dCpy == \a false).
568  */
569 DataArrayByte *DataArrayByte::performCopyOrIncrRef(bool dCpy) const
570 {
571   if(dCpy)
572     return deepCopy();
573   else
574     {
575       incrRef();
576       return const_cast<DataArrayByte *>(this);
577     }
578 }
579
580 /*!
581  * Returns the only one value in \a this, if and only if number of elements
582  * (nb of tuples * nb of components) is equal to 1, and that \a this is allocated.
583  *  \return char - the sole value stored in \a this array.
584  *  \throw If at least one of conditions stated above is not fulfilled.
585  */
586 char DataArrayByte::byteValue() const
587 {
588   if(isAllocated())
589     {
590       if(getNbOfElems()==1)
591         {
592           return *getConstPointer();
593         }
594       else
595         throw INTERP_KERNEL::Exception("DataArrayByte::byteValue : DataArrayByte instance is allocated but number of elements is not equal to 1 !");
596     }
597   else
598     throw INTERP_KERNEL::Exception("DataArrayByte::byteValue : DataArrayByte instance is not allocated !");
599 }
600
601 DataArrayChar *DataArrayByte::buildEmptySpecializedDAChar() const
602 {
603   return DataArrayByte::New();
604 }
605
606 void DataArrayByte::reprStream(std::ostream& stream) const
607 {
608   stream << "Name of byte array : \"" << _name << "\"\n";
609   reprWithoutNameStream(stream);
610 }
611
612 void DataArrayByte::reprZipStream(std::ostream& stream) const
613 {
614   stream << "Name of byte array : \"" << _name << "\"\n";
615   reprZipWithoutNameStream(stream);
616 }
617
618 void DataArrayByte::reprWithoutNameStream(std::ostream& stream) const
619 {
620   DataArray::reprWithoutNameStream(stream);
621   if(_mem.reprHeader(ToIdType(getNumberOfComponents()),stream))
622     {
623       const char *data=begin();
624       mcIdType nbOfTuples=getNumberOfTuples();
625       std::size_t nbCompo=getNumberOfComponents();
626       for(mcIdType i=0;i<nbOfTuples;i++,data+=nbCompo)
627         {
628           stream << "Tuple #" << i << " : ";
629           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
630           stream << "\n";
631         }
632     }
633 }
634
635 void DataArrayByte::reprZipWithoutNameStream(std::ostream& stream) const
636 {
637   DataArray::reprWithoutNameStream(stream);
638   _mem.reprZip(ToIdType(getNumberOfComponents()),stream);
639 }
640
641 void DataArrayByte::reprCppStream(const std::string& varName, std::ostream& stream) const
642 {
643   mcIdType nbTuples=getNumberOfTuples();
644   std::size_t nbComp=getNumberOfComponents();
645   const char *data=getConstPointer();
646   stream << "DataArrayByte *" << varName << "=DataArrayByte::New();" << std::endl;
647   if(nbTuples*nbComp>=1)
648     {
649       stream << "const char " << varName << "Data[" << nbTuples*nbComp << "]={";
650       std::copy(data,data+nbTuples*nbComp-1,std::ostream_iterator<char>(stream,","));
651       stream << data[nbTuples*nbComp-1] << "};" << std::endl;
652       stream << varName << "->useArray(" << varName << "Data,false,CPP_DEALLOC," << nbTuples << "," << nbComp << ");" << std::endl;
653     }
654   else
655     stream << varName << "->alloc(" << nbTuples << "," << nbComp << ");" << std::endl;
656   stream << varName << "->setName(\"" << getName() << "\");" << std::endl;
657 }
658
659 /*!
660  * Method that gives a quick overvien of \a this for python.
661  */
662 void DataArrayByte::reprQuickOverview(std::ostream& stream) const
663 {
664   static const std::size_t MAX_NB_OF_BYTE_IN_REPR=300;
665   stream << "DataArrayByte C++ instance at " << this << ". ";
666   if(isAllocated())
667     {
668       std::size_t nbOfCompo=_info_on_compo.size();
669       if(nbOfCompo>=1)
670         {
671           mcIdType nbOfTuples=getNumberOfTuples();
672           stream << "Number of tuples : " << nbOfTuples << ". Number of components : " << nbOfCompo << "." << std::endl;
673           reprQuickOverviewData(stream,MAX_NB_OF_BYTE_IN_REPR);
674         }
675       else
676         stream << "Number of components : 0.";
677     }
678   else
679     stream << "*** No data allocated ****";
680 }
681
682 void DataArrayByte::reprQuickOverviewData(std::ostream& stream, std::size_t maxNbOfByteInRepr) const
683 {
684   const char *data=begin();
685   mcIdType nbOfTuples=getNumberOfTuples();
686   std::size_t nbOfCompo=_info_on_compo.size();
687   std::ostringstream oss2; oss2 << "[";
688   std::string oss2Str(oss2.str());
689   bool isFinished=true;
690   for(mcIdType i=0;i<nbOfTuples && isFinished;i++)
691     {
692       if(nbOfCompo>1)
693         {
694           oss2 << "(";
695           for(std::size_t j=0;j<nbOfCompo;j++,data++)
696             {
697               oss2 << (int)*data;
698               if(j!=nbOfCompo-1) oss2 << ", ";
699             }
700           oss2 << ")";
701         }
702       else
703         { oss2 << (int)*data; data++; }
704       if(i!=nbOfTuples-1) oss2 << ", ";
705       std::string oss3Str(oss2.str());
706       if(oss3Str.length()<maxNbOfByteInRepr)
707         oss2Str=oss3Str;
708       else
709         isFinished=false;
710     }
711   stream << oss2Str;
712   if(!isFinished)
713     stream << "... ";
714   stream << "]";
715 }
716
717 bool DataArrayByte::isEqualIfNotWhy(const DataArrayChar& other, std::string& reason) const
718 {
719   const DataArrayByte *otherC=dynamic_cast<const DataArrayByte *>(&other);
720   if(!otherC)
721     { reason="this is of type DataArrayByte whereas other is not a DataArrayByte instance"; return false; }
722   return DataArrayChar::isEqualIfNotWhy(other,reason);
723 }
724
725 /*!
726  * This method is \b NOT wrapped into python because it can be useful only for performance reasons in C++ context.
727  * \throw if \a this is not allocated.
728  * \throw if \a this has not exactly one component.
729  */
730 std::vector<bool> DataArrayByte::toVectorOfBool() const
731 {
732   checkAllocated();
733   if(getNumberOfComponents()!=1)
734     throw INTERP_KERNEL::Exception("DataArrayByte::toVectorOfBool : this method can be used only if this has one component !");
735   mcIdType nbt(getNumberOfTuples());
736   std::vector<bool> ret(nbt,false);
737   const char *pt(begin());
738   for(mcIdType i=0;i<nbt;i++,pt++)
739     if(*pt!=0)
740       ret[i]=true;
741   return ret;
742 }
743
744 DataArrayByteIterator::DataArrayByteIterator(DataArrayByte *da):_da(da),_pt(0),_tuple_id(0),_nb_comp(0),_nb_tuple(0)
745 {
746   if(_da)
747     {
748       _da->incrRef();
749       if(_da->isAllocated())
750         {
751           _nb_comp=da->getNumberOfComponents();
752           _nb_tuple=da->getNumberOfTuples();
753           _pt=da->getPointer();
754         }
755     }
756 }
757
758 DataArrayByteIterator::~DataArrayByteIterator()
759 {
760   if(_da)
761     _da->decrRef();
762 }
763
764 DataArrayByteTuple *DataArrayByteIterator::nextt()
765 {
766   if(_tuple_id<_nb_tuple)
767     {
768       _tuple_id++;
769       DataArrayByteTuple *ret=new DataArrayByteTuple(_pt,_nb_comp);
770       _pt+=_nb_comp;
771       return ret;
772     }
773   else
774     return 0;
775 }
776
777 DataArrayByteTuple::DataArrayByteTuple(char *pt, std::size_t nbOfComp):_pt(pt),_nb_of_compo(nbOfComp)
778 {
779 }
780
781 std::string DataArrayByteTuple::repr() const
782 {
783   std::ostringstream oss; oss << "(";
784   for(std::size_t i=0;i<_nb_of_compo-1;i++)
785     oss << (int)_pt[i] << ", ";
786   oss << _pt[_nb_of_compo-1] << ")";
787   return oss.str();
788 }
789
790 char DataArrayByteTuple::byteValue() const
791 {
792   if(_nb_of_compo==1)
793     return *_pt;
794   throw INTERP_KERNEL::Exception("DataArrayByteTuple::byteValue : DataArrayByteTuple instance has not exactly 1 component -> Not possible to convert it into an character !");
795 }
796
797 /*!
798  * This method returns a newly allocated instance the caller should dealed with by a MEDCoupling::DataArrayByte::decrRef.
799  * This method performs \b no copy of data. The content is only referenced using MEDCoupling::DataArrayByte::useArray with ownership set to \b false.
800  * 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
801  * \b nbOfCompo=1 and \bnbOfTuples==this->_nb_of_elem.
802  */
803 DataArrayByte *DataArrayByteTuple::buildDAByte(std::size_t nbOfTuples, std::size_t nbOfCompo) const
804 {
805   if((_nb_of_compo==nbOfCompo && nbOfTuples==1) || (_nb_of_compo==nbOfTuples && nbOfCompo==1))
806     {
807       DataArrayByte *ret=DataArrayByte::New();
808       ret->useExternalArrayWithRWAccess(_pt,nbOfTuples,nbOfCompo);
809       return ret;
810     }
811   else
812     {
813       std::ostringstream oss; oss << "DataArrayByteTuple::buildDAByte : unable to build a requested DataArrayByte instance with nbofTuple=" << nbOfTuples << " and nbOfCompo=" << nbOfCompo;
814       oss << ".\nBecause the number of elements in this is " << _nb_of_compo << " !";
815       throw INTERP_KERNEL::Exception(oss.str().c_str());
816     }
817 }
818
819 /*!
820  * Returns a new instance of DataArrayAsciiChar. The caller is to delete this array
821  * using decrRef() as it is no more needed. 
822  */
823 DataArrayAsciiChar *DataArrayAsciiChar::New()
824 {
825   return new DataArrayAsciiChar;
826 }
827
828 /*!
829  * Returns a new instance of DataArrayAsciiChar. The caller is to delete this array
830  * using decrRef() as it is no more needed. 
831  * \param [in] st the string. This input string should have a length greater than 0. If not an excpetion will be thrown.
832  */
833 DataArrayAsciiChar *DataArrayAsciiChar::New(const std::string& st)
834 {
835   return new DataArrayAsciiChar(st);
836 }
837
838 /*!
839  * \param [in] st the string. This input string should have a length greater than 0. If not an excpetion will be thrown.
840  */
841 DataArrayAsciiChar::DataArrayAsciiChar(const std::string& st)
842 {
843   std::size_t lgth=st.length();
844   if(lgth==0)
845     throw INTERP_KERNEL::Exception("DataArrayAsciiChar constructor with string ! Size of input string is null !");
846   alloc(1,lgth);
847   std::copy(st.begin(),st.begin()+lgth,getPointer());
848 }
849
850 /*!
851  * Returns a new instance of DataArrayAsciiChar. The caller is to delete this array
852  * using decrRef() as it is no more needed. 
853  * 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
854  * \a vst the remaining locations in memory will be set to character \a defaultChar.
855  *
856  * \param [in] defaultChar the default character used to fill not defined locations in \a this
857  * \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
858  *             in \a vst. If all strings are empty an INTERP_KERNEL::Exception will be thrown.
859  *
860  * \throw If input \a vst is empty.
861  * \throw If all strings in \a vst are empty.
862  */
863 DataArrayAsciiChar *DataArrayAsciiChar::New(const std::vector<std::string>& vst, char defaultChar)
864 {
865   return new DataArrayAsciiChar(vst,defaultChar);
866 }
867
868 /*!
869  * 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
870  * \a vst the remaining locations in memory will be set to character \a defaultChar.
871  *
872  * \param [in] defaultChar the default character used to fill not defined locations in \a this
873  * \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
874  *             in \a vst. If all strings are empty an INTERP_KERNEL::Exception will be thrown.
875  *
876  * \throw If input \a vst is empty.
877  * \throw If all strings in \a vst are empty.
878  */
879 DataArrayAsciiChar::DataArrayAsciiChar(const std::vector<std::string>& vst, char defaultChar)
880 {
881   if(vst.empty())
882     throw INTERP_KERNEL::Exception("DataArrayAsciiChar constructor with vector of strings ! Empty array !");
883   std::size_t nbCompo=0;
884   for(std::vector<std::string>::const_iterator it=vst.begin();it!=vst.end();it++)
885     nbCompo=std::max(nbCompo,(*it).length());
886   if(nbCompo==0)
887     throw INTERP_KERNEL::Exception("DataArrayAsciiChar constructor with vector of strings ! All strings in not empty vector are empty !");
888   std::size_t nbTuples=vst.size();
889   alloc(nbTuples,nbCompo);
890   char *pt=getPointer();
891   for(std::size_t i=0;i<nbTuples;i++,pt+=nbCompo)
892     {
893       const std::string& tmp=vst[i];
894       std::size_t sz=tmp.length();
895       std::copy(tmp.begin(),tmp.begin()+sz,pt);
896       std::fill(pt+sz,pt+nbCompo,defaultChar);
897     }
898 }
899
900 DataArrayAsciiCharIterator *DataArrayAsciiChar::iterator()
901 {
902   return new DataArrayAsciiCharIterator(this);
903 }
904
905 /*!
906  * Returns a full copy of \a this. For more info on copying data arrays see
907  * \ref MEDCouplingArrayBasicsCopyDeep.
908  *  \return DataArrayAsciiChar * - a new instance of DataArrayAsciiChar.
909  */
910 DataArrayAsciiChar *DataArrayAsciiChar::deepCopy() const
911 {
912   return new DataArrayAsciiChar(*this);
913 }
914
915 /*!
916  * Returns either a \a deep or \a shallow copy of this array. For more info see
917  * \ref MEDCouplingArrayBasicsCopyDeep and \ref MEDCouplingArrayBasicsCopyShallow.
918  *  \param [in] dCpy - if \a true, a deep copy is returned, else, a shallow one.
919  *  \return DataArrayAsciiChar * - either a new instance of DataArrayAsciiChar (if \a dCpy
920  *          == \a true) or \a this instance (if \a dCpy == \a false).
921  */
922 DataArrayAsciiChar *DataArrayAsciiChar::performCopyOrIncrRef(bool dCpy) const
923 {
924   if(dCpy)
925     return deepCopy();
926   else
927     {
928       incrRef();
929       return const_cast<DataArrayAsciiChar *>(this);
930     }
931 }
932
933 /*!
934  * Returns the only one value in \a this, if and only if number of elements
935  * (nb of tuples * nb of components) is equal to 1, and that \a this is allocated.
936  *  \return char - the sole value stored in \a this array.
937  *  \throw If at least one of conditions stated above is not fulfilled.
938  */
939 char DataArrayAsciiChar::asciiCharValue() const
940 {
941   if(isAllocated())
942     {
943       if(getNbOfElems()==1)
944         {
945           return *getConstPointer();
946         }
947       else
948         throw INTERP_KERNEL::Exception("DataArrayAsciiChar::asciiCharValue : DataArrayAsciiChar instance is allocated but number of elements is not equal to 1 !");
949     }
950   else
951     throw INTERP_KERNEL::Exception("DataArrayAsciiChar::asciiCharValue : DataArrayAsciiChar instance is not allocated !");
952 }
953
954 DataArrayChar *DataArrayAsciiChar::buildEmptySpecializedDAChar() const
955 {
956   return DataArrayAsciiChar::New();
957 }
958
959 void DataArrayAsciiChar::reprStream(std::ostream& stream) const
960 {
961   stream << "Name of ASCII char array : \"" << _name << "\"\n";
962   reprWithoutNameStream(stream);
963 }
964
965 void DataArrayAsciiChar::reprZipStream(std::ostream& stream) const
966 {
967   stream << "Name of ASCII char array : \"" << _name << "\"\n";
968   reprZipWithoutNameStream(stream);
969 }
970
971 void DataArrayAsciiChar::reprWithoutNameStream(std::ostream& stream) const
972 {
973   DataArray::reprWithoutNameStream(stream);
974   if(_mem.reprHeader(ToIdType(getNumberOfComponents()),stream))
975     {
976       const char *data=begin();
977       mcIdType nbOfTuples=getNumberOfTuples();
978       std::size_t nbCompo=getNumberOfComponents();
979       for(mcIdType i=0;i<nbOfTuples;i++,data+=nbCompo)
980         {
981           stream << "Tuple #" << i << " : \"";
982           std::copy(data,data+nbCompo,std::ostream_iterator<char>(stream));
983           stream << "\"\n";
984         }
985     }
986 }
987
988 void DataArrayAsciiChar::reprZipWithoutNameStream(std::ostream& stream) const
989 {
990   reprWithoutNameStream(stream);
991 }
992
993 void DataArrayAsciiChar::reprCppStream(const std::string& varName, std::ostream& stream) const
994 {
995   mcIdType nbTuples=getNumberOfTuples();
996   std::size_t nbComp=getNumberOfComponents();
997   const char *data=getConstPointer();
998   stream << "DataArrayAsciiChar *" << varName << "=DataArrayAsciiChar::New();" << std::endl;
999   if(nbTuples*nbComp>=1)
1000     {
1001       stream << "const char " << varName << "Data[" << nbTuples*nbComp << "]={";
1002       std::copy(data,data+nbTuples*nbComp-1,std::ostream_iterator<char>(stream,","));
1003       stream << data[nbTuples*nbComp-1] << "};" << std::endl;
1004       stream << varName << "->useArray(" << varName << "Data,false,CPP_DEALLOC," << nbTuples << "," << nbComp << ");" << std::endl;
1005     }
1006   else
1007     stream << varName << "->alloc(" << nbTuples << "," << nbComp << ");" << std::endl;
1008   stream << varName << "->setName(\"" << getName() << "\");" << std::endl;
1009 }
1010
1011 /*!
1012  * Method that gives a quick overvien of \a this for python.
1013  */
1014 void DataArrayAsciiChar::reprQuickOverview(std::ostream& stream) const
1015 {
1016   static const std::size_t MAX_NB_OF_BYTE_IN_REPR=300;
1017   stream << "DataArrayAsciiChar C++ instance at " << this << ". ";
1018   if(isAllocated())
1019     {
1020       std::size_t nbOfCompo=_info_on_compo.size();
1021       if(nbOfCompo>=1)
1022         {
1023           mcIdType nbOfTuples=getNumberOfTuples();
1024           stream << "Number of tuples : " << nbOfTuples << ". Number of components : " << nbOfCompo << "." << std::endl;
1025           reprQuickOverviewData(stream,MAX_NB_OF_BYTE_IN_REPR);
1026         }
1027       else
1028         stream << "Number of components : 0.";
1029     }
1030   else
1031     stream << "*** No data allocated ****";
1032 }
1033
1034 void DataArrayAsciiChar::reprQuickOverviewData(std::ostream& stream, std::size_t maxNbOfByteInRepr) const
1035 {
1036   const char *data=begin();
1037   mcIdType nbOfTuples=getNumberOfTuples();
1038   std::size_t nbOfCompo=_info_on_compo.size();
1039   std::ostringstream oss2; oss2 << "[";
1040   std::string oss2Str(oss2.str());
1041   bool isFinished=true;
1042   for(mcIdType i=0;i<nbOfTuples && isFinished;i++)
1043     {
1044       bool isAscii=true;
1045       for(std::size_t j=0;j<nbOfCompo;j++)
1046         if(data[j]<32) isAscii=false;
1047       if(isAscii)
1048         {
1049           oss2 << "\'";
1050           for(std::size_t j=0;j<nbOfCompo;j++,data++)
1051             oss2 << *data;
1052           oss2 << "\'";
1053         }
1054       else
1055         {
1056           oss2 << "(";
1057           for(std::size_t j=0;j<nbOfCompo;j++,data++)
1058             {
1059               oss2 << (int)*data;
1060               if(j!=nbOfCompo-1) oss2 << ", ";
1061             }
1062           oss2 << ")";
1063         }
1064       if(i!=nbOfTuples-1) oss2 << ", ";
1065       std::string oss3Str(oss2.str());
1066       if(oss3Str.length()<maxNbOfByteInRepr)
1067         oss2Str=oss3Str;
1068       else
1069         isFinished=false;
1070     }
1071   stream << oss2Str;
1072   if(!isFinished)
1073     stream << "... ";
1074   stream << "]";
1075 }
1076
1077 bool DataArrayAsciiChar::isEqualIfNotWhy(const DataArrayChar& other, std::string& reason) const
1078 {
1079   const DataArrayAsciiChar *otherC=dynamic_cast<const DataArrayAsciiChar *>(&other);
1080   if(!otherC)
1081     { reason="this is of type DataArrayAsciiChar whereas other is not a DataArrayAsciiChar instance"; return false; }
1082   return DataArrayChar::isEqualIfNotWhy(other,reason);
1083 }
1084
1085 DataArrayAsciiCharIterator::DataArrayAsciiCharIterator(DataArrayAsciiChar *da):_da(da),_pt(0),_tuple_id(0),_nb_comp(0),_nb_tuple(0)
1086 {
1087   if(_da)
1088     {
1089       _da->incrRef();
1090       if(_da->isAllocated())
1091         {
1092           _nb_comp=da->getNumberOfComponents();
1093           _nb_tuple=da->getNumberOfTuples();
1094           _pt=da->getPointer();
1095         }
1096     }
1097 }
1098
1099 DataArrayAsciiCharIterator::~DataArrayAsciiCharIterator()
1100 {
1101   if(_da)
1102     _da->decrRef();
1103 }
1104
1105 DataArrayAsciiCharTuple *DataArrayAsciiCharIterator::nextt()
1106 {
1107   if(_tuple_id<_nb_tuple)
1108     {
1109       _tuple_id++;
1110       DataArrayAsciiCharTuple *ret=new DataArrayAsciiCharTuple(_pt,_nb_comp);
1111       _pt+=_nb_comp;
1112       return ret;
1113     }
1114   else
1115     return 0;
1116 }
1117
1118 DataArrayAsciiCharTuple::DataArrayAsciiCharTuple(char *pt, std::size_t nbOfComp):_pt(pt),_nb_of_compo(nbOfComp)
1119 {
1120 }
1121
1122 std::string DataArrayAsciiCharTuple::repr() const
1123 {
1124   std::ostringstream oss;
1125   std::copy(_pt,_pt+_nb_of_compo,std::ostream_iterator<char>(oss));
1126   return oss.str();
1127 }
1128
1129 char DataArrayAsciiCharTuple::asciiCharValue() const
1130 {
1131   if(_nb_of_compo==1)
1132     return *_pt;
1133   throw INTERP_KERNEL::Exception("DataArrayAsciiCharTuple::asciiCharValue : DataArrayAsciiCharTuple instance has not exactly 1 component -> Not possible to convert it into an character !");
1134 }
1135
1136 /*!
1137  * This method returns a newly allocated instance the caller should dealed with by a MEDCoupling::DataArrayAsciiChar::decrRef.
1138  * This method performs \b no copy of data. The content is only referenced using MEDCoupling::DataArrayAsciiChar::useArray with ownership set to \b false.
1139  * 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
1140  * \b nbOfCompo=1 and \bnbOfTuples==this->_nb_of_elem.
1141  */
1142 DataArrayAsciiChar *DataArrayAsciiCharTuple::buildDAAsciiChar(std::size_t nbOfTuples, std::size_t nbOfCompo) const
1143 {
1144   if((_nb_of_compo==nbOfCompo && nbOfTuples==1) || (_nb_of_compo==nbOfTuples && nbOfCompo==1))
1145     {
1146       DataArrayAsciiChar *ret=DataArrayAsciiChar::New();
1147       ret->useExternalArrayWithRWAccess(_pt,nbOfTuples,nbOfCompo);
1148       return ret;
1149     }
1150   else
1151     {
1152       std::ostringstream oss; oss << "DataArrayAsciiCharTuple::buildDAAsciiChar : unable to build a requested DataArrayAsciiChar instance with nbofTuple=" << nbOfTuples << " and nbOfCompo=" << nbOfCompo;
1153       oss << ".\nBecause the number of elements in this is " << _nb_of_compo << " !";
1154       throw INTERP_KERNEL::Exception(oss.str().c_str());
1155     }
1156 }