2 #include "TypeCode.hxx"
7 #include "YacsTrace.hxx"
9 using namespace YACS::ENGINE;
12 const char *TypeCode::KIND_STR_REPR []={ "None", "Double", "Int", "String", "Bool", "Objref", "Sequence", "Array","Struct" };
16 TypeCode::TypeCode(DynType kind):_kind(kind)
20 TypeCode::TypeCode(const TypeCode& tc):_kind(tc._kind)
28 DynType TypeCode::kind() const
33 TypeCode *TypeCode::clone() const
35 return new TypeCode(*this);
38 void TypeCode::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
40 AtomAny::putReprAtPlace(pt,val,this,deepCpy);
43 void TypeCode::destroyZippedAny(char *data) const
45 AtomAny::destroyReprAtPlace(data,this);
48 AnyPtr TypeCode::getOrBuildAnyFromZippedData(char *data) const
50 return AtomAny::getOrBuildFromData(data,this);
53 const char * TypeCode::name() const throw(Exception)
55 //throw Exception("No name");
59 const char * TypeCode::shortName() const
61 //throw Exception("No shortName");
65 const char * TypeCode::id() const throw(Exception)
82 int TypeCode::isA(const char* id) const throw(Exception)
84 throw Exception("Not implemented for this type");
87 int TypeCode::isA(const TypeCode* tc) const
89 if(_kind == tc->kind()) return 1;
93 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
95 * this TypeCode is adaptable to tc if tc type can be converted to this type
97 * \param tc : the TypeCode that must be convertible to this
99 int TypeCode::isAdaptable(const TypeCode* tc) const
104 if (tc->kind() == Double) return 1;
105 if (tc->kind() == Int) return 1;
108 if (tc->kind() == Int) return 1;
111 if (tc->kind() == String) return 1;
114 if (tc->kind() == Bool) return 1;
115 if (tc->kind() == Int) return 1;
118 //objref, sequence, ...
123 //! Check if this TypeCode can be used in place of tc
125 * this TypeCode is equivalent to tc if they have the same kind
127 * \param tc : the TypeCode to compare
129 int TypeCode::isEquivalent(const TypeCode* tc) const
131 if(_kind == tc->kind()) return 1;
135 unsigned TypeCode::getSizeInByteOfAnyReprInSeq() const
140 return sizeof(double);
144 return sizeof(StringOnHeap *);
148 return sizeof(void *);
152 const TypeCode * TypeCode::contentType() const throw(Exception)
154 throw Exception("No content type");
157 static inline int validChar0(char c)
159 return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
162 static inline int validNextChar(char c)
164 return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
165 (c >= '0' && c <= '9') || (c == '_') || (c == '/'));
168 static void checkValidName(const char* name)
173 if (!validChar0(*name++)) ok = 0;
174 for(; ok && *name; name++) if (!validNextChar(*name)) ok = 0;
176 if (!ok)throw YACS::Exception("Invalid Name");
179 const char *TypeCode::getKindRepr(DynType kind)
181 return KIND_STR_REPR[(int)kind];
184 const char * TypeCode::getKindRepr() const
186 return KIND_STR_REPR[(int)_kind];
189 //! static factory of object reference type given an id and a name
190 TypeCode * TypeCode::interfaceTc(const char* id,
193 checkValidName(name);
194 return new TypeCodeObjref(id, name);
197 //! static factory of object reference type given an id, a name and a list of base types
200 * \param name : the name
201 * \param ltc : the list of base types
203 * The name must be a valid one (throw Exception is not)
205 TypeCode * TypeCode::interfaceTc(const char* id,
207 const std::list<TypeCodeObjref *>& ltc)
209 checkValidName(name);
210 return new TypeCodeObjref(id, name,ltc);
214 //! static factory of sequence type given an id, a name and a content type
215 TypeCode * TypeCode::sequenceTc(const char* id,
219 return new TypeCodeSeq(id, name,content);
221 //! static factory of struct type given an id and a name
222 TypeCode * TypeCode::structTc(const char* id,
225 return new TypeCodeStruct(id, name);
228 TypeCodeComposed::TypeCodeComposed(const TypeCodeComposed& other):TypeCode(other),
229 _name(other._name),_repoId(other._repoId),
230 _shortName(other._shortName)
234 TypeCodeComposed::TypeCodeComposed(DynType kind, const char* repositoryId, const char* name):TypeCode(kind),
235 _repoId(repositoryId),_name(name)
237 string::size_type debut =_name.find_last_of('/');
238 if(debut == std::string::npos)
241 _shortName=_name.substr(debut+1);
244 // --- TypeCodeObjref
247 TypeCodeObjref::TypeCodeObjref(const char* repositoryId,
248 const char* name) : TypeCodeComposed(Objref,repositoryId,name)
253 TypeCodeObjref::~TypeCodeObjref()
255 list<TypeCodeObjref *>::iterator iter;
256 for(iter=_listOfBases.begin();iter != _listOfBases.end(); iter++)
260 TypeCode *TypeCodeObjref::clone() const
262 return new TypeCodeObjref(*this);
265 void TypeCodeObjref::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
267 throw Exception("Not implemented yet : YACS::Any for objs ref");
270 void TypeCodeObjref::destroyZippedAny(char *data) const
272 throw Exception("Not implemented yet : YACS::Any for objs ref");
275 AnyPtr TypeCodeObjref::getOrBuildAnyFromZippedData(char *data) const
277 throw Exception("Not implemented yet : YACS::Any for objs ref");
280 const char * TypeCodeObjref::id() const throw(Exception)
282 return _repoId.c_str();
285 const char * TypeCodeObjref::name() const throw(Exception)
287 return _name.c_str();
290 const char * TypeCodeObjref::shortName() const
292 return _shortName.c_str();
295 TypeCodeObjref::TypeCodeObjref(const char* repositoryId,
297 const std::list<TypeCodeObjref *>& ltc) : TypeCodeComposed(Objref,repositoryId,name)
300 list<TypeCodeObjref *>::const_iterator iter;
301 for(iter=_listOfBases.begin();iter != _listOfBases.end(); iter++)
305 //! Check if this TypeCode is derived from a TypeCode with a given id
307 * \param id : a given id
308 * \return 1 if true, 0 if false
310 int TypeCodeObjref::isA(const char* id) const throw(Exception)
312 if(_repoId == id)return 1;
313 list<TypeCodeObjref *>::const_iterator iter;
314 for(iter=_listOfBases.begin();iter != _listOfBases.end(); iter++)
316 if ((*iter)->isA(id)) return 1;
321 //! Check if this TypeCode is derived from a given TypeCode
323 * \param tc : the given TypeCode
324 * \return 1 if true, 0 if false
326 int TypeCodeObjref::isA(const TypeCode* tc) const
328 return isA(tc->id());
331 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
333 * \param tc : the given TypeCode
334 * \return 1 if true, 0 if false
336 int TypeCodeObjref::isAdaptable(const TypeCode* tc) const
338 if(_kind == tc->kind()) return isA(tc->id());
342 //! Check if this TypeCode can be used in place of tc
344 * this TypeCode is equivalent to tc if they have the same kind
346 * \param tc : the TypeCode to compare
348 int TypeCodeObjref::isEquivalent(const TypeCode* tc) const
350 if(_kind != tc->kind())return 0;
351 if(_repoId == tc->id())return 1;
355 TypeCodeObjref::TypeCodeObjref(const TypeCodeObjref& other):TypeCodeComposed(other),
356 _listOfBases(other._listOfBases)
358 list<TypeCodeObjref *>::const_iterator iter;
359 for(iter=other._listOfBases.begin();iter!=other._listOfBases.end();iter++)
366 //! Create a sequence type with a given name, a given id and a given contained type.
368 * \param repositoryId : the given id
369 * \param name : the given name
370 * \param content : the given contained TypeCode
372 TypeCodeSeq::TypeCodeSeq(const char* repositoryId,
374 const TypeCode *content) : TypeCodeComposed(Sequence,repositoryId,name), _content(content)
379 TypeCodeSeq::~TypeCodeSeq()
381 ((TypeCode *)_content)->decrRef();
384 TypeCode *TypeCodeSeq::clone() const
386 return new TypeCodeSeq(*this);
389 void TypeCodeSeq::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
391 SequenceAny::putReprAtPlace(pt,val,this,deepCpy);
394 void TypeCodeSeq::destroyZippedAny(char *data) const
396 SequenceAny::destroyReprAtPlace(data,this);
399 unsigned TypeCodeSeq::getSizeInByteOfAnyReprInSeq() const
401 return sizeof(void*);
404 AnyPtr TypeCodeSeq::getOrBuildAnyFromZippedData(char *data) const
406 return SequenceAny::getOrBuildFromData(data,this);
409 const char * TypeCodeSeq::id() const throw(Exception)
411 return _repoId.c_str();
414 const char * TypeCodeSeq::name() const throw(Exception)
416 return _name.c_str();
418 const char * TypeCodeSeq::shortName() const
420 return _shortName.c_str();
423 const TypeCode * TypeCodeSeq::contentType() const throw(Exception)
428 int TypeCodeSeq::isA(const TypeCode* tc) const
430 if(_kind == tc->kind())
431 return _content->isA(tc->contentType());
435 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
437 * \param tc : the given TypeCode
438 * \return 1 if true, 0 if false
440 int TypeCodeSeq::isAdaptable(const TypeCode* tc) const
442 if(_kind == tc->kind())
443 return contentType()->isAdaptable(tc->contentType());
447 //! Check if this TypeCode can be used in place of tc
449 * this TypeCode is equivalent to tc if they have the same kind
451 * \param tc : the TypeCode to compare
453 int TypeCodeSeq::isEquivalent(const TypeCode* tc) const
455 if(_kind == tc->kind())
456 return _content->isEquivalent(tc->contentType());
460 TypeCodeSeq::TypeCodeSeq(const TypeCodeSeq& tc):TypeCodeComposed(tc),
461 _content(tc._content)
469 //! Create an Array type with a given name, a given id and a given contained type.
471 * \param repositoryId : the given id
472 * \param name : the given name
473 * \param content : the given contained TypeCode
475 TypeCodeArray::TypeCodeArray(const char* repositoryId,
477 const TypeCode *content,
478 unsigned staticLgth) : TypeCodeComposed(Array,repositoryId,name), _content(content),_staticLgth(staticLgth)
483 TypeCodeArray::~TypeCodeArray()
485 ((TypeCode *)_content)->decrRef();
488 TypeCode *TypeCodeArray::clone() const
490 return new TypeCodeArray(*this);
493 void TypeCodeArray::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
495 ArrayAny::putReprAtPlace(pt,val,this,deepCpy);
498 void TypeCodeArray::destroyZippedAny(char *data) const
500 ArrayAny::destroyReprAtPlace(data,this);
503 AnyPtr TypeCodeArray::getOrBuildAnyFromZippedData(char *data) const
505 return ArrayAny::getOrBuildFromData(data,this);
508 const char * TypeCodeArray::id() const throw(Exception)
510 return _repoId.c_str();
513 const char * TypeCodeArray::name() const throw(Exception)
515 return _name.c_str();
517 const char * TypeCodeArray::shortName() const
519 return _shortName.c_str();
522 unsigned TypeCodeArray::getStaticLgth() const
527 const TypeCode * TypeCodeArray::contentType() const throw(Exception)
532 int TypeCodeArray::isA(const TypeCode* tc) const
534 if(_kind == tc->kind())
535 if(_content->isA(tc->contentType()))
537 const TypeCodeArray *tcC=dynamic_cast<const TypeCodeArray *>(tc);
539 return tcC->getStaticLgth()==_staticLgth;
545 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
547 * \param tc : the given TypeCode
548 * \return 1 if true, 0 if false
550 int TypeCodeArray::isAdaptable(const TypeCode* tc) const
552 if(_kind == tc->kind())
553 return contentType()->isAdaptable(tc->contentType());
557 //! Check if this TypeCode can be used in place of tc
559 * this TypeCode is equivalent to tc if they have the same kind
561 * \param tc : the TypeCode to compare
563 int TypeCodeArray::isEquivalent(const TypeCode* tc) const
565 if(_kind == tc->kind())
566 return _content->isEquivalent(tc->contentType());
570 TypeCodeArray::TypeCodeArray(const TypeCodeArray& tc):TypeCodeComposed(tc),
571 _content(tc._content),
572 _staticLgth(tc._staticLgth)
577 unsigned TypeCodeArray::getSizeInByteOfAnyReprInSeq() const
579 return _staticLgth*_content->getSizeInByteOfAnyReprInSeq();
582 // --- TypeCodeStruct
585 //! Create a struct type with a given name and a given id
587 * \param repositoryId : the given id
588 * \param name : the given name
590 TypeCodeStruct::TypeCodeStruct(const char* repositoryId,
591 const char* name) : TypeCodeComposed(Struct,repositoryId,name)
595 TypeCodeStruct::~TypeCodeStruct()
599 TypeCode *TypeCodeStruct::clone() const
601 return new TypeCodeStruct(*this);
604 TypeCodeStruct::TypeCodeStruct(const TypeCodeStruct& tc):TypeCodeComposed(tc),_members(tc._members)
606 for(vector< std::pair<std::string,TypeCode*> >::iterator iter=_members.begin();iter!=_members.end();iter++)
607 (*iter).second->incrRef();
610 void TypeCodeStruct::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
612 StructAny::putReprAtPlace(pt,val,this,deepCpy);
615 void TypeCodeStruct::destroyZippedAny(char *data) const
617 StructAny::destroyReprAtPlace(data,this);
620 AnyPtr TypeCodeStruct::getOrBuildAnyFromZippedData(char *data) const
622 return StructAny::getOrBuildFromData(data,this);
625 const char * TypeCodeStruct::id() const throw(Exception)
627 return _repoId.c_str();
630 const char * TypeCodeStruct::name() const throw(Exception)
632 return _name.c_str();
635 const char * TypeCodeStruct::shortName() const
637 return _shortName.c_str();
640 unsigned TypeCodeStruct::getSizeInByteOfAnyReprInSeq() const
643 for(vector< pair<string,TypeCode*> >::const_iterator iter=_members.begin();iter!=_members.end();iter++)
644 ret+=(*iter).second->getSizeInByteOfAnyReprInSeq();
648 const TypeCode *TypeCodeStruct::contentType() const throw(Exception)
650 const char what[]="Content type is specified by giving a key.";
651 throw Exception(what);
654 //! Check if this TypeCode is derived from a TypeCode with a given id
656 * \param id : a given id
657 * \return 1 if true, 0 if false
659 int TypeCodeStruct::isA(const char* id) const throw(Exception)
661 if(_repoId == id)return 1;
665 //! Check if this TypeCode is derived from a given TypeCode
667 * \param tc : the given TypeCode
668 * \return 1 if true, 0 if false
670 int TypeCodeStruct::isA(const TypeCode* tc) const
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++)
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;
685 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
687 * \param tc : the given TypeCode
688 * \return 1 if true, 0 if false
690 int TypeCodeStruct::isAdaptable(const TypeCode* tc) const
692 if(_kind == tc->kind()) return isA(tc->id());
696 //! Check if this TypeCode can be used in place of tc
698 * this TypeCode is equivalent to tc if they have the same kind
700 * \param tc : the TypeCode to compare
702 int TypeCodeStruct::isEquivalent(const TypeCode* tc) const
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++)
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;
716 void TypeCodeStruct::addMember(const std::string& name,TypeCode* tc)
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++)
722 if((*iter).first == name)
723 throw Exception("Struct member " + name + " already defined");
725 _members.push_back(std::pair<std::string,TypeCode*>(name,tc));
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.
732 const TypeCode *TypeCodeStruct::getMember(const std::string& name, unsigned& offset) const
734 std::vector< std::pair<std::string,TypeCode*> >::const_iterator iter;
736 for(iter=_members.begin();iter != _members.end(); iter++)
738 if((*iter).first==name)
739 return (*iter).second;
740 offset+=(*iter).second->getSizeInByteOfAnyReprInSeq();
745 int TypeCodeStruct::memberCount() const
747 return _members.size();
750 const char* TypeCodeStruct::memberName(int index) const
752 if(index > _members.size())
755 msg << "Struct size less than " << index;
756 msg << " : " << __FILE__ << ":" << __LINE__;
757 throw Exception(msg.str());
759 return _members[index].first.c_str();
762 TypeCode* TypeCodeStruct::memberType(int index) const
764 if(index > _members.size())
767 msg << "Struct size less than " << index;
768 msg << " : " << __FILE__ << ":" << __LINE__;
769 throw Exception(msg.str());
771 return _members[index].second;