]> SALOME platform Git repositories - modules/yacs.git/blob - src/engine/TypeCode.cxx
Salome HOME
merge from branch DEV tag mergeto_trunk_04apr08
[modules/yacs.git] / src / engine / TypeCode.cxx
1
2 #include "TypeCode.hxx"
3 #include <sstream>
4 #include <iostream>
5
6 //#define _DEVDEBUG_
7 #include "YacsTrace.hxx"
8
9 using namespace YACS::ENGINE;
10 using namespace std;
11
12 const char *TypeCode::KIND_STR_REPR []={ "None", "Double", "Int", "String", "Bool", "Objref", "Sequence", "Array","Struct" };
13
14 // --- TypeCode
15
16 TypeCode::TypeCode(DynType kind):_kind(kind)
17 {
18 }
19
20 TypeCode::TypeCode(const TypeCode& tc):_kind(tc._kind)
21 {
22 }
23
24 TypeCode::~TypeCode()
25 {
26 }
27
28 DynType TypeCode::kind() const
29 {
30   return _kind;
31 }
32
33 TypeCode *TypeCode::clone() const
34 {
35   return new TypeCode(*this);
36 }
37
38 void TypeCode::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
39 {
40   AtomAny::putReprAtPlace(pt,val,this,deepCpy);
41 }
42
43 void TypeCode::destroyZippedAny(char *data) const
44 {
45   AtomAny::destroyReprAtPlace(data,this);
46 }
47
48 AnyPtr TypeCode::getOrBuildAnyFromZippedData(char *data) const
49 {
50   return AtomAny::getOrBuildFromData(data,this);
51 }
52
53 const char * TypeCode::name() const throw(Exception)
54 {
55   //throw Exception("No name");
56   return id();
57 }
58
59 const char * TypeCode::shortName() const
60 {
61   //throw Exception("No shortName");
62   return id();
63 }
64
65 const char * TypeCode::id() const throw(Exception)
66 {
67   switch(_kind)
68     {
69     case Double:
70       return "Double";
71     case Int:
72       return "Int";
73     case String:
74       return "String";
75     case Bool:
76       return "Bool";
77     default:
78       return "";
79     }
80 }
81
82 int TypeCode::isA(const char* id) const throw(Exception)
83 {
84   throw Exception("Not implemented for this type");
85 }
86
87 int TypeCode::isA(const TypeCode* tc) const 
88 {
89   if(_kind == tc->kind()) return 1;
90   return 0;
91 }
92
93 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
94 /*!
95  * this TypeCode is adaptable to tc if tc type can be converted to this type
96  *
97  *   \param tc : the TypeCode that must be convertible to this
98  */
99 int TypeCode::isAdaptable(const TypeCode* tc) const
100 {
101   switch(_kind)
102     {
103     case Double:
104       if (tc->kind() == Double) return 1;
105       if (tc->kind() == Int) return 1;
106       return 0;
107     case Int:
108       if (tc->kind() == Int) return 1;
109       return 0;
110     case String:
111       if (tc->kind() == String) return 1;
112       return 0;
113     case Bool:
114       if (tc->kind() == Bool) return 1;
115       if (tc->kind() == Int) return 1;
116       return 0;
117     default:
118       //objref, sequence, ...
119       return 0;
120     }
121 }
122
123 //! Check if this TypeCode can be used in place of tc
124 /*!
125  * this TypeCode is equivalent to tc if they have the same kind
126  *
127  *   \param tc : the TypeCode to compare
128  */
129 int TypeCode::isEquivalent(const TypeCode* tc) const 
130 {
131   if(_kind == tc->kind()) return 1;
132   return 0;
133 }
134
135 unsigned TypeCode::getSizeInByteOfAnyReprInSeq() const
136 {
137   switch(_kind)
138     {
139     case Double:
140       return sizeof(double);
141     case Int:
142       return sizeof(int);
143     case String:
144       return sizeof(StringOnHeap *);
145     case Bool:
146       return sizeof(bool);
147     default:
148       return sizeof(void *);
149     }
150 }
151
152 const TypeCode * TypeCode::contentType() const throw(Exception)
153 {
154   throw Exception("No content type");
155 };
156
157 static inline int validChar0(char c)
158 {
159   return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
160 }
161
162 static inline int validNextChar(char c)
163 {
164   return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
165           (c >= '0' && c <= '9') || (c == '_') || (c == '/'));
166 }
167
168 static void checkValidName(const char* name)
169 {
170   int ok = 1;
171   if (*name) 
172     {
173       if (!validChar0(*name++)) ok = 0;
174       for(; ok && *name; name++) if (!validNextChar(*name)) ok = 0; 
175     }
176   if (!ok)throw YACS::Exception("Invalid Name");
177 }
178
179 const char *TypeCode::getKindRepr(DynType kind)
180 {
181   return KIND_STR_REPR[(int)kind];
182 }
183
184 const char * TypeCode::getKindRepr() const
185 {
186   return KIND_STR_REPR[(int)_kind];
187 }
188
189 //! static factory of object reference type given an id and a name
190 TypeCode * TypeCode::interfaceTc(const char* id,
191                                   const char* name)
192 {
193   checkValidName(name);
194   return new TypeCodeObjref(id, name);
195 };
196
197 //! static factory of object reference type given an id, a name and a list of base types
198 /*!
199  *   \param id :  the id
200  *   \param name :  the name
201  *   \param ltc :  the list of base types
202  *
203  *   The name must be a valid one (throw Exception is not)
204  */
205 TypeCode * TypeCode::interfaceTc(const char* id,
206                                   const char* name,
207                                   const std::list<TypeCodeObjref *>& ltc)
208 {
209   checkValidName(name);
210   return new TypeCodeObjref(id, name,ltc);
211 }
212
213
214 //! static factory of sequence type given an id, a name and a content type
215 TypeCode * TypeCode::sequenceTc(const char* id,
216                                  const char* name,
217                                  TypeCode *content)
218 {
219   return new TypeCodeSeq(id, name,content);
220 };
221 //! static factory of struct type given an id and a name 
222 TypeCode * TypeCode::structTc(const char* id,
223                                  const char* name)
224 {
225   return new TypeCodeStruct(id, name);
226 };
227
228 TypeCodeComposed::TypeCodeComposed(const TypeCodeComposed& other):TypeCode(other),
229                                                                   _name(other._name),_repoId(other._repoId),
230                                                                   _shortName(other._shortName)
231 {
232 }
233
234 TypeCodeComposed::TypeCodeComposed(DynType kind, const char* repositoryId, const char* name):TypeCode(kind),
235                                                                                              _repoId(repositoryId),_name(name)
236 {
237   string::size_type debut =_name.find_last_of('/');
238   if(debut == std::string::npos)
239     _shortName= name;
240   else
241     _shortName=_name.substr(debut+1);
242 }
243
244 // --- TypeCodeObjref
245
246
247 TypeCodeObjref::TypeCodeObjref(const char* repositoryId, 
248                                const char* name) : TypeCodeComposed(Objref,repositoryId,name)
249 {
250 }
251
252
253 TypeCodeObjref::~TypeCodeObjref()
254 {
255   list<TypeCodeObjref *>::iterator iter;
256   for(iter=_listOfBases.begin();iter != _listOfBases.end(); iter++)
257     (*iter)->decrRef();
258 }
259
260 TypeCode *TypeCodeObjref::clone() const
261 {
262   return new TypeCodeObjref(*this);
263 }
264
265 void TypeCodeObjref::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
266 {
267   throw Exception("Not implemented yet : YACS::Any for objs ref");
268 }
269
270 void TypeCodeObjref::destroyZippedAny(char *data) const
271 {
272   throw Exception("Not implemented yet : YACS::Any for objs ref");
273 }
274
275 AnyPtr TypeCodeObjref::getOrBuildAnyFromZippedData(char *data) const
276 {
277   throw Exception("Not implemented yet : YACS::Any for objs ref");
278 }
279
280 const char * TypeCodeObjref::id() const throw(Exception)
281 {
282   return _repoId.c_str();
283 };
284
285 const char * TypeCodeObjref::name() const throw(Exception)
286 {
287   return _name.c_str();
288 }
289
290 const char * TypeCodeObjref::shortName() const
291 {
292   return _shortName.c_str();
293 }
294
295 TypeCodeObjref::TypeCodeObjref(const char* repositoryId,
296                                const char* name,
297                                const std::list<TypeCodeObjref *>& ltc) : TypeCodeComposed(Objref,repositoryId,name)
298 {
299   _listOfBases=ltc;
300   list<TypeCodeObjref *>::const_iterator iter;
301   for(iter=_listOfBases.begin();iter != _listOfBases.end(); iter++)
302     (*iter)->incrRef();
303 }
304
305 //! Check if this TypeCode is derived from a TypeCode with a given id
306 /*!
307  *   \param id :  a given id
308  *   \return     1 if true, 0 if false
309  */
310 int TypeCodeObjref::isA(const char* id) const throw(Exception)
311 {
312   if(_repoId == id)return 1;
313   list<TypeCodeObjref *>::const_iterator iter;
314   for(iter=_listOfBases.begin();iter != _listOfBases.end(); iter++)
315     {
316       if ((*iter)->isA(id)) return 1;
317     }
318   return 0;
319 }
320
321 //! Check if this TypeCode is derived from a given TypeCode
322 /*!
323  *   \param tc : the given TypeCode
324  *   \return    1 if true, 0 if false
325  */
326 int TypeCodeObjref::isA(const TypeCode* tc) const
327 {
328   return isA(tc->id());
329 }
330
331 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
332 /*!
333  *   \param tc : the given TypeCode
334  *   \return    1 if true, 0 if false
335  */
336 int TypeCodeObjref::isAdaptable(const TypeCode* tc) const
337 {
338   if(_kind == tc->kind()) return isA(tc->id());
339   return 0;
340 }
341
342 //! Check if this TypeCode can be used in place of tc
343 /*!
344  * this TypeCode is equivalent to tc if they have the same kind
345  *
346  *   \param tc : the TypeCode to compare
347  */
348 int TypeCodeObjref::isEquivalent(const TypeCode* tc) const 
349 {
350   if(_kind != tc->kind())return 0;
351   if(_repoId == tc->id())return 1;
352   return 0;
353 }
354
355 TypeCodeObjref::TypeCodeObjref(const TypeCodeObjref& other):TypeCodeComposed(other),
356                                                             _listOfBases(other._listOfBases)
357 {
358   list<TypeCodeObjref *>::const_iterator iter;
359   for(iter=other._listOfBases.begin();iter!=other._listOfBases.end();iter++)
360     (*iter)->incrRef();
361 }
362
363 // --- TypeCodeSeq
364
365
366 //! Create a sequence type with a given name, a given id and a given contained type.
367 /*!
368  *   \param repositoryId : the given id
369  *   \param name : the given name
370  *   \param content : the given contained TypeCode
371  */
372 TypeCodeSeq::TypeCodeSeq(const char* repositoryId,
373                          const char* name, 
374                          const TypeCode *content) : TypeCodeComposed(Sequence,repositoryId,name), _content(content)
375 {
376   _content->incrRef();
377 }
378
379 TypeCodeSeq::~TypeCodeSeq()
380 {
381   ((TypeCode *)_content)->decrRef();
382 }
383
384 TypeCode *TypeCodeSeq::clone() const
385 {
386   return new TypeCodeSeq(*this);
387 }
388
389 void TypeCodeSeq::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
390 {
391   SequenceAny::putReprAtPlace(pt,val,this,deepCpy);
392 }
393
394 void TypeCodeSeq::destroyZippedAny(char *data) const
395 {
396   SequenceAny::destroyReprAtPlace(data,this);
397 }
398
399 unsigned TypeCodeSeq::getSizeInByteOfAnyReprInSeq() const
400 {
401   return sizeof(void*);
402 }
403
404 AnyPtr TypeCodeSeq::getOrBuildAnyFromZippedData(char *data) const
405 {
406   return SequenceAny::getOrBuildFromData(data,this);
407 }
408
409 const char * TypeCodeSeq::id() const throw(Exception)
410 {
411   return _repoId.c_str();
412 }
413
414 const char * TypeCodeSeq::name() const throw(Exception)
415 {
416   return _name.c_str();
417 }
418 const char * TypeCodeSeq::shortName() const
419 {
420   return _shortName.c_str();
421 }
422
423 const TypeCode * TypeCodeSeq::contentType() const throw(Exception)
424 {
425   return _content;
426 }
427
428 int TypeCodeSeq::isA(const TypeCode* tc) const
429 {
430   if(_kind == tc->kind())
431     return _content->isA(tc->contentType());
432   return 0;
433 }
434
435 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
436 /*!
437  *   \param tc : the given TypeCode
438  *   \return    1 if true, 0 if false
439  */
440 int TypeCodeSeq::isAdaptable(const TypeCode* tc) const
441 {
442   if(_kind == tc->kind())
443     return contentType()->isAdaptable(tc->contentType());
444   return 0;
445 }
446
447 //! Check if this TypeCode can be used in place of tc
448 /*!
449  * this TypeCode is equivalent to tc if they have the same kind
450  *
451  *   \param tc : the TypeCode to compare
452  */
453 int TypeCodeSeq::isEquivalent(const TypeCode* tc) const 
454 {
455   if(_kind == tc->kind())
456     return _content->isEquivalent(tc->contentType());
457   return 0;
458 }
459
460 TypeCodeSeq::TypeCodeSeq(const TypeCodeSeq& tc):TypeCodeComposed(tc),
461                                                 _content(tc._content)
462 {
463   _content->incrRef();
464 }
465
466 // --- TypeCodeArray
467
468
469 //! Create an Array type with a given name, a given id and a given contained type.
470 /*!
471  *   \param repositoryId : the given id
472  *   \param name : the given name
473  *   \param content : the given contained TypeCode
474  */
475 TypeCodeArray::TypeCodeArray(const char* repositoryId,
476                              const char* name, 
477                              const TypeCode *content,
478                              unsigned staticLgth) : TypeCodeComposed(Array,repositoryId,name), _content(content),_staticLgth(staticLgth)
479 {
480   _content->incrRef();
481 }
482
483 TypeCodeArray::~TypeCodeArray()
484 {
485   ((TypeCode *)_content)->decrRef();
486 }
487
488 TypeCode *TypeCodeArray::clone() const
489 {
490   return new TypeCodeArray(*this);
491 }
492
493 void TypeCodeArray::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
494 {
495   ArrayAny::putReprAtPlace(pt,val,this,deepCpy);
496 }
497
498 void TypeCodeArray::destroyZippedAny(char *data) const
499 {
500   ArrayAny::destroyReprAtPlace(data,this);
501 }
502
503 AnyPtr TypeCodeArray::getOrBuildAnyFromZippedData(char *data) const
504 {
505   return ArrayAny::getOrBuildFromData(data,this);
506 }
507
508 const char * TypeCodeArray::id() const throw(Exception)
509 {
510   return _repoId.c_str();
511 }
512
513 const char * TypeCodeArray::name() const throw(Exception)
514 {
515   return _name.c_str();
516 }
517 const char * TypeCodeArray::shortName() const
518 {
519   return _shortName.c_str();
520 }
521
522 unsigned TypeCodeArray::getStaticLgth() const
523 {
524   return _staticLgth;
525 }
526
527 const TypeCode * TypeCodeArray::contentType() const throw(Exception)
528 {
529   return _content;
530 }
531
532 int TypeCodeArray::isA(const TypeCode* tc) const
533 {
534   if(_kind == tc->kind())
535     if(_content->isA(tc->contentType()))
536       {
537         const TypeCodeArray *tcC=dynamic_cast<const TypeCodeArray *>(tc);
538         if(tcC)
539           return tcC->getStaticLgth()==_staticLgth;
540         return 0;
541       }
542   return 0;
543 }
544
545 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
546 /*!
547  *   \param tc : the given TypeCode
548  *   \return    1 if true, 0 if false
549  */
550 int TypeCodeArray::isAdaptable(const TypeCode* tc) const
551 {
552   if(_kind == tc->kind())
553     return contentType()->isAdaptable(tc->contentType());
554   return 0;
555 }
556
557 //! Check if this TypeCode can be used in place of tc
558 /*!
559  * this TypeCode is equivalent to tc if they have the same kind
560  *
561  *   \param tc : the TypeCode to compare
562  */
563 int TypeCodeArray::isEquivalent(const TypeCode* tc) const 
564 {
565   if(_kind == tc->kind())
566     return _content->isEquivalent(tc->contentType());
567   return 0;
568 }
569
570 TypeCodeArray::TypeCodeArray(const TypeCodeArray& tc):TypeCodeComposed(tc),
571                                                       _content(tc._content),
572                                                       _staticLgth(tc._staticLgth)
573 {
574   _content->incrRef();
575 }
576
577 unsigned TypeCodeArray::getSizeInByteOfAnyReprInSeq() const
578 {
579   return _staticLgth*_content->getSizeInByteOfAnyReprInSeq();
580 }
581
582 // --- TypeCodeStruct
583
584
585 //! Create a struct type with a given name and a given id 
586 /*!
587  *   \param repositoryId : the given id
588  *   \param name : the given name
589  */
590 TypeCodeStruct::TypeCodeStruct(const char* repositoryId, 
591                                const char* name) : TypeCodeComposed(Struct,repositoryId,name)
592 {
593 }
594
595 TypeCodeStruct::~TypeCodeStruct()
596 {
597 }
598
599 TypeCode *TypeCodeStruct::clone() const
600 {
601   return new TypeCodeStruct(*this);
602 }
603
604 TypeCodeStruct::TypeCodeStruct(const TypeCodeStruct& tc):TypeCodeComposed(tc),_members(tc._members)
605 {
606   for(vector< std::pair<std::string,TypeCode*> >::iterator iter=_members.begin();iter!=_members.end();iter++)
607     (*iter).second->incrRef();
608 }
609
610 void TypeCodeStruct::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
611 {
612   StructAny::putReprAtPlace(pt,val,this,deepCpy);
613 }
614
615 void TypeCodeStruct::destroyZippedAny(char *data) const
616 {
617   StructAny::destroyReprAtPlace(data,this);
618 }
619
620 AnyPtr TypeCodeStruct::getOrBuildAnyFromZippedData(char *data) const
621 {
622   return StructAny::getOrBuildFromData(data,this);
623 }
624
625 const char * TypeCodeStruct::id() const throw(Exception)
626 {
627   return _repoId.c_str();
628 };
629
630 const char * TypeCodeStruct::name() const throw(Exception)
631 {
632   return _name.c_str();
633 }
634
635 const char * TypeCodeStruct::shortName() const
636 {
637   return _shortName.c_str();
638 }
639
640 unsigned TypeCodeStruct::getSizeInByteOfAnyReprInSeq() const
641 {
642   unsigned ret=0;
643   for(vector< pair<string,TypeCode*> >::const_iterator iter=_members.begin();iter!=_members.end();iter++)
644     ret+=(*iter).second->getSizeInByteOfAnyReprInSeq();
645   return ret;
646 }
647
648 const TypeCode *TypeCodeStruct::contentType() const throw(Exception)
649 {
650   const char what[]="Content type is specified by giving a key.";
651   throw Exception(what);
652 }
653
654 //! Check if this TypeCode is derived from a TypeCode with a given id
655 /*!
656  *   \param id :  a given id
657  *   \return     1 if true, 0 if false
658  */
659 int TypeCodeStruct::isA(const char* id) const throw(Exception)
660 {
661   if(_repoId == id)return 1;
662   return 0;
663 }
664
665 //! Check if this TypeCode is derived from a given TypeCode
666 /*!
667  *   \param tc : the given TypeCode
668  *   \return    1 if true, 0 if false
669  */
670 int TypeCodeStruct::isA(const TypeCode* tc) const 
671 {
672   if(_kind != tc->kind()) return 0;
673   if(_repoId == tc->id())return 1;
674   int nMember=memberCount();
675   if(nMember != ((TypeCodeStruct*)tc)->memberCount())return 0;
676   for(int i=0;i<nMember;i++)
677     {
678        const char * name=memberName(i);
679        if(strcmp(memberName(i),((TypeCodeStruct*)tc)->memberName(i)) != 0)return 0;
680        if(!memberType(i)->isA(((TypeCodeStruct*)tc)->memberType(i)))return 0;
681     }
682   return 1;
683 }
684
685 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
686 /*!
687  *   \param tc : the given TypeCode
688  *   \return    1 if true, 0 if false
689  */
690 int TypeCodeStruct::isAdaptable(const TypeCode* tc) const
691 {
692   if(_kind == tc->kind()) return isA(tc->id());
693   return 0;
694 }
695
696 //! Check if this TypeCode can be used in place of tc
697 /*!
698  * this TypeCode is equivalent to tc if they have the same kind
699  *
700  *   \param tc : the TypeCode to compare
701  */
702 int TypeCodeStruct::isEquivalent(const TypeCode* tc) const 
703 {
704   if(_kind != tc->kind()) return 0;
705   int nMember=memberCount();
706   if(nMember != ((TypeCodeStruct*)tc)->memberCount())return 0;
707   for(int i=0;i<nMember;i++)
708     {
709        const char * name=memberName(i);
710        if(strcmp(memberName(i),((TypeCodeStruct*)tc)->memberName(i)) != 0)return 0;
711        if(!memberType(i)->isEquivalent(((TypeCodeStruct*)tc)->memberType(i)))return 0;
712     }
713   return 1;
714 }
715
716 void TypeCodeStruct::addMember(const std::string& name,TypeCode* tc)
717 {
718   DEBTRACE(name << " " << tc->name());
719   std::vector< std::pair<std::string,TypeCode*> >::const_iterator iter;
720   for(iter=_members.begin();iter != _members.end(); iter++)
721     {
722       if((*iter).first == name)
723         throw Exception("Struct member " + name + " already defined");
724     }
725   _members.push_back(std::pair<std::string,TypeCode*>(name,tc));
726 }
727
728 /*!
729  * If name is not an existing key, 0 is returned.
730  * \param offset : Out parameter, that specified the location of start of data discriminated by name key.
731  */
732 const TypeCode *TypeCodeStruct::getMember(const std::string& name, unsigned& offset) const
733 {
734   std::vector< std::pair<std::string,TypeCode*> >::const_iterator iter;
735   offset=0;
736   for(iter=_members.begin();iter != _members.end(); iter++)
737     {
738       if((*iter).first==name)
739         return (*iter).second;
740       offset+=(*iter).second->getSizeInByteOfAnyReprInSeq();
741     }
742   return 0;
743 }
744
745 int TypeCodeStruct::memberCount() const
746 {
747   return _members.size();
748 }
749
750 const char*  TypeCodeStruct::memberName(int index) const
751 {
752   if(index > _members.size())
753     {
754       stringstream msg;
755       msg << "Struct size less than " << index;
756       msg << " : " << __FILE__ << ":" << __LINE__;
757       throw Exception(msg.str());
758     }
759   return _members[index].first.c_str();
760 }
761
762 TypeCode*  TypeCodeStruct::memberType(int index) const
763 {
764   if(index > _members.size())
765     {
766       stringstream msg;
767       msg << "Struct size less than " << index;
768       msg << " : " << __FILE__ << ":" << __LINE__;
769       throw Exception(msg.str());
770     }
771   return _members[index].second;
772 }
773
774