Salome HOME
9aeb6ba7290793fb44433137d4cc4b72df536690
[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 unsigned TypeCode::getSizeInByteOfAnyReprInSeq() const
124 {
125   switch(_kind)
126     {
127     case Double:
128       return sizeof(double);
129     case Int:
130       return sizeof(int);
131     case String:
132       return sizeof(StringOnHeap *);
133     case Bool:
134       return sizeof(bool);
135     default:
136       return sizeof(void *);
137     }
138 }
139
140 const TypeCode * TypeCode::contentType() const throw(Exception)
141 {
142   throw Exception("No content type");
143 };
144
145 static inline int validChar0(char c)
146 {
147   return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
148 }
149
150 static inline int validNextChar(char c)
151 {
152   return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
153           (c >= '0' && c <= '9') || (c == '_') || (c == '/'));
154 }
155
156 static void checkValidName(const char* name)
157 {
158   int ok = 1;
159   if (*name) 
160     {
161       if (!validChar0(*name++)) ok = 0;
162       for(; ok && *name; name++) if (!validNextChar(*name)) ok = 0; 
163     }
164   if (!ok)throw YACS::Exception("Invalid Name");
165 }
166
167 const char *TypeCode::getKindRepr(DynType kind)
168 {
169   return KIND_STR_REPR[(int)kind];
170 }
171
172 const char * TypeCode::getKindRepr() const
173 {
174   return KIND_STR_REPR[(int)_kind];
175 }
176
177 //! static factory of object reference type given an id and a name
178 TypeCode * TypeCode::interfaceTc(const char* id,
179                                   const char* name)
180 {
181   checkValidName(name);
182   return new TypeCodeObjref(id, name);
183 };
184
185 //! static factory of object reference type given an id, a name and a list of base types
186 /*!
187  *   \param id :  the id
188  *   \param name :  the name
189  *   \param ltc :  the list of base types
190  *
191  *   The name must be a valid one (throw Exception is not)
192  */
193 TypeCode * TypeCode::interfaceTc(const char* id,
194                                   const char* name,
195                                   const std::list<TypeCodeObjref *>& ltc)
196 {
197   checkValidName(name);
198   return new TypeCodeObjref(id, name,ltc);
199 }
200
201
202 //! static factory of sequence type given an id, a name and a content type
203 TypeCode * TypeCode::sequenceTc(const char* id,
204                                  const char* name,
205                                  TypeCode *content)
206 {
207   return new TypeCodeSeq(id, name,content);
208 };
209 //! static factory of struct type given an id and a name 
210 TypeCode * TypeCode::structTc(const char* id,
211                                  const char* name)
212 {
213   return new TypeCodeStruct(id, name);
214 };
215
216
217 // --- TypeCodeObjref
218
219
220 TypeCodeObjref::TypeCodeObjref(const char* repositoryId, 
221                                  const char* name) : TypeCode(Objref)
222 {
223   _repoId = repositoryId;
224   _name = name;
225   string::size_type debut =_name.find_last_of('/');
226   if(debut == std::string::npos)_shortName= name;
227   else _shortName=_name.substr(debut+1);
228 }
229
230
231 TypeCodeObjref::~TypeCodeObjref()
232 {
233   list<TypeCodeObjref *>::iterator iter;
234   for(iter=_listOfBases.begin();iter != _listOfBases.end(); iter++)
235     (*iter)->decrRef();
236 }
237
238 TypeCode *TypeCodeObjref::clone() const
239 {
240   return new TypeCodeObjref(*this);
241 }
242
243 void TypeCodeObjref::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
244 {
245   throw Exception("Not implemented yet : YACS::Any for objs ref");
246 }
247
248 void TypeCodeObjref::destroyZippedAny(char *data) const
249 {
250   throw Exception("Not implemented yet : YACS::Any for objs ref");
251 }
252
253 AnyPtr TypeCodeObjref::getOrBuildAnyFromZippedData(char *data) const
254 {
255   throw Exception("Not implemented yet : YACS::Any for objs ref");
256 }
257
258 const char * TypeCodeObjref::id() const throw(Exception)
259 {
260   return _repoId.c_str();
261 };
262
263 const char * TypeCodeObjref::name() const throw(Exception)
264 {
265   return _name.c_str();
266 }
267
268 const char * TypeCodeObjref::shortName() const
269 {
270   return _shortName.c_str();
271 }
272
273 TypeCodeObjref::TypeCodeObjref(const char* repositoryId,
274                                  const char* name,
275                                  const std::list<TypeCodeObjref *>& ltc) : TypeCode(Objref)
276 {
277   _repoId = repositoryId;
278   _name = name;
279   string::size_type debut =_name.find_last_of('/');
280   if(debut == std::string::npos)_shortName= name;
281   else _shortName=_name.substr(debut+1);
282   _listOfBases=ltc;
283   list<TypeCodeObjref *>::const_iterator iter;
284   for(iter=_listOfBases.begin();iter != _listOfBases.end(); iter++)
285     (*iter)->incrRef();
286 }
287
288 //! Check if this TypeCode is derived from a TypeCode with a given id
289 /*!
290  *   \param id :  a given id
291  *   \return     1 if true, 0 if false
292  */
293 int TypeCodeObjref::isA(const char* id) const throw(Exception)
294 {
295   if(_repoId == id)return 1;
296   list<TypeCodeObjref *>::const_iterator iter;
297   for(iter=_listOfBases.begin();iter != _listOfBases.end(); iter++)
298     {
299       if ((*iter)->isA(id)) return 1;
300     }
301   return 0;
302 }
303
304 //! Check if this TypeCode is derived from a given TypeCode
305 /*!
306  *   \param tc : the given TypeCode
307  *   \return    1 if true, 0 if false
308  */
309 int TypeCodeObjref::isA(const TypeCode* tc) const
310 {
311   return isA(tc->id());
312 }
313
314 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
315 /*!
316  *   \param tc : the given TypeCode
317  *   \return    1 if true, 0 if false
318  */
319 int TypeCodeObjref::isAdaptable(const TypeCode* tc) const
320 {
321   if(_kind == tc->kind()) return isA(tc->id());
322   return 0;
323 }
324
325 TypeCodeObjref::TypeCodeObjref(const TypeCodeObjref& other):TypeCode(other),_name(other._name),
326                                                                _repoId(other._shortName),
327                                                                _listOfBases(other._listOfBases)
328 {
329   list<TypeCodeObjref *>::const_iterator iter;
330   for(iter=other._listOfBases.begin();iter!=other._listOfBases.end();iter++)
331     (*iter)->incrRef();
332 }
333
334 // --- TypeCodeSeq
335
336
337 //! Create a sequence type with a given name, a given id and a given contained type.
338 /*!
339  *   \param repositoryId : the given id
340  *   \param name : the given name
341  *   \param content : the given contained TypeCode
342  */
343 TypeCodeSeq::TypeCodeSeq(const char* repositoryId,
344                            const char* name, 
345                            const TypeCode *content) : TypeCode(Sequence), _content(content)
346 {
347   _repoId = repositoryId;
348   _name = name;
349   string::size_type debut =_name.find_last_of('/');
350   if(debut == std::string::npos)_shortName= name;
351   else _shortName=_name.substr(debut+1);
352   _content->incrRef();
353 }
354
355 TypeCodeSeq::~TypeCodeSeq()
356 {
357   ((TypeCode *)_content)->decrRef();
358 }
359
360 TypeCode *TypeCodeSeq::clone() const
361 {
362   return new TypeCodeSeq(*this);
363 }
364
365 void TypeCodeSeq::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
366 {
367   SequenceAny::putReprAtPlace(pt,val,this,deepCpy);
368 }
369
370 void TypeCodeSeq::destroyZippedAny(char *data) const
371 {
372   SequenceAny::destroyReprAtPlace(data,this);
373 }
374
375 AnyPtr TypeCodeSeq::getOrBuildAnyFromZippedData(char *data) const
376 {
377   return SequenceAny::getOrBuildFromData(data,this);
378 }
379
380 const char * TypeCodeSeq::id() const throw(Exception)
381 {
382   return _repoId.c_str();
383 }
384
385 const char * TypeCodeSeq::name() const throw(Exception)
386 {
387   return _name.c_str();
388 }
389 const char * TypeCodeSeq::shortName() const
390 {
391   return _shortName.c_str();
392 }
393
394 const TypeCode * TypeCodeSeq::contentType() const throw(Exception)
395 {
396   return _content;
397 }
398
399 int TypeCodeSeq::isA(const TypeCode* tc) const
400 {
401   if(_kind == tc->kind())
402     return _content->isA(tc->contentType());
403   return 0;
404 }
405
406 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
407 /*!
408  *   \param tc : the given TypeCode
409  *   \return    1 if true, 0 if false
410  */
411 int TypeCodeSeq::isAdaptable(const TypeCode* tc) const
412 {
413   if(_kind == tc->kind())
414     return contentType()->isAdaptable(tc->contentType());
415   return 0;
416 }
417
418 TypeCodeSeq::TypeCodeSeq(const TypeCodeSeq& tc):TypeCode(tc),
419                                                    _name(tc._name),_shortName(tc._shortName),
420                                                    _repoId(tc._repoId),
421                                                    _content(tc._content)
422 {
423   _content->incrRef();
424 }
425
426 // --- TypeCodeArray
427
428
429 //! Create an Array type with a given name, a given id and a given contained type.
430 /*!
431  *   \param repositoryId : the given id
432  *   \param name : the given name
433  *   \param content : the given contained TypeCode
434  */
435 TypeCodeArray::TypeCodeArray(const char* repositoryId,
436                              const char* name, 
437                              const TypeCode *content,
438                              unsigned staticLgth) : TypeCode(Array), _content(content),_staticLgth(staticLgth)
439 {
440   _repoId = repositoryId;
441   _name = name;
442   string::size_type debut =_name.find_last_of('/');
443   if(debut == std::string::npos)_shortName= name;
444   else _shortName=_name.substr(debut+1);
445   _content->incrRef();
446 }
447
448 TypeCodeArray::~TypeCodeArray()
449 {
450   ((TypeCode *)_content)->decrRef();
451 }
452
453 TypeCode *TypeCodeArray::clone() const
454 {
455   return new TypeCodeArray(*this);
456 }
457
458 void TypeCodeArray::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
459 {
460   ArrayAny::putReprAtPlace(pt,val,this,deepCpy);
461 }
462
463 void TypeCodeArray::destroyZippedAny(char *data) const
464 {
465   ArrayAny::destroyReprAtPlace(data,this);
466 }
467
468 AnyPtr TypeCodeArray::getOrBuildAnyFromZippedData(char *data) const
469 {
470   return ArrayAny::getOrBuildFromData(data,this);
471 }
472
473 const char * TypeCodeArray::id() const throw(Exception)
474 {
475   return _repoId.c_str();
476 }
477
478 const char * TypeCodeArray::name() const throw(Exception)
479 {
480   return _name.c_str();
481 }
482 const char * TypeCodeArray::shortName() const
483 {
484   return _shortName.c_str();
485 }
486
487 unsigned TypeCodeArray::getStaticLgth() const
488 {
489   return _staticLgth;
490 }
491
492 const TypeCode * TypeCodeArray::contentType() const throw(Exception)
493 {
494   return _content;
495 }
496
497 int TypeCodeArray::isA(const TypeCode* tc) const
498 {
499   if(_kind == tc->kind())
500     if(_content->isA(tc->contentType()))
501       {
502         const TypeCodeArray *tcC=dynamic_cast<const TypeCodeArray *>(tc);
503         if(tcC)
504           return tcC->getStaticLgth()==_staticLgth;
505         return 0;
506       }
507   return 0;
508 }
509
510 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
511 /*!
512  *   \param tc : the given TypeCode
513  *   \return    1 if true, 0 if false
514  */
515 int TypeCodeArray::isAdaptable(const TypeCode* tc) const
516 {
517   if(_kind == tc->kind())
518     return contentType()->isAdaptable(tc->contentType());
519   return 0;
520 }
521
522 TypeCodeArray::TypeCodeArray(const TypeCodeArray& tc):TypeCode(tc),
523                                                       _name(tc._name),_shortName(tc._shortName),
524                                                       _repoId(tc._repoId),
525                                                       _content(tc._content),
526                                                       _staticLgth(tc._staticLgth)
527 {
528   _content->incrRef();
529 }
530
531 unsigned TypeCodeArray::getSizeInByteOfAnyReprInSeq() const
532 {
533   return _staticLgth*_content->getSizeInByteOfAnyReprInSeq();
534 }
535
536 // --- TypeCodeStruct
537
538
539 //! Create a struct type with a given name and a given id 
540 /*!
541  *   \param repositoryId : the given id
542  *   \param name : the given name
543  */
544 TypeCodeStruct::TypeCodeStruct(const char* repositoryId, 
545                          const char* name) : TypeCode(Struct), _name(name),_repoId(repositoryId)
546 {
547   string::size_type debut =_name.find_last_of('/');
548   if(debut == std::string::npos)_shortName= name;
549   else _shortName=_name.substr(debut+1);
550 }
551
552 TypeCodeStruct::~TypeCodeStruct()
553 {
554 }
555
556 TypeCode *TypeCodeStruct::clone() const
557 {
558   return new TypeCodeStruct(*this);
559 }
560
561 TypeCodeStruct::TypeCodeStruct(const TypeCodeStruct& tc):TypeCode(tc),
562                                                          _name(tc._name),_shortName(tc._shortName),
563                                                          _repoId(tc._repoId)
564 {
565 }
566
567 void TypeCodeStruct::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
568 {
569   throw Exception("Not implemented yet : YACS::Any for struct");
570 }
571
572 void TypeCodeStruct::destroyZippedAny(char *data) const
573 {
574   throw Exception("Not implemented yet : YACS::Any for struct");
575 }
576
577 AnyPtr TypeCodeStruct::getOrBuildAnyFromZippedData(char *data) const
578 {
579   throw Exception("Not implemented yet : YACS::Any for struct");
580 }
581
582 const char * TypeCodeStruct::id() const throw(Exception)
583 {
584   return _repoId.c_str();
585 };
586
587 const char * TypeCodeStruct::name() const throw(Exception)
588 {
589   return _name.c_str();
590 }
591
592 const char * TypeCodeStruct::shortName() const
593 {
594   return _shortName.c_str();
595 }
596
597 //! Check if this TypeCode is derived from a TypeCode with a given id
598 /*!
599  *   \param id :  a given id
600  *   \return     1 if true, 0 if false
601  */
602 int TypeCodeStruct::isA(const char* id) const throw(Exception)
603 {
604   if(_repoId.c_str() == id)return 1;
605   return 0;
606 }
607
608 //! Check if this TypeCode is derived from a given TypeCode
609 /*!
610  *   \param tc : the given TypeCode
611  *   \return    1 if true, 0 if false
612  */
613 int TypeCodeStruct::isA(const TypeCode* tc) const 
614 {
615   return isA(tc->id());
616 }
617
618 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
619 /*!
620  *   \param tc : the given TypeCode
621  *   \return    1 if true, 0 if false
622  */
623 int TypeCodeStruct::isAdaptable(const TypeCode* tc) const
624 {
625   if(_kind == tc->kind()) return isA(tc->id());
626   return 0;
627 }
628
629 void TypeCodeStruct::addMember(const std::string& name,TypeCode* tc)
630 {
631   DEBTRACE(name << " " << tc->name());
632   std::vector< std::pair<std::string,TypeCode*> >::const_iterator iter;
633   for(iter=_members.begin();iter != _members.end(); iter++)
634     {
635       if((*iter).first == name)
636         throw Exception("Struct member " + name + " already defined");
637     }
638   _members.push_back(std::pair<std::string,TypeCode*>(name,tc));
639 }
640
641 int TypeCodeStruct::memberCount() const
642 {
643   return _members.size();
644 }
645
646 const char*  TypeCodeStruct::memberName(int index) const
647 {
648   if(index > _members.size())
649     {
650       stringstream msg;
651       msg << "Struct size less than " << index;
652       msg << " : " << __FILE__ << ":" << __LINE__;
653       throw Exception(msg.str());
654     }
655   return _members[index].first.c_str();
656 }
657
658 TypeCode*  TypeCodeStruct::memberType(int index) const
659 {
660   if(index > _members.size())
661     {
662       stringstream msg;
663       msg << "Struct size less than " << index;
664       msg << " : " << __FILE__ << ":" << __LINE__;
665       throw Exception(msg.str());
666     }
667   return _members[index].second;
668 }
669
670