1 // Copyright (C) 2006-2022 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "TypeCode.hxx"
26 #include "YacsTrace.hxx"
28 using namespace YACS::ENGINE;
31 const char *TypeCode::KIND_STR_REPR []={ "None", "double", "int", "string", "bool", "Objref", "Sequence", "Array","Struct" };
35 TypeCode::TypeCode(DynType kind):_kind(kind)
39 TypeCode::TypeCode(const TypeCode& tc):_kind(tc._kind)
47 DynType TypeCode::kind() const
52 TypeCode *TypeCode::clone() const
54 return new TypeCode(*this);
57 void TypeCode::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
59 AtomAny::putReprAtPlace(pt,val,this,deepCpy);
62 void TypeCode::destroyZippedAny(char *data) const
64 AtomAny::destroyReprAtPlace(data,this);
67 AnyPtr TypeCode::getOrBuildAnyFromZippedData(char *data) const
69 return AtomAny::getOrBuildFromData(data,this);
72 const char * TypeCode::name() const
77 const char * TypeCode::shortName() const
82 const char * TypeCode::id() const
99 int TypeCode::isA(const char* id) const
101 throw Exception("Not implemented for this type");
104 int TypeCode::isA(const TypeCode* tc) const
106 if(_kind == tc->kind()) return 1;
110 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
112 * this TypeCode is adaptable to tc if tc type can be converted to this type
114 * \param tc : the TypeCode that must be convertible to this
116 int TypeCode::isAdaptable(const TypeCode* tc) const
121 if (tc->kind() == Double) return 1;
122 if (tc->kind() == Int) return 1;
125 if (tc->kind() == Int) return 1;
128 if (tc->kind() == String) return 1;
131 if (tc->kind() == Bool) return 1;
132 if (tc->kind() == Int) return 1;
135 //objref, sequence, ...
140 std::string TypeCode::getPrintStr() const
145 //! Check if this TypeCode can be used in place of tc
147 * this TypeCode is equivalent to tc if they have the same kind
149 * \param tc : the TypeCode to compare
151 int TypeCode::isEquivalent(const TypeCode* tc) const
153 if(_kind == tc->kind()) return 1;
157 unsigned TypeCode::getSizeInByteOfAnyReprInSeq() const
162 return sizeof(double);
166 return sizeof(StringOnHeap *);
170 return sizeof(void *);
174 const TypeCode * TypeCode::contentType() const
176 throw Exception("No content type");
179 static inline int validChar0(char c)
181 return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
184 static inline int validNextChar(char c)
186 return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
187 (c >= '0' && c <= '9') || (c == '_') || (c == '/'));
190 static void checkValidName(const char* name)
195 if (!validChar0(*name++)) ok = 0;
196 for(; ok && *name; name++) if (!validNextChar(*name)) ok = 0;
198 if (!ok)throw YACS::Exception("Invalid Name");
201 const char *TypeCode::getKindRepr(DynType kind)
203 return KIND_STR_REPR[(int)kind];
206 const TypeCode *TypeCode::subContentType(int lev) const
209 throw YACS::Exception("subContentType: Invalid input val !");
212 const TypeCode *ret(this);
213 for(int i=0;i<lev;i++)
215 const TypeCode *cand(ret->contentType());
217 throw YACS::Exception("subContentType : Invalid input val 2 !");
223 const char * TypeCode::getKindRepr() const
225 return KIND_STR_REPR[(int)_kind];
228 //! static factory of object reference type given an id and a name
229 TypeCode * TypeCode::interfaceTc(const char* id,
232 checkValidName(name);
233 return new TypeCodeObjref(id, name);
236 //! static factory of object reference type given an id, a name and a list of base types
239 * \param name : the name
240 * \param ltc : the list of base types
242 * The name must be a valid one (throw Exception is not)
244 TypeCode * TypeCode::interfaceTc(const char* id,
246 const std::list<TypeCodeObjref *>& ltc)
248 checkValidName(name);
249 return new TypeCodeObjref(id, name,ltc);
253 //! static factory of sequence type given an id, a name and a content type
254 TypeCode * TypeCode::sequenceTc(const char* id,
259 if(std::string(name)=="")
261 typname="seq"+std::string(content->name());
262 name=typname.c_str();
264 if(std::string(id)=="")
266 return new TypeCodeSeq(id, name,content);
268 //! static factory of struct type given an id and a name
269 TypeCode * TypeCode::structTc(const char* id,
272 return new TypeCodeStruct(id, name);
275 TypeCodeComposed::TypeCodeComposed(const TypeCodeComposed& other):TypeCode(other),
276 _name(other._name),_repoId(other._repoId),
277 _shortName(other._shortName)
281 TypeCodeComposed::TypeCodeComposed(DynType kind, const char* repositoryId, const char* name):TypeCode(kind),
282 _repoId(repositoryId),_name(name)
284 string::size_type debut =_name.find_last_of('/');
285 if(debut == std::string::npos)
288 _shortName=_name.substr(debut+1);
291 // --- TypeCodeObjref
294 TypeCodeObjref::TypeCodeObjref(const char* repositoryId,
295 const char* name) : TypeCodeComposed(Objref,repositoryId,name)
300 TypeCodeObjref::~TypeCodeObjref()
302 list<TypeCodeObjref *>::iterator iter;
303 for(iter=_listOfBases.begin();iter != _listOfBases.end(); iter++)
307 TypeCode *TypeCodeObjref::clone() const
309 return new TypeCodeObjref(*this);
312 void TypeCodeObjref::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
314 AtomAny::putReprAtPlace(pt,val,this,deepCpy);
317 void TypeCodeObjref::destroyZippedAny(char *data) const
319 AtomAny::destroyReprAtPlace(data,this);
322 AnyPtr TypeCodeObjref::getOrBuildAnyFromZippedData(char *data) const
324 return AtomAny::getOrBuildFromData(data,this);
327 const char * TypeCodeObjref::id() const
329 return _repoId.c_str();
332 const char * TypeCodeObjref::name() const
334 return _name.c_str();
337 const char * TypeCodeObjref::shortName() const
339 return _shortName.c_str();
342 TypeCodeObjref::TypeCodeObjref(const char* repositoryId,
344 const std::list<TypeCodeObjref *>& ltc) : TypeCodeComposed(Objref,repositoryId,name)
347 list<TypeCodeObjref *>::const_iterator iter;
348 for(iter=_listOfBases.begin();iter != _listOfBases.end(); iter++)
352 //! Check if this TypeCode is derived from a TypeCode with a given id
354 * \param id : a given id
355 * \return 1 if true, 0 if false
357 int TypeCodeObjref::isA(const char* id) const
359 if(_repoId == id)return 1;
360 list<TypeCodeObjref *>::const_iterator iter;
361 for(iter=_listOfBases.begin();iter != _listOfBases.end(); iter++)
363 if ((*iter)->isA(id)) return 1;
368 //! Check if this TypeCode is derived from a given TypeCode
370 * \param tc : the given TypeCode
371 * \return 1 if true, 0 if false
373 int TypeCodeObjref::isA(const TypeCode* tc) const
375 return isA(tc->id());
378 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
380 * \param tc : the given TypeCode
381 * \return 1 if true, 0 if false
383 int TypeCodeObjref::isAdaptable(const TypeCode* tc) const
385 if(_kind == tc->kind()) return isA(tc->id());
389 //! Check if this TypeCode can be used in place of tc
391 * this TypeCode is equivalent to tc if they have the same kind
393 * \param tc : the TypeCode to compare
395 int TypeCodeObjref::isEquivalent(const TypeCode* tc) const
397 if(_kind != tc->kind())return 0;
398 if(_repoId == tc->id())return 1;
402 TypeCodeObjref::TypeCodeObjref(const TypeCodeObjref& other):TypeCodeComposed(other),
403 _listOfBases(other._listOfBases)
405 list<TypeCodeObjref *>::const_iterator iter;
406 for(iter=other._listOfBases.begin();iter!=other._listOfBases.end();iter++)
413 //! Create a sequence type with a given name, a given id and a given contained type.
415 * \param repositoryId : the given id
416 * \param name : the given name
417 * \param content : the given contained TypeCode
419 TypeCodeSeq::TypeCodeSeq(const char* repositoryId,
421 const TypeCode *content) : TypeCodeComposed(Sequence,repositoryId,name), _content(content)
426 TypeCodeSeq::~TypeCodeSeq()
428 ((TypeCode *)_content)->decrRef();
431 TypeCode *TypeCodeSeq::clone() const
433 return new TypeCodeSeq(*this);
436 void TypeCodeSeq::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
438 SequenceAny::putReprAtPlace(pt,val,this,deepCpy);
441 void TypeCodeSeq::destroyZippedAny(char *data) const
443 SequenceAny::destroyReprAtPlace(data,this);
446 unsigned TypeCodeSeq::getSizeInByteOfAnyReprInSeq() const
448 return sizeof(void*);
451 AnyPtr TypeCodeSeq::getOrBuildAnyFromZippedData(char *data) const
453 return SequenceAny::getOrBuildFromData(data,this);
456 const char * TypeCodeSeq::id() const
458 return _repoId.c_str();
461 const char * TypeCodeSeq::name() const
463 return _name.c_str();
465 const char * TypeCodeSeq::shortName() const
467 return _shortName.c_str();
470 std::string TypeCodeSeq::getPrintStr() const
472 std::ostringstream oss; oss << "seq[" << contentType()->getPrintStr() << "]";
476 const TypeCode * TypeCodeSeq::contentType() const
481 int TypeCodeSeq::isA(const TypeCode* tc) const
483 if(_kind == tc->kind())
484 return _content->isA(tc->contentType());
488 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
490 * \param tc : the given TypeCode
491 * \return 1 if true, 0 if false
493 int TypeCodeSeq::isAdaptable(const TypeCode* tc) const
495 if(_kind == tc->kind())
496 return contentType()->isAdaptable(tc->contentType());
500 //! Check if this TypeCode can be used in place of tc
502 * this TypeCode is equivalent to tc if they have the same kind
504 * \param tc : the TypeCode to compare
506 int TypeCodeSeq::isEquivalent(const TypeCode* tc) const
508 if(_kind == tc->kind())
509 return _content->isEquivalent(tc->contentType());
513 TypeCodeSeq::TypeCodeSeq(const TypeCodeSeq& tc):TypeCodeComposed(tc),
514 _content(tc._content)
522 //! Create an Array type with a given name, a given id and a given contained type.
524 * \param repositoryId : the given id
525 * \param name : the given name
526 * \param content : the given contained TypeCode
527 * \param staticLgth : the length
529 TypeCodeArray::TypeCodeArray(const char* repositoryId,
531 const TypeCode *content,
532 unsigned staticLgth) : TypeCodeComposed(Array,repositoryId,name), _content(content),_staticLgth(staticLgth)
537 TypeCodeArray::~TypeCodeArray()
539 ((TypeCode *)_content)->decrRef();
542 TypeCode *TypeCodeArray::clone() const
544 return new TypeCodeArray(*this);
547 void TypeCodeArray::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
549 ArrayAny::putReprAtPlace(pt,val,this,deepCpy);
552 void TypeCodeArray::destroyZippedAny(char *data) const
554 ArrayAny::destroyReprAtPlace(data,this);
557 AnyPtr TypeCodeArray::getOrBuildAnyFromZippedData(char *data) const
559 return ArrayAny::getOrBuildFromData(data,this);
562 const char * TypeCodeArray::id() const
564 return _repoId.c_str();
567 const char * TypeCodeArray::name() const
569 return _name.c_str();
571 const char * TypeCodeArray::shortName() const
573 return _shortName.c_str();
576 unsigned TypeCodeArray::getStaticLgth() const
581 const TypeCode * TypeCodeArray::contentType() const
586 int TypeCodeArray::isA(const TypeCode* tc) const
588 if(_kind == tc->kind())
589 if(_content->isA(tc->contentType()))
591 const TypeCodeArray *tcC=dynamic_cast<const TypeCodeArray *>(tc);
593 return tcC->getStaticLgth()==_staticLgth;
599 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
601 * \param tc : the given TypeCode
602 * \return 1 if true, 0 if false
604 int TypeCodeArray::isAdaptable(const TypeCode* tc) const
606 if(_kind == tc->kind())
607 return contentType()->isAdaptable(tc->contentType());
611 //! Check if this TypeCode can be used in place of tc
613 * this TypeCode is equivalent to tc if they have the same kind
615 * \param tc : the TypeCode to compare
617 int TypeCodeArray::isEquivalent(const TypeCode* tc) const
619 if(_kind == tc->kind())
620 return _content->isEquivalent(tc->contentType());
624 TypeCodeArray::TypeCodeArray(const TypeCodeArray& tc):TypeCodeComposed(tc),
625 _content(tc._content),
626 _staticLgth(tc._staticLgth)
631 unsigned TypeCodeArray::getSizeInByteOfAnyReprInSeq() const
633 return _staticLgth*_content->getSizeInByteOfAnyReprInSeq();
636 // --- TypeCodeStruct
639 //! Create a struct type with a given name and a given id
641 * \param repositoryId : the given id
642 * \param name : the given name
644 TypeCodeStruct::TypeCodeStruct(const char* repositoryId,
645 const char* name) : TypeCodeComposed(Struct,repositoryId,name)
649 TypeCodeStruct::~TypeCodeStruct()
651 for(vector< pair<string,TypeCode*> >::iterator iter=_members.begin();iter!=_members.end();iter++)
652 (*iter).second->decrRef();
655 TypeCode *TypeCodeStruct::clone() const
657 return new TypeCodeStruct(*this);
660 TypeCodeStruct::TypeCodeStruct(const TypeCodeStruct& tc):TypeCodeComposed(tc),_members(tc._members)
662 for(vector< std::pair<std::string,TypeCode*> >::iterator iter=_members.begin();iter!=_members.end();iter++)
663 (*iter).second->incrRef();
666 void TypeCodeStruct::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
668 StructAny::putReprAtPlace(pt,val,this,deepCpy);
671 void TypeCodeStruct::destroyZippedAny(char *data) const
673 StructAny::destroyReprAtPlace(data,this);
676 AnyPtr TypeCodeStruct::getOrBuildAnyFromZippedData(char *data) const
678 return StructAny::getOrBuildFromData(data,this);
681 const char * TypeCodeStruct::id() const
683 return _repoId.c_str();
686 const char * TypeCodeStruct::name() const
688 return _name.c_str();
691 const char * TypeCodeStruct::shortName() const
693 return _shortName.c_str();
696 unsigned TypeCodeStruct::getSizeInByteOfAnyReprInSeq() const
699 for(vector< pair<string,TypeCode*> >::const_iterator iter=_members.begin();iter!=_members.end();iter++)
700 ret+=(*iter).second->getSizeInByteOfAnyReprInSeq();
704 const TypeCode *TypeCodeStruct::contentType() const
706 const char what[]="Content type is specified by giving a key.";
707 throw Exception(what);
710 //! Check if this TypeCode is derived from a TypeCode with a given id
712 * \param id : a given id
713 * \return 1 if true, 0 if false
715 int TypeCodeStruct::isA(const char* id) const
717 if(_repoId == id)return 1;
721 //! Check if this TypeCode is derived from a given TypeCode
723 * \param tc : the given TypeCode
724 * \return 1 if true, 0 if false
726 int TypeCodeStruct::isA(const TypeCode* tc) const
728 if(_kind != tc->kind()) return 0;
729 if(_repoId == tc->id())return 1;
730 int nMember=memberCount();
731 if(nMember != ((TypeCodeStruct*)tc)->memberCount())return 0;
732 for(int i=0;i<nMember;i++)
734 const char * name=memberName(i);
735 if(strcmp(memberName(i),((TypeCodeStruct*)tc)->memberName(i)) != 0)return 0;
736 if(!memberType(i)->isA(((TypeCodeStruct*)tc)->memberType(i)))return 0;
741 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
743 * \param tc : the given TypeCode
744 * \return 1 if true, 0 if false
746 int TypeCodeStruct::isAdaptable(const TypeCode* tc) const
748 if (_kind != tc->kind()) return 0;
749 if (_repoId == tc->id()) return 1;
750 int nMember = memberCount();
751 if (nMember != ((TypeCodeStruct*)tc)->memberCount()) return 0;
752 for (int i=0 ; i<nMember ; i++)
754 const char * name = memberName(i);
755 if (strcmp(memberName(i), ((TypeCodeStruct*)tc)->memberName(i)) != 0) return 0;
756 if (!memberType(i)->isAdaptable(((TypeCodeStruct*)tc)->memberType(i))) return 0;
761 //! Check if this TypeCode can be used in place of tc
763 * this TypeCode is equivalent to tc if they have the same kind
765 * \param tc : the TypeCode to compare
767 int TypeCodeStruct::isEquivalent(const TypeCode* tc) const
769 if(_kind != tc->kind()) return 0;
770 int nMember=memberCount();
771 if(nMember != ((TypeCodeStruct*)tc)->memberCount())return 0;
772 for(int i=0;i<nMember;i++)
774 const char * name=memberName(i);
775 if(strcmp(memberName(i),((TypeCodeStruct*)tc)->memberName(i)) != 0)return 0;
776 if(!memberType(i)->isEquivalent(((TypeCodeStruct*)tc)->memberType(i)))return 0;
781 void TypeCodeStruct::addMember(const std::string& name,TypeCode* tc)
783 DEBTRACE(name << " " << tc->name());
784 std::vector< std::pair<std::string,TypeCode*> >::const_iterator iter;
785 for(iter=_members.begin();iter != _members.end(); iter++)
787 if((*iter).first == name)
788 throw Exception("Struct member " + name + " already defined");
790 _members.push_back(std::pair<std::string,TypeCode*>(name,tc));
794 //! Get typecode of struct member given its name
796 * If name is not an existing key, 0 is returned.
797 * \param name : the member name
798 * \param offset : Out parameter, that specified the location of start of data discriminated by name key.
799 * \return the member TypeCode
801 const TypeCode *TypeCodeStruct::getMember(const std::string& name, unsigned& offset) const
803 std::vector< std::pair<std::string,TypeCode*> >::const_iterator iter;
805 for(iter=_members.begin();iter != _members.end(); iter++)
807 if((*iter).first==name)
808 return (*iter).second;
809 offset+=(*iter).second->getSizeInByteOfAnyReprInSeq();
814 int TypeCodeStruct::memberCount() const
816 return _members.size();
819 const char* TypeCodeStruct::memberName(int index) const
821 if(index > _members.size())
824 msg << "Struct size less than " << index;
825 msg << " : " << __FILE__ << ":" << __LINE__;
826 throw Exception(msg.str());
828 return _members[index].first.c_str();
831 TypeCode* TypeCodeStruct::memberType(int index) const
833 if(index > _members.size())
836 msg << "Struct size less than " << index;
837 msg << " : " << __FILE__ << ":" << __LINE__;
838 throw Exception(msg.str());
840 return _members[index].second;