Salome HOME
Add a test for base64 conversion
[modules/yacs.git] / src / engine / Any.cxx
1 // Copyright (C) 2006-2019  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
20 #include "Any.hxx"
21 #include "Runtime.hxx"
22 #include "TypeCode.hxx"
23 #include "InvalidExtractionException.hxx"
24
25 #include <boost/archive/iterators/base64_from_binary.hpp>
26 #include <boost/archive/iterators/binary_from_base64.hpp>
27 #include <boost/archive/iterators/transform_width.hpp>
28 #include <boost/archive/iterators/insert_linebreaks.hpp>
29 #include <boost/archive/iterators/remove_whitespace.hpp>
30
31 #include <algorithm>
32 #include <cstring>
33 #include <cstdlib>
34
35 using namespace YACS::ENGINE;
36 using namespace std;
37
38 // forbidden value int=-269488145 double=-1.54947e+231 bool=239
39 const char SeqAlloc::DFT_CHAR_VAR=-17;//0xEF
40
41 constexpr unsigned NB_BITS = 6;
42
43 constexpr unsigned char TAB[64]={46, 61, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122};
44
45 unsigned char BitAtPosSimple(char val, std::size_t bitPos)
46 {
47   return (val >> bitPos) & 0x1;
48 }
49
50 unsigned char BitAtPos(char pt0, char pt1, std::size_t bitPos)
51 {
52   if(bitPos<8)
53     return BitAtPosSimple(pt0,bitPos);
54   else
55     return BitAtPosSimple(pt1,bitPos-8);
56 }
57
58 unsigned char ChunkInternal(char pt0, char pt1, std::size_t startBitIdInByte)
59 {
60   unsigned char ret(0);
61   for(unsigned i = 0; i<NB_BITS; ++i)
62     {
63       ret |= BitAtPos(pt0,pt1,startBitIdInByte+i);
64       ret <<= 1;
65     }
66   ret >>= 1;
67   return ret;
68 }
69
70 unsigned char ChunkAtPos(const char *pt, std::size_t len, std::size_t posChunk)
71 {
72   std::size_t startByte((posChunk*NB_BITS)/8);
73   std::size_t startBitIdInByte((posChunk*NB_BITS)%8);
74   char pt1(startByte!=len-1?pt[startByte+1]:pt[startByte]);
75   return ChunkInternal(pt[startByte],pt1,startBitIdInByte);
76 }
77
78 std::size_t OnOff(std::size_t i)
79 {
80   if(i!=0)
81     return 1;
82   return 0;
83 }
84
85 std::string YACS::ENGINE::ToBase64(const std::string& bytes)
86 {//64 == 2**6
87   const char *bytesPt(bytes.c_str());
88   std::size_t input_len(bytes.size());
89   std::size_t input_len_bit(input_len*8);
90   std::size_t nb_chunks( input_len_bit/NB_BITS + OnOff((NB_BITS - input_len_bit%NB_BITS)%NB_BITS) );
91   std::string ret(nb_chunks,'\0');
92   for(std::size_t i=0;i<nb_chunks;++i)
93     {
94       unsigned char cp(ChunkAtPos(bytesPt,input_len, i));
95       ret[i] = TAB[cp];
96     }
97   return ret;
98 }
99
100 constexpr unsigned MAX_VAL_TAB2=123;
101
102 constexpr unsigned char TAB2[MAX_VAL_TAB2] = { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 128, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 128, 128, 128, 1, 128, 128, 128, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 128, 128, 128, 128, 128, 128, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 };
103
104 unsigned char BitAtPosSimple2(char val, std::size_t bitPos)
105 {
106   return ( val >> (5-bitPos) ) & 0x1;
107 }
108
109 char BitAtPosOnChunk(char pt0, char pt1, std::size_t bitPos)
110 {
111   if(bitPos<6)
112     return BitAtPosSimple2(pt0,bitPos);
113   else
114     return BitAtPosSimple2(pt1,bitPos-6);
115 }
116
117 char ByteInternal(char c0, char c1, std::size_t startBitIdInByte)
118 {
119   unsigned char ret(0);
120   char ct0(TAB2[(unsigned char)c0]),ct1(TAB2[(unsigned char)c1]);
121   for(int i = 7; i>=0; --i)
122     {
123       ret |= BitAtPosOnChunk(ct0,ct1,startBitIdInByte+i);
124       if(i!=0)
125         ret <<= 1;
126     }
127   return ret;
128 }
129
130 char ByteAtPos(const char *chunckPt, std::size_t bytePos)
131 {
132   std::size_t startChunk((bytePos*8)/NB_BITS);
133   std::size_t startBitId((bytePos*8)%NB_BITS);
134   return ByteInternal(chunckPt[startChunk],chunckPt[startChunk+1],startBitId);
135 }
136
137 std::string YACS::ENGINE::FromBase64(const std::string& bytes)
138 {
139   std::size_t nb_chunks(bytes.size());
140   const char *chunckPt(bytes.c_str());
141   std::size_t nb_bytes_output((nb_chunks*NB_BITS)/8);
142   std::string ret(nb_bytes_output,'\0');
143   for(std::size_t i = 0; i<nb_bytes_output; ++i)
144     {
145       ret[i] = ByteAtPos(chunckPt,i);
146     }
147   return ret;
148 }
149
150 StringOnHeap::StringOnHeap(const char *val):_str(strdup(val)),_len(strlen(val)),_dealloc(0)
151 {
152 }
153
154 StringOnHeap::StringOnHeap(const char *val, std::size_t len):_dealloc(0),_len(len)
155 {
156   _str=(char *)malloc(len+1);
157   std::copy(val,val+len,_str);
158   _str[len]='\0';
159 }
160
161 StringOnHeap::StringOnHeap(const std::string& val):_dealloc(0),_len(val.size()),_str(nullptr)
162 {
163   _str=(char *)malloc(val.size()+1);
164   std::copy(val.cbegin(),val.cend(),_str);
165   _str[val.size()]='\0';
166 }
167
168 /*! 
169  * \note : no copy is performed if a deallocator is given.
170  * \param val     : String in C format that is NOT copied if
171  *                  deAlloc != 0
172  * \param deAlloc : pointer on function to deallocate val after
173  *                  last use.
174  */
175 StringOnHeap::StringOnHeap(char *val, Deallocator deAlloc):_len(0),_dealloc(deAlloc)
176 {
177   if(deAlloc)
178     _str=val;
179   else
180     _str=strdup(val);
181 }
182
183 bool StringOnHeap::operator ==(const StringOnHeap& other) const
184 {
185   return strcmp(_str, other._str)==0;
186 }
187
188 StringOnHeap *StringOnHeap::deepCopy() const
189 {
190   if(_len==0)
191     return new StringOnHeap(_str);
192   else
193     return new StringOnHeap(_str,_len);
194 }
195
196 StringOnHeap::~StringOnHeap()
197 {
198   if(_dealloc)
199     _dealloc(_str);
200   else
201     free(_str);
202 }
203
204 Any::Any(TypeCode* type):_type(type)
205 {
206   _type->incrRef();
207 }
208
209 Any::Any(const Any& other):_type(other._type)
210 {
211   _type->incrRef();
212 }
213
214 Any::~Any()
215 {
216   _type->decrRef();
217 }
218
219 bool Any::IsNull(char *data)
220 {
221   if(!data)
222     return true;
223   bool isNull(true);
224   for(std::size_t i=0;i<sizeof(void *) && isNull;i++)
225     isNull=(data[i]==SeqAlloc::DFT_CHAR_VAR);
226   return isNull;
227 }
228
229 AtomAny::AtomAny(int val):Any(Runtime::_tc_int)
230 {
231   _value._i=val;
232 }
233
234 AtomAny::AtomAny(bool val):Any(Runtime::_tc_bool)
235 {
236   _value._b=val;
237 }
238
239 AtomAny::AtomAny(double val):Any(Runtime::_tc_double)
240 {
241   _value._d=val;
242 }
243
244 AtomAny::AtomAny(const char *val):Any(Runtime::_tc_string)
245 {
246   _value._s=new StringOnHeap(val);
247 }
248
249 AtomAny::AtomAny(const std::string& val):Any(Runtime::_tc_string)
250 {
251   _value._s=new StringOnHeap(val);
252 }
253
254 AtomAny::AtomAny(const AtomAny& other):Any(other)
255 {
256   if(_type->isA(Runtime::_tc_string))
257     {
258       StringOnHeap *cpy=(other._value._s)->deepCopy();
259       memcpy(&_value._s,&cpy,_type->getSizeInByteOfAnyReprInSeq());
260     }
261   else if(_type->isA(Runtime::_tc_double))
262     memcpy(&_value._d,&other._value._d,_type->getSizeInByteOfAnyReprInSeq());
263   else if(_type->isA(Runtime::_tc_int))
264     memcpy(&_value._i,&other._value._i,_type->getSizeInByteOfAnyReprInSeq());
265   else if(_type->isA(Runtime::_tc_bool))
266     memcpy(&_value._b,&other._value._b,_type->getSizeInByteOfAnyReprInSeq());
267 }
268
269 AtomAny::AtomAny(char *val, Deallocator deAlloc):Any(Runtime::_tc_string)
270 {
271   _value._s=new StringOnHeap(val,deAlloc);
272 }
273
274 AtomAny::AtomAny(char *data, TypeCode* type):Any(type)
275 {
276   if(type->isA(Runtime::_tc_string))
277     {
278       void **tmp=(void **)data;
279       StringOnHeap *cpy=((StringOnHeap *)(*tmp))->deepCopy();
280       memcpy(&_value._s,&cpy,type->getSizeInByteOfAnyReprInSeq());
281     }
282   else if(type->isA(Runtime::_tc_double))
283     memcpy(&_value._d,data,type->getSizeInByteOfAnyReprInSeq());
284   else if(type->isA(Runtime::_tc_int))
285     memcpy(&_value._i,data,type->getSizeInByteOfAnyReprInSeq());
286   else if(type->isA(Runtime::_tc_bool))
287     memcpy(&_value._b,data,type->getSizeInByteOfAnyReprInSeq());
288 }
289
290 Any *AtomAny::clone() const
291 {
292   return new AtomAny(*this);
293 }
294
295 AtomAny *AtomAny::New(char *val,Deallocator dealloc)
296 {
297   return new AtomAny(val,dealloc);
298 }
299
300 AnyPtr AtomAny::operator[](int i) const throw(YACS::Exception)
301 {
302   throw InvalidExtractionException(_type->kind(),Sequence);
303 }
304
305 AnyPtr AtomAny::operator[](const char *key) const throw(YACS::Exception)
306 {
307   throw Exception("AtomAny::operator[] : try to get a part of a partitionned data whereas atomical.");
308 }
309
310 bool AtomAny::operator ==(const Any& other) const
311 {
312   if(!_type->isA(other.getType()))
313     return false;
314   const AtomAny& otherC=(const AtomAny&) other;//cast granted due to previous lines
315   if(_type->isA(Runtime::_tc_double))
316     return _value._d==otherC._value._d;
317   else if(_type->isA(Runtime::_tc_int))
318     return _value._i==otherC._value._i;
319   else if(_type->isA(Runtime::_tc_bool))
320     return _value._b==otherC._value._b;
321   else if(_type->isA(Runtime::_tc_string))
322     return (*_value._s)==*(otherC._value._s);
323   else
324     return false;
325 }
326
327 int AtomAny::getIntValue() const throw(YACS::Exception)
328 {
329   if(_type->isA(Runtime::_tc_int))
330     return _value._i;
331   else
332     throw Exception("Value is not an int");
333 }
334
335 bool AtomAny::getBoolValue() const throw(YACS::Exception)
336 {
337   if(_type->isA(Runtime::_tc_bool))
338     return _value._b;
339   else
340     throw Exception("Value is not a bool");
341 }
342
343 double AtomAny::getDoubleValue() const throw(YACS::Exception)
344 {
345   if(_type->isA(Runtime::_tc_double))
346     return _value._d;
347   else
348     throw Exception("Value is not a double");
349 }
350
351 std::string AtomAny::getStringValue() const throw(YACS::Exception)
352 {
353   if(_type->isA(Runtime::_tc_string))
354     {
355       std::size_t sz(_value._s->size());
356       if(sz==0)
357         return string(_value._s->cStr());
358       else
359         return string(_value._s->cStr(),sz);
360     }
361   else
362     throw Exception("Value is not a string");
363 }
364
365 const char *AtomAny::getBytesValue(std::size_t& len) const
366 {
367   if(_type->isA(Runtime::_tc_string))
368     {
369       len=_value._s->size();
370       return _value._s->cStr();
371     }
372   else
373     throw Exception("Value is not a string");
374 }
375
376 /*!
377  * \note : This method put in data its zipped recursive content in data.
378  *         The ownership of the recursive content is tranfered to data.
379  *         So this owns nothing and its counter fall by 1.
380  *         For memory space minimal use, not all of '*this' is pushed at data location. 
381  * \param data : already allocated memory zone where to put compressed content of 'this'
382  */
383 void AtomAny::putMyReprAtPlace(char *data) const
384 {
385   if(_type->isA(Runtime::_tc_string))
386     {
387       StringOnHeap *tmp=_value._s->deepCopy();
388       memcpy(data,&tmp,_type->getSizeInByteOfAnyReprInSeq());
389     }
390   else if(_type->isA(Runtime::_tc_double))
391     memcpy(data,&_value._d,_type->getSizeInByteOfAnyReprInSeq());
392   else if(_type->isA(Runtime::_tc_int))
393     memcpy(data,&_value._i,_type->getSizeInByteOfAnyReprInSeq());
394   else if(_type->isA(Runtime::_tc_bool))
395     memcpy(data,&_value._b,_type->getSizeInByteOfAnyReprInSeq());
396 }
397
398 /*!
399  * \note : This method put in data its zipped recursive content in data.
400  *         The ownership of the recursive content is tranfered to data.
401  *         So this owns nothing and its counter fall by 1.
402  *         For memory space minimal use, not all of '*this' is pushed at data location.
403  *         'deepCpy' param is not used here because by definition of AtomAny deep copy is performed.
404  * \param data : already allocated memory zone where to put compressed content of 'this'
405  * \param src :
406  * \param type :
407  * \param deepCpy :
408  */
409 void AtomAny::putReprAtPlace(char *data, const char *src, const TypeCode *type, bool deepCpy)
410 {
411   if(type->isA(Runtime::_tc_string))
412     {
413       void **tmp1=(void **)src;
414       StringOnHeap *tmp=((const StringOnHeap *)(*tmp1))->deepCopy();
415       memcpy(data,&tmp,type->getSizeInByteOfAnyReprInSeq());
416     }
417   else if(type->isA(Runtime::_tc_double))
418     memcpy(data,src,type->getSizeInByteOfAnyReprInSeq());
419   else if(type->isA(Runtime::_tc_int))
420     memcpy(data,src,type->getSizeInByteOfAnyReprInSeq());
421   else if(type->isA(Runtime::_tc_bool))
422     memcpy(data,src,type->getSizeInByteOfAnyReprInSeq());
423 }
424
425 /*!
426  * \note : Opposite method of putMyReprAtPlace. But static because due to data compression
427  *         instance is lost.
428  */
429 void AtomAny::destroyReprAtPlace(char *data, const TypeCode *type)
430 {
431   DynType typ=type->kind();
432   if(typ==String)
433     {
434       if(!Any::IsNull(data))
435         {
436           void **tmp=(void **)data;
437           delete ((StringOnHeap *)(*tmp));
438         }
439     }
440 }
441
442 AnyPtr AtomAny::getOrBuildFromData(char *data, const TypeCode *type)
443 {
444   Any *ret;
445   ret=new AtomAny(data,(TypeCode *)type);
446   return AnyPtr(ret);
447 }
448
449 bool AtomAny::takeInChargeStorageOf(TypeCode *type)
450 {
451   DynType typ=type->kind();
452   return (typ==Double || typ==Int || typ==Bool || typ==String);
453 }
454
455 AtomAny::~AtomAny()
456 {
457   if(_type->kind() == String)
458     delete _value._s;
459 }
460
461 ComposedAny::ComposedAny(const ComposedAny& other):Any(other)
462 {
463 }
464
465 ComposedAny::ComposedAny(TypeCode* type, bool isNew):Any(type)
466 {
467   if(isNew)
468     _type->decrRef();
469 }
470
471 AnyPtr ComposedAny::operator[](const char *key) const throw(YACS::Exception)
472 {
473   throw Exception("AtomAny::operator[] : try to get a part of a partitionned data not localizable by a string.");
474 }
475
476 void ComposedAny::checkTypeOf(const Any *elem) const throw(YACS::Exception)
477 {
478   if(!elem->getType()->isA(_type->contentType()))
479     throw Exception("ComposedAny::checkTypeOf : invalid type.");
480 }
481
482 int ComposedAny::getIntValue() const throw(YACS::Exception)
483 {
484  throw InvalidExtractionException(_type->kind(),Runtime::_tc_int->kind());
485 }
486
487 bool ComposedAny::getBoolValue() const throw(YACS::Exception)
488 {
489   throw InvalidExtractionException(_type->kind(),Runtime::_tc_bool->kind());
490 }
491
492 double ComposedAny::getDoubleValue() const throw(YACS::Exception)
493 {
494   throw InvalidExtractionException(_type->kind(),Runtime::_tc_double->kind());
495 }
496
497 std::string ComposedAny::getStringValue() const throw(YACS::Exception)
498 {
499   throw InvalidExtractionException(_type->kind(),Runtime::_tc_string->kind());
500 }
501
502 SeqAlloc::SeqAlloc(const SeqAlloc& other):_sizeOf1Elm(other._sizeOf1Elm),_notStdDeAlloc(0),
503  _start(0),_finish(0),_endOfStorage(0)
504 {
505   _start=allocate(other._finish-other._start);
506   _finish=_start+(other._finish-other._start);
507   _endOfStorage=_finish;
508 }
509
510 SeqAlloc::SeqAlloc(unsigned int sizeOf1Elm):_sizeOf1Elm(sizeOf1Elm),_notStdDeAlloc(0),
511                                             _start(0),_finish(0),_endOfStorage(0)
512 {
513 }
514
515 SeqAlloc::~SeqAlloc()
516 {
517   deallocate(_start);
518 }
519
520 void SeqAlloc::clear()
521 {
522   deallocate(_start);
523   _start=0;
524   _finish=0;
525   _endOfStorage=0;
526 }
527
528 /*!
529  * \note : This method is exclusively reserved for arrays of C++ built-in types because no
530  *         constructor is applied atomically.
531  */
532 void SeqAlloc::initCoarseMemory(char *mem, unsigned int size, Deallocator dealloc)
533 {
534   unsigned sizeInByte=size*_sizeOf1Elm;
535   if(dealloc)
536     {
537       _notStdDeAlloc=dealloc;
538       _start=mem;
539     }
540   else
541     {
542       _start=allocate(sizeInByte);
543       if(mem)
544         memcpy(_start,mem,sizeInByte);
545       else
546         {
547           for(unsigned int i=0;i<sizeInByte;i++) _start[i]=DFT_CHAR_VAR;// see getSetItems
548         }
549     }
550   _finish=_start+sizeInByte;
551   _endOfStorage=_finish;
552 }
553
554 void SeqAlloc::construct(char *pt, const Any *val)
555 {
556   val->putMyReprAtPlace(pt);
557 }
558
559 /*!
560  * \note: This performs the placement new or zip info into pt.
561  * \param pt :
562  * \param val     : the source from which the construction will be performed.
563  * \param tc  :
564  * \param deepCpy : If true in pt place a deep copy pointed by val will be put.
565  */
566 void SeqAlloc::construct(char *pt, const char *val, const TypeCode *tc, bool deepCpy)
567 {
568   tc->putReprAtPlace(pt,val,deepCpy);
569 }
570
571 char *SeqAlloc::allocate(unsigned int nbOfByte)
572
573   if(nbOfByte>0)
574     return (char *)::operator new(nbOfByte);
575   else
576     return 0;
577 }
578
579 // pt is not permitted to be a null pointer.
580 void SeqAlloc::deallocate(char *pt)
581
582   if(pt)
583     {
584       if(!_notStdDeAlloc)
585         ::operator delete(pt); 
586       else
587         {
588           _notStdDeAlloc(pt);
589           _notStdDeAlloc=0;
590         }
591     }
592 }
593
594 void SeqAlloc::destroy(char *pt, const TypeCode *tc) 
595
596   tc->destroyZippedAny(pt);
597 }
598
599 unsigned int SeqAlloc::size() const
600 {
601   return (_finish-_start)/_sizeOf1Elm;
602 }
603
604 std::vector<unsigned int> SeqAlloc::getSetItems() const
605 {
606   std::vector<unsigned int> ret;
607   unsigned int sz(size());
608   for(unsigned int i=0;i<sz;i++)
609     {
610       const char *pt(_start+i*_sizeOf1Elm);
611       for(unsigned j=0;j<_sizeOf1Elm && *pt==DFT_CHAR_VAR;j++,pt++); //see initCoarseMemory
612       if(pt!=_start+(i+1)*_sizeOf1Elm)
613         ret.push_back(i);
614     }
615   return ret;
616 }
617
618 void SequenceAny::clear()
619 {
620   for (char *cur=_alloc._start;cur!=_alloc._finish;cur+=_alloc._sizeOf1Elm)
621     _alloc.destroy(cur,_type->contentType());
622   _alloc.clear();
623 }
624
625 void SequenceAny::popBack()
626 {
627   _alloc._finish-=_alloc._sizeOf1Elm;
628   _alloc.destroy(_alloc._finish,_type->contentType());
629 }
630
631 void SequenceAny::pushBack(const Any* elem)
632 {
633   if(!elem->_type->isA(_type->contentType()))
634     throw InvalidExtractionException(elem->_type->kind(),_type->contentType()->kind());
635   if(_alloc._finish != _alloc._endOfStorage)
636     {
637       _alloc.construct(_alloc._finish, elem);
638       _alloc._finish+=_alloc._sizeOf1Elm;
639     }
640   else
641     realloc(_alloc._finish, elem);
642 }
643
644 bool SequenceAny::operator ==(const Any& other) const
645 {
646   if(!_type->isA(other.getType()))
647     return false;
648   const SequenceAny& otherC=(const SequenceAny&) other;//cast granted due to previous lines
649   if(size()!=otherC.size())
650     return false;
651   for(unsigned i=0;i<size();i++)
652     if(!((*(*this)[i])==(*otherC[i])))
653       return false;
654   return true;
655 }
656
657 void SequenceAny::setEltAtRank(int i, const Any *elem) throw(YACS::Exception)
658 {
659   checkTypeOf(elem);
660   _alloc.destroy(_alloc._start+i*_alloc._sizeOf1Elm,_type->contentType());
661   _alloc.construct(_alloc._start+i*_alloc._sizeOf1Elm,elem);
662 }
663
664 AnyPtr SequenceAny::operator[](int i) const throw(YACS::Exception)
665 {
666   return _type->contentType()->getOrBuildAnyFromZippedData(_alloc._start+i*_alloc._sizeOf1Elm);
667 }
668
669 /*!
670  * \note : Contrary to AtomAny 'this' (ref) is put in data NOT a deep copy.
671  * \param data : already allocated memory zone where to put address of 'this'
672  */
673 void SequenceAny::putMyReprAtPlace(char *data) const
674 {
675   const void *tmp=(const void *)this;
676   memcpy(data,&tmp,_type->getSizeInByteOfAnyReprInSeq());
677   const void **tmp2=(const void **) data;
678   ((SequenceAny *)(*tmp2))->incrRef();
679   //::new((SequenceAny *)data) SequenceAny((SequenceAny&) (*this));
680 }
681
682 void SequenceAny::putReprAtPlace(char *data, const char *src, const TypeCode *type, bool deepCpy)
683 {
684   void **tmp2=(void **) src;
685   if(!deepCpy)
686     {
687       ((SequenceAny *)(*tmp2))->incrRef();
688       memcpy(data,src,type->getSizeInByteOfAnyReprInSeq());
689     }
690   else
691     {
692       SequenceAny *cpy=new SequenceAny(*((SequenceAny *)(*tmp2)));
693       memcpy(data,&cpy,type->getSizeInByteOfAnyReprInSeq());
694     }
695   //::new((SequenceAny *)data) SequenceAny((SequenceAny&) (*this));
696 }
697
698 void SequenceAny::destroyReprAtPlace(char *data, const TypeCode *type)
699 {
700   void **tmp=(void **) data;
701   if(!Any::IsNull(data))
702     ((SequenceAny *)(*tmp))->decrRef();
703   //((SequenceAny *)data)->~SequenceAny();
704 }
705
706 AnyPtr SequenceAny::getOrBuildFromData(char *data, const TypeCode *type)
707 {
708   void **tmp=(void **) data;
709   ((SequenceAny *) (*tmp))->incrRef();
710   return AnyPtr((SequenceAny *)(*tmp));
711 }
712
713 Any *SequenceAny::clone() const
714 {
715   return new SequenceAny(*this);
716 }
717
718 SequenceAny *SequenceAny::removeUnsetItemsFromThis() const
719 {
720   std::vector<unsigned int> its(getSetItems());
721   std::size_t sz(its.size());
722   SequenceAny *ret(SequenceAny::New(getType()->contentType(),sz));
723   for(std::size_t i=0;i<sz;i++)
724     {
725       AnyPtr obj((*this)[its[i]]);
726       ret->setEltAtRank(i,obj);
727     }
728   return ret;
729 }
730
731 SequenceAny *SequenceAny::New(const TypeCode *typeOfContent)
732 {
733   if(typeOfContent->kind() == Objref)
734     {
735       //In case of Objref, use a sequence of string
736       return new SequenceAny(Runtime::_tc_string);
737     }
738   else
739     return new SequenceAny(typeOfContent);
740 }
741
742 SequenceAny *SequenceAny::New(const TypeCode *typeOfContent, unsigned lgth)
743 {
744   if(typeOfContent->kind() == Objref)
745     {
746       //In case of Objref, use a sequence of string
747       return new SequenceAny(Runtime::_tc_string,lgth);
748     }
749   else
750     return new SequenceAny(typeOfContent,lgth);
751 }
752
753 bool SequenceAny::takeInChargeStorageOf(TypeCode *type)
754 {
755   DynType typ=type->kind();
756   return (typ==Sequence);
757 }
758
759 SequenceAny::SequenceAny(const SequenceAny& other):ComposedAny(other),_alloc(other._alloc)
760 {
761   const char *srcCur=other._alloc._start;
762   for(char *cur=_alloc._start;srcCur != other._alloc._finish; srcCur+=_alloc._sizeOf1Elm, cur+=_alloc._sizeOf1Elm)
763     _alloc.construct(cur, srcCur, _type->contentType(),true);
764 }
765
766 SequenceAny::~SequenceAny()
767 {
768   for (char *cur=_alloc._start;cur!=_alloc._finish;cur+=_alloc._sizeOf1Elm)
769     _alloc.destroy(cur,_type->contentType());
770 }
771
772 /*!
773  * \param typeOfContent : typeCode of the type of elements stored in sequence.
774  */
775 SequenceAny::SequenceAny(const TypeCode *typeOfContent):ComposedAny(new TypeCodeSeq("","",typeOfContent)),
776                                                         _alloc(typeOfContent->getSizeInByteOfAnyReprInSeq())
777 {
778 }
779
780 SequenceAny::SequenceAny(const TypeCode *typeOfContent, unsigned lgth):ComposedAny(new TypeCodeSeq("","",typeOfContent)),
781                                                                        _alloc(typeOfContent->getSizeInByteOfAnyReprInSeq())
782 {
783   _alloc.initCoarseMemory(0,lgth,0);
784 }
785
786 SequenceAny::SequenceAny(int *val, unsigned int lgth, Deallocator deAlloc):ComposedAny(new TypeCodeSeq("","",Runtime::_tc_int)),
787                                                                            _alloc(Runtime::_tc_int->getSizeInByteOfAnyReprInSeq())
788 {
789   _alloc.initCoarseMemory((char *)val,lgth,deAlloc);
790 }
791
792 SequenceAny::SequenceAny(bool *val, unsigned int lgth, Deallocator deAlloc):ComposedAny(new TypeCodeSeq("","",Runtime::_tc_bool)),
793                                                                             _alloc(Runtime::_tc_bool->getSizeInByteOfAnyReprInSeq())
794 {
795   _alloc.initCoarseMemory((char *)val,lgth,deAlloc);
796 }
797
798 SequenceAny::SequenceAny(double *val, unsigned int lgth, Deallocator deAlloc):ComposedAny(new TypeCodeSeq("","",Runtime::_tc_double)),
799                                                                               _alloc(Runtime::_tc_double->getSizeInByteOfAnyReprInSeq())
800 {
801   _alloc.initCoarseMemory((char *)val,lgth,deAlloc);
802 }
803
804 SequenceAny::SequenceAny(const std::vector<int>& val):ComposedAny(new TypeCodeSeq("","",Runtime::_tc_int)),
805                                                       _alloc(Runtime::_tc_int->getSizeInByteOfAnyReprInSeq())
806 {
807   _alloc.initCoarseMemory((char *)&val[0],val.size(),0);
808 }
809
810 SequenceAny::SequenceAny(const std::vector<bool>& val):ComposedAny(new TypeCodeSeq("","",Runtime::_tc_bool)),
811                                                        _alloc(Runtime::_tc_bool->getSizeInByteOfAnyReprInSeq())
812 {
813   for(vector<bool>::const_iterator iter=val.begin();iter!=val.end();iter++)
814     {
815       AtomAnyPtr tmp=AtomAny::New(*iter);
816       pushBack(tmp);
817     }
818 }
819
820 SequenceAny::SequenceAny(const std::vector<double>& val):ComposedAny(new TypeCodeSeq("","",Runtime::_tc_double)),
821                                                          _alloc(Runtime::_tc_double->getSizeInByteOfAnyReprInSeq())
822 {
823   _alloc.initCoarseMemory((char *)&val[0],val.size(),0);
824 }
825
826 SequenceAny::SequenceAny(const std::vector<std::string>& val):ComposedAny(new TypeCodeSeq("","",Runtime::_tc_string)),
827                                                               _alloc(Runtime::_tc_string->getSizeInByteOfAnyReprInSeq())
828 {
829   for(vector<string>::const_iterator iter=val.begin();iter!=val.end();iter++)
830     {
831       AtomAnyPtr tmp=AtomAny::New(*iter);
832       pushBack(tmp);
833     }
834 }
835
836 void SequenceAny::realloc(char *endOfCurrentAllocated, const Any *elem)
837 {
838   unsigned int oldSize=_alloc._finish-_alloc._start;
839   unsigned int newSize = oldSize != 0 ? 2 * oldSize : _alloc._sizeOf1Elm;
840   char *newStart=_alloc.allocate(newSize);
841   //
842   char *newFinish=performCpy(_alloc._start, endOfCurrentAllocated,newStart);
843   _alloc.construct(newFinish, elem);
844   newFinish+=_alloc._sizeOf1Elm;
845   newFinish=performCpy(endOfCurrentAllocated, _alloc._finish, newFinish);
846   //
847   for (char *cur=_alloc._start;cur!=_alloc._finish;cur+=_alloc._sizeOf1Elm)
848     _alloc.destroy(cur,_type->contentType());
849   _alloc.deallocate(_alloc._start);
850   _alloc._start = newStart;
851   _alloc._finish = newFinish;
852   _alloc._endOfStorage=newStart+newSize;
853 }
854
855 char *SequenceAny::performCpy(char *srcStart, char *srcFinish, char *destStart)
856 {
857   char *cur=destStart;
858   for (;srcStart != srcFinish; srcStart+=_alloc._sizeOf1Elm, cur+=_alloc._sizeOf1Elm)
859     _alloc.construct(cur, srcStart, _type->contentType(),false);
860   return cur;
861 }
862
863 ArrayAny::~ArrayAny()
864 {
865   const TypeCode *subType=_type->contentType();
866   unsigned sizePerContent=subType->getSizeInByteOfAnyReprInSeq();
867   unsigned int size=((TypeCodeArray *)_type)->getStaticLgth();
868   char *tmp=_data;
869   for(unsigned i=0;i<size;i++,tmp+=sizePerContent)
870     subType->destroyZippedAny(tmp);
871   delete [] _data;
872 }
873
874 ArrayAny::ArrayAny(const TypeCode *typeOfContent, unsigned int lgth):ComposedAny(new TypeCodeArray("","",typeOfContent,lgth))
875 {
876   _data=new char[_type->getSizeInByteOfAnyReprInSeq()];
877   for(unsigned int i=0;i<_type->getSizeInByteOfAnyReprInSeq();i++)
878     _data[i]=SeqAlloc::DFT_CHAR_VAR;
879 }
880
881 ArrayAny::ArrayAny(char *data, TypeCodeArray * type):ComposedAny(type,false),_data(0)
882 {
883   _data=new char[_type->getSizeInByteOfAnyReprInSeq()];
884   const TypeCode *subType=_type->contentType();
885   unsigned sizePerContent=subType->getSizeInByteOfAnyReprInSeq();
886   for(unsigned i=0;i<type->getStaticLgth();i++)
887     subType->putReprAtPlace(_data+i*sizePerContent,data+i*sizePerContent,false);
888 }
889
890 ArrayAny::ArrayAny(const ArrayAny& other):ComposedAny(other)
891 {
892   _data=new char[_type->getSizeInByteOfAnyReprInSeq()];
893   const TypeCode *subType=_type->contentType();
894   unsigned sizePerContent=subType->getSizeInByteOfAnyReprInSeq();
895   for(unsigned i=0;i<((TypeCodeArray *)_type)->getStaticLgth();i++)
896     subType->putReprAtPlace(_data+i*sizePerContent,other._data+i*sizePerContent,true);
897 }
898
899 ArrayAny::ArrayAny(const int *val, unsigned int lgth):ComposedAny(new TypeCodeArray("","",Runtime::_tc_int,lgth)),
900                                                       _data(0)
901 {
902   _data=new char[_type->getSizeInByteOfAnyReprInSeq()];
903   memcpy(_data,val,_type->getSizeInByteOfAnyReprInSeq());
904 }
905
906 ArrayAny::ArrayAny(const bool *val, unsigned int lgth):ComposedAny(new TypeCodeArray("","",Runtime::_tc_bool,lgth)),
907                                                        _data(0)
908 {
909   _data=new char[_type->getSizeInByteOfAnyReprInSeq()];
910   memcpy(_data,val,_type->getSizeInByteOfAnyReprInSeq());
911 }
912
913 ArrayAny::ArrayAny(const double *val, unsigned int lgth):ComposedAny(new TypeCodeArray("","",Runtime::_tc_double,lgth)),
914                                                          _data(0)
915 {
916   _data=new char[_type->getSizeInByteOfAnyReprInSeq()];
917   memcpy(_data,val,_type->getSizeInByteOfAnyReprInSeq());
918 }
919
920 ArrayAny::ArrayAny(const std::vector<int>& val):ComposedAny(new TypeCodeArray("","",Runtime::_tc_int,val.size())),
921                                                 _data(0)
922 {
923   _data=new char[_type->getSizeInByteOfAnyReprInSeq()];
924   memcpy(_data,&val[0],_type->getSizeInByteOfAnyReprInSeq());
925 }
926
927 ArrayAny::ArrayAny(const std::vector<double>& val):ComposedAny(new TypeCodeArray("","",Runtime::_tc_double,val.size())),
928                                                 _data(0)
929 {
930   _data=new char[_type->getSizeInByteOfAnyReprInSeq()];
931   memcpy(_data,&val[0],_type->getSizeInByteOfAnyReprInSeq());
932 }
933
934 ArrayAny::ArrayAny(const std::vector<std::string>& val):ComposedAny(new TypeCodeArray("","",Runtime::_tc_string,val.size())),
935                                                         _data(0)
936 {
937   _data=new char[_type->getSizeInByteOfAnyReprInSeq()];
938   unsigned i=0;
939   const TypeCode *subType=_type->contentType();
940   unsigned sizePerContent=subType->getSizeInByteOfAnyReprInSeq();
941   for(vector<std::string>::const_iterator iter=val.begin();iter!=val.end();iter++,i++)
942     {
943       StringOnHeap *st=new StringOnHeap(*iter);
944       memcpy(_data+i*sizePerContent,&st,sizePerContent);
945     }
946 }
947
948 void ArrayAny::setEltAtRank(int i, const Any *elem) throw(YACS::Exception)
949 {
950   checkTypeOf(elem);
951   const TypeCode *subType=_type->contentType();
952   subType->destroyZippedAny(_data+i*subType->getSizeInByteOfAnyReprInSeq());
953   elem->putMyReprAtPlace(_data+i*subType->getSizeInByteOfAnyReprInSeq());
954 }
955
956 bool ArrayAny::operator ==(const Any& other) const
957 {
958   if(!_type->isA(other.getType()))
959     return false;
960   const ArrayAny& otherC=(const ArrayAny&) other;//cast granted due to previous lines
961   for(unsigned i=0;i<((const TypeCodeArray *)_type)->getStaticLgth();i++)
962     if(!((*(*this)[i])==(*otherC[i])))
963       return false;
964   return true;
965 }
966
967 AnyPtr ArrayAny::operator[](int i) const throw(YACS::Exception)
968 {
969   const TypeCode *subType=_type->contentType();
970   unsigned sizePerContent=subType->getSizeInByteOfAnyReprInSeq();
971   if(i<0 || i>=((TypeCodeArray *)_type)->getStaticLgth())
972     throw Exception("Trying to access to an invalid index in an Any Tuple");
973   return _type->contentType()->getOrBuildAnyFromZippedData(_data+i*sizePerContent);
974 }
975
976 unsigned int ArrayAny::size() const
977 {
978   return ((TypeCodeArray *)_type)->getStaticLgth();
979 }
980
981 Any *ArrayAny::clone() const
982 {
983   return new ArrayAny(*this);
984 }
985
986 ArrayAny *ArrayAny::New(const TypeCode *typeOfContent, unsigned int lgth)
987 {
988   return new ArrayAny(typeOfContent,lgth);
989 }
990
991 void ArrayAny::putMyReprAtPlace(char *data) const
992 {
993   const TypeCode *subType=_type->contentType();
994   unsigned sizePerContent=subType->getSizeInByteOfAnyReprInSeq();
995   for(unsigned i=0;i<((const TypeCodeArray *)_type)->getStaticLgth();i++)
996     subType->putReprAtPlace(data+i*sizePerContent,_data+i*sizePerContent,false);
997 }
998
999 void ArrayAny::putReprAtPlace(char *data, const char *src, const TypeCodeArray *type, bool deepCpy)
1000 {
1001   const TypeCode *subType=type->contentType();
1002   unsigned sizePerContent=subType->getSizeInByteOfAnyReprInSeq();
1003   for(unsigned i=0;i<type->getStaticLgth();i++)
1004     subType->putReprAtPlace(data+i*sizePerContent,src+i*sizePerContent,deepCpy);
1005 }
1006
1007 void ArrayAny::destroyReprAtPlace(char *data, const TypeCodeArray *type)
1008 {
1009   const TypeCode *subType=type->contentType();
1010   unsigned sizePerContent=subType->getSizeInByteOfAnyReprInSeq();
1011   for(unsigned i=0;i<type->getStaticLgth();i++)
1012     subType->destroyZippedAny(data+i*sizePerContent);
1013 }
1014
1015 AnyPtr ArrayAny::getOrBuildFromData(char *data, const TypeCodeArray *type)
1016 {
1017   Any *ret;
1018   ret=new ArrayAny(data,(TypeCodeArray *)type);
1019   return AnyPtr(ret);
1020 }
1021
1022 bool ArrayAny::takeInChargeStorageOf(TypeCode *type)
1023 {
1024   DynType typ=type->kind();
1025   return (typ==Array);
1026 }
1027
1028 Any *StructAny::clone() const
1029 {
1030   return new StructAny(*this);
1031 }
1032
1033 bool StructAny::operator ==(const Any& other) const
1034 {
1035   if(!_type->isA(other.getType()))
1036     return false;
1037   const TypeCodeStruct *typeC=(const TypeCodeStruct *)_type;
1038   vector< pair<string,TypeCode*> >::const_iterator iter;
1039   for(iter=typeC->_members.begin();iter!=typeC->_members.end();iter++)
1040     if(!((*(*this)[(*iter).first.c_str()]==(*other[(*iter).first.c_str()]))))
1041       return false;
1042   return true;
1043 }
1044
1045 AnyPtr StructAny::operator[](int i) const throw(YACS::Exception)
1046 {
1047   const char what[]="StructAny::operator[](int i) : Struct key are strings not integers.";
1048   throw Exception(what);
1049 }
1050
1051 AnyPtr StructAny::operator[](const char *key) const throw(YACS::Exception)
1052 {
1053   const TypeCodeStruct *typeC=(const TypeCodeStruct *)_type;
1054   char *whereToGet=_data;
1055   vector< pair<string,TypeCode*> >::const_iterator iter;
1056   for(iter=typeC->_members.begin();iter!=typeC->_members.end();iter++)
1057     if((*iter).first!=key)
1058       whereToGet+=(*iter).second->getSizeInByteOfAnyReprInSeq();
1059     else
1060       break;
1061   if(iter==typeC->_members.end())
1062     {
1063       string what("Unexisting key \""); what+=key; what+="\" for struct extraction.";
1064       throw Exception(what);
1065     }
1066   return (*iter).second->getOrBuildAnyFromZippedData(whereToGet);
1067 }
1068
1069 void StructAny::setEltAtRank(int i, const Any *elem) throw(YACS::Exception)
1070 {
1071   const char what[]="Struct key are strings not integers.";
1072   throw Exception(what);
1073 }
1074
1075 void StructAny::setEltAtRank(const char *key, const Any *elem) throw(YACS::Exception)
1076 {
1077   const TypeCodeStruct *typeC=(const TypeCodeStruct *)_type;
1078   unsigned offset;
1079   const TypeCode *tcOnKey=typeC->getMember(key,offset);
1080   if(!tcOnKey)
1081     throw Exception("StructAny::setEltAtRank : invalid key given.");
1082   if(!elem->getType()->isA(tcOnKey))
1083     throw Exception("StructAny::setEltAtRank : invalid data type on the specified given key.");
1084   tcOnKey->destroyZippedAny(_data+offset);
1085   elem->putMyReprAtPlace(_data+offset);
1086 }
1087
1088 void StructAny::putMyReprAtPlace(char *data) const
1089 {
1090   const TypeCodeStruct *typeC=(const TypeCodeStruct *)_type;
1091   unsigned offset=0;
1092   vector< pair<string,TypeCode*> >::const_iterator iter;
1093   for(iter=typeC->_members.begin();iter!=typeC->_members.end();iter++)
1094     {
1095       (*iter).second->putReprAtPlace(data+offset,_data+offset,false);
1096       offset+=(*iter).second->getSizeInByteOfAnyReprInSeq();
1097     }
1098 }
1099
1100 void StructAny::putReprAtPlace(char *data, const char *src, const TypeCodeStruct *type, bool deepCpy)
1101 {
1102   unsigned offset=0;
1103   vector< pair<string,TypeCode*> >::const_iterator iter;
1104   for(iter=type->_members.begin();iter!=type->_members.end();iter++)
1105     {
1106       (*iter).second->putReprAtPlace(data+offset,src+offset,deepCpy);
1107       offset+=(*iter).second->getSizeInByteOfAnyReprInSeq();
1108     }
1109 }
1110
1111 void StructAny::destroyReprAtPlace(char *data, const TypeCodeStruct *type)
1112 {
1113   char *whereToGet=data;
1114   vector< pair<string,TypeCode*> >::const_iterator iter;
1115   for(iter=type->_members.begin();iter!=type->_members.end();iter++)
1116     {
1117       (*iter).second->destroyZippedAny(whereToGet);
1118       whereToGet+=(*iter).second->getSizeInByteOfAnyReprInSeq();
1119     }
1120 }
1121
1122 AnyPtr StructAny::getOrBuildFromData(char *data, const TypeCodeStruct *type)
1123 {
1124   Any *ret;
1125   ret=new StructAny(data,(TypeCodeStruct *)type);
1126   return AnyPtr(ret);
1127 }
1128
1129 StructAny::~StructAny()
1130 {
1131   const TypeCodeStruct *typeC=(const TypeCodeStruct *)_type;
1132   vector< pair<string,TypeCode*> >::const_iterator iter;
1133   char *whereToGet=_data;
1134   for(iter=typeC->_members.begin();iter!=typeC->_members.end();iter++)
1135     {
1136       (*iter).second->destroyZippedAny(whereToGet);
1137       whereToGet+=(*iter).second->getSizeInByteOfAnyReprInSeq();
1138     }
1139   delete [] _data;
1140 }
1141
1142 StructAny::StructAny(TypeCodeStruct *type):ComposedAny(type,false)
1143 {
1144   _data=new char[_type->getSizeInByteOfAnyReprInSeq()];
1145   for(unsigned int i=0;i<_type->getSizeInByteOfAnyReprInSeq();i++)
1146     _data[i]=SeqAlloc::DFT_CHAR_VAR;
1147 }
1148
1149 StructAny::StructAny(const StructAny& other):ComposedAny(other)
1150 {
1151   _data=new char[_type->getSizeInByteOfAnyReprInSeq()];
1152   const TypeCodeStruct *typeC=(const TypeCodeStruct *)_type;
1153   vector< pair<string,TypeCode*> >::const_iterator iter;
1154   unsigned offset=0;
1155   for(iter=typeC->_members.begin();iter!=typeC->_members.end();iter++)
1156     {
1157      (*iter).second->putReprAtPlace(_data+offset,other._data+offset,true);
1158      offset+=(*iter).second->getSizeInByteOfAnyReprInSeq();
1159     }
1160 }
1161
1162 StructAny::StructAny(char *data, TypeCodeStruct * type):ComposedAny(type,false),_data(0)
1163 {
1164   _data=new char[_type->getSizeInByteOfAnyReprInSeq()];
1165   vector< pair<string,TypeCode*> >::const_iterator iter;
1166   unsigned offset=0;
1167   for(iter=type->_members.begin();iter!=type->_members.end();iter++)
1168     {
1169       (*iter).second->putReprAtPlace(_data+offset,data+offset,false);
1170       offset+=(*iter).second->getSizeInByteOfAnyReprInSeq();
1171     }
1172 }
1173
1174 StructAny *StructAny::New(TypeCodeStruct *type)
1175 {
1176   return new StructAny(type);
1177 }