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