1 // Copyright (C) 2006-2016 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 throw(YACS::Exception)
74 //throw Exception("No name");
78 const char * TypeCode::shortName() const
80 //throw Exception("No shortName");
84 const char * TypeCode::id() const throw(YACS::Exception)
101 int TypeCode::isA(const char* id) const throw(YACS::Exception)
103 throw Exception("Not implemented for this type");
106 int TypeCode::isA(const TypeCode* tc) const
108 if(_kind == tc->kind()) return 1;
112 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
114 * this TypeCode is adaptable to tc if tc type can be converted to this type
116 * \param tc : the TypeCode that must be convertible to this
118 int TypeCode::isAdaptable(const TypeCode* tc) const
123 if (tc->kind() == Double) return 1;
124 if (tc->kind() == Int) return 1;
127 if (tc->kind() == Int) return 1;
130 if (tc->kind() == String) return 1;
133 if (tc->kind() == Bool) return 1;
134 if (tc->kind() == Int) return 1;
137 //objref, sequence, ...
142 //! Check if this TypeCode can be used in place of tc
144 * this TypeCode is equivalent to tc if they have the same kind
146 * \param tc : the TypeCode to compare
148 int TypeCode::isEquivalent(const TypeCode* tc) const
150 if(_kind == tc->kind()) return 1;
154 unsigned TypeCode::getSizeInByteOfAnyReprInSeq() const
159 return sizeof(double);
163 return sizeof(StringOnHeap *);
167 return sizeof(void *);
171 const TypeCode * TypeCode::contentType() const throw(YACS::Exception)
173 throw Exception("No content type");
176 static inline int validChar0(char c)
178 return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
181 static inline int validNextChar(char c)
183 return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
184 (c >= '0' && c <= '9') || (c == '_') || (c == '/'));
187 static void checkValidName(const char* name)
192 if (!validChar0(*name++)) ok = 0;
193 for(; ok && *name; name++) if (!validNextChar(*name)) ok = 0;
195 if (!ok)throw YACS::Exception("Invalid Name");
198 const char *TypeCode::getKindRepr(DynType kind)
200 return KIND_STR_REPR[(int)kind];
203 const char * TypeCode::getKindRepr() const
205 return KIND_STR_REPR[(int)_kind];
208 //! static factory of object reference type given an id and a name
209 TypeCode * TypeCode::interfaceTc(const char* id,
212 checkValidName(name);
213 return new TypeCodeObjref(id, name);
216 //! static factory of object reference type given an id, a name and a list of base types
219 * \param name : the name
220 * \param ltc : the list of base types
222 * The name must be a valid one (throw Exception is not)
224 TypeCode * TypeCode::interfaceTc(const char* id,
226 const std::list<TypeCodeObjref *>& ltc)
228 checkValidName(name);
229 return new TypeCodeObjref(id, name,ltc);
233 //! static factory of sequence type given an id, a name and a content type
234 TypeCode * TypeCode::sequenceTc(const char* id,
239 if(std::string(name)=="")
241 typname="seq"+std::string(content->name());
242 name=typname.c_str();
244 if(std::string(id)=="")
246 return new TypeCodeSeq(id, name,content);
248 //! static factory of struct type given an id and a name
249 TypeCode * TypeCode::structTc(const char* id,
252 return new TypeCodeStruct(id, name);
255 TypeCodeComposed::TypeCodeComposed(const TypeCodeComposed& other):TypeCode(other),
256 _name(other._name),_repoId(other._repoId),
257 _shortName(other._shortName)
261 TypeCodeComposed::TypeCodeComposed(DynType kind, const char* repositoryId, const char* name):TypeCode(kind),
262 _repoId(repositoryId),_name(name)
264 string::size_type debut =_name.find_last_of('/');
265 if(debut == std::string::npos)
268 _shortName=_name.substr(debut+1);
271 // --- TypeCodeObjref
274 TypeCodeObjref::TypeCodeObjref(const char* repositoryId,
275 const char* name) : TypeCodeComposed(Objref,repositoryId,name)
280 TypeCodeObjref::~TypeCodeObjref()
282 list<TypeCodeObjref *>::iterator iter;
283 for(iter=_listOfBases.begin();iter != _listOfBases.end(); iter++)
287 TypeCode *TypeCodeObjref::clone() const
289 return new TypeCodeObjref(*this);
292 void TypeCodeObjref::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
294 throw Exception("Not implemented yet : YACS::Any for objs ref");
297 void TypeCodeObjref::destroyZippedAny(char *data) const
299 throw Exception("Not implemented yet : YACS::Any for objs ref");
302 AnyPtr TypeCodeObjref::getOrBuildAnyFromZippedData(char *data) const
304 throw Exception("Not implemented yet : YACS::Any for objs ref");
307 const char * TypeCodeObjref::id() const throw(YACS::Exception)
309 return _repoId.c_str();
312 const char * TypeCodeObjref::name() const throw(YACS::Exception)
314 return _name.c_str();
317 const char * TypeCodeObjref::shortName() const
319 return _shortName.c_str();
322 TypeCodeObjref::TypeCodeObjref(const char* repositoryId,
324 const std::list<TypeCodeObjref *>& ltc) : TypeCodeComposed(Objref,repositoryId,name)
327 list<TypeCodeObjref *>::const_iterator iter;
328 for(iter=_listOfBases.begin();iter != _listOfBases.end(); iter++)
332 //! Check if this TypeCode is derived from a TypeCode with a given id
334 * \param id : a given id
335 * \return 1 if true, 0 if false
337 int TypeCodeObjref::isA(const char* id) const throw(YACS::Exception)
339 if(_repoId == id)return 1;
340 list<TypeCodeObjref *>::const_iterator iter;
341 for(iter=_listOfBases.begin();iter != _listOfBases.end(); iter++)
343 if ((*iter)->isA(id)) return 1;
348 //! Check if this TypeCode is derived from a given TypeCode
350 * \param tc : the given TypeCode
351 * \return 1 if true, 0 if false
353 int TypeCodeObjref::isA(const TypeCode* tc) const
355 return isA(tc->id());
358 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
360 * \param tc : the given TypeCode
361 * \return 1 if true, 0 if false
363 int TypeCodeObjref::isAdaptable(const TypeCode* tc) const
365 if(_kind == tc->kind()) return isA(tc->id());
369 //! Check if this TypeCode can be used in place of tc
371 * this TypeCode is equivalent to tc if they have the same kind
373 * \param tc : the TypeCode to compare
375 int TypeCodeObjref::isEquivalent(const TypeCode* tc) const
377 if(_kind != tc->kind())return 0;
378 if(_repoId == tc->id())return 1;
382 TypeCodeObjref::TypeCodeObjref(const TypeCodeObjref& other):TypeCodeComposed(other),
383 _listOfBases(other._listOfBases)
385 list<TypeCodeObjref *>::const_iterator iter;
386 for(iter=other._listOfBases.begin();iter!=other._listOfBases.end();iter++)
393 //! Create a sequence type with a given name, a given id and a given contained type.
395 * \param repositoryId : the given id
396 * \param name : the given name
397 * \param content : the given contained TypeCode
399 TypeCodeSeq::TypeCodeSeq(const char* repositoryId,
401 const TypeCode *content) : TypeCodeComposed(Sequence,repositoryId,name), _content(content)
406 TypeCodeSeq::~TypeCodeSeq()
408 ((TypeCode *)_content)->decrRef();
411 TypeCode *TypeCodeSeq::clone() const
413 return new TypeCodeSeq(*this);
416 void TypeCodeSeq::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
418 SequenceAny::putReprAtPlace(pt,val,this,deepCpy);
421 void TypeCodeSeq::destroyZippedAny(char *data) const
423 SequenceAny::destroyReprAtPlace(data,this);
426 unsigned TypeCodeSeq::getSizeInByteOfAnyReprInSeq() const
428 return sizeof(void*);
431 AnyPtr TypeCodeSeq::getOrBuildAnyFromZippedData(char *data) const
433 return SequenceAny::getOrBuildFromData(data,this);
436 const char * TypeCodeSeq::id() const throw(YACS::Exception)
438 return _repoId.c_str();
441 const char * TypeCodeSeq::name() const throw(YACS::Exception)
443 return _name.c_str();
445 const char * TypeCodeSeq::shortName() const
447 return _shortName.c_str();
450 const TypeCode * TypeCodeSeq::contentType() const throw(YACS::Exception)
455 int TypeCodeSeq::isA(const TypeCode* tc) const
457 if(_kind == tc->kind())
458 return _content->isA(tc->contentType());
462 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
464 * \param tc : the given TypeCode
465 * \return 1 if true, 0 if false
467 int TypeCodeSeq::isAdaptable(const TypeCode* tc) const
469 if(_kind == tc->kind())
470 return contentType()->isAdaptable(tc->contentType());
474 //! Check if this TypeCode can be used in place of tc
476 * this TypeCode is equivalent to tc if they have the same kind
478 * \param tc : the TypeCode to compare
480 int TypeCodeSeq::isEquivalent(const TypeCode* tc) const
482 if(_kind == tc->kind())
483 return _content->isEquivalent(tc->contentType());
487 TypeCodeSeq::TypeCodeSeq(const TypeCodeSeq& tc):TypeCodeComposed(tc),
488 _content(tc._content)
496 //! Create an Array type with a given name, a given id and a given contained type.
498 * \param repositoryId : the given id
499 * \param name : the given name
500 * \param content : the given contained TypeCode
501 * \param staticLgth : the length
503 TypeCodeArray::TypeCodeArray(const char* repositoryId,
505 const TypeCode *content,
506 unsigned staticLgth) : TypeCodeComposed(Array,repositoryId,name), _content(content),_staticLgth(staticLgth)
511 TypeCodeArray::~TypeCodeArray()
513 ((TypeCode *)_content)->decrRef();
516 TypeCode *TypeCodeArray::clone() const
518 return new TypeCodeArray(*this);
521 void TypeCodeArray::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
523 ArrayAny::putReprAtPlace(pt,val,this,deepCpy);
526 void TypeCodeArray::destroyZippedAny(char *data) const
528 ArrayAny::destroyReprAtPlace(data,this);
531 AnyPtr TypeCodeArray::getOrBuildAnyFromZippedData(char *data) const
533 return ArrayAny::getOrBuildFromData(data,this);
536 const char * TypeCodeArray::id() const throw(YACS::Exception)
538 return _repoId.c_str();
541 const char * TypeCodeArray::name() const throw(YACS::Exception)
543 return _name.c_str();
545 const char * TypeCodeArray::shortName() const
547 return _shortName.c_str();
550 unsigned TypeCodeArray::getStaticLgth() const
555 const TypeCode * TypeCodeArray::contentType() const throw(YACS::Exception)
560 int TypeCodeArray::isA(const TypeCode* tc) const
562 if(_kind == tc->kind())
563 if(_content->isA(tc->contentType()))
565 const TypeCodeArray *tcC=dynamic_cast<const TypeCodeArray *>(tc);
567 return tcC->getStaticLgth()==_staticLgth;
573 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
575 * \param tc : the given TypeCode
576 * \return 1 if true, 0 if false
578 int TypeCodeArray::isAdaptable(const TypeCode* tc) const
580 if(_kind == tc->kind())
581 return contentType()->isAdaptable(tc->contentType());
585 //! Check if this TypeCode can be used in place of tc
587 * this TypeCode is equivalent to tc if they have the same kind
589 * \param tc : the TypeCode to compare
591 int TypeCodeArray::isEquivalent(const TypeCode* tc) const
593 if(_kind == tc->kind())
594 return _content->isEquivalent(tc->contentType());
598 TypeCodeArray::TypeCodeArray(const TypeCodeArray& tc):TypeCodeComposed(tc),
599 _content(tc._content),
600 _staticLgth(tc._staticLgth)
605 unsigned TypeCodeArray::getSizeInByteOfAnyReprInSeq() const
607 return _staticLgth*_content->getSizeInByteOfAnyReprInSeq();
610 // --- TypeCodeStruct
613 //! Create a struct type with a given name and a given id
615 * \param repositoryId : the given id
616 * \param name : the given name
618 TypeCodeStruct::TypeCodeStruct(const char* repositoryId,
619 const char* name) : TypeCodeComposed(Struct,repositoryId,name)
623 TypeCodeStruct::~TypeCodeStruct()
625 for(vector< pair<string,TypeCode*> >::iterator iter=_members.begin();iter!=_members.end();iter++)
626 (*iter).second->decrRef();
629 TypeCode *TypeCodeStruct::clone() const
631 return new TypeCodeStruct(*this);
634 TypeCodeStruct::TypeCodeStruct(const TypeCodeStruct& tc):TypeCodeComposed(tc),_members(tc._members)
636 for(vector< std::pair<std::string,TypeCode*> >::iterator iter=_members.begin();iter!=_members.end();iter++)
637 (*iter).second->incrRef();
640 void TypeCodeStruct::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
642 StructAny::putReprAtPlace(pt,val,this,deepCpy);
645 void TypeCodeStruct::destroyZippedAny(char *data) const
647 StructAny::destroyReprAtPlace(data,this);
650 AnyPtr TypeCodeStruct::getOrBuildAnyFromZippedData(char *data) const
652 return StructAny::getOrBuildFromData(data,this);
655 const char * TypeCodeStruct::id() const throw(YACS::Exception)
657 return _repoId.c_str();
660 const char * TypeCodeStruct::name() const throw(YACS::Exception)
662 return _name.c_str();
665 const char * TypeCodeStruct::shortName() const
667 return _shortName.c_str();
670 unsigned TypeCodeStruct::getSizeInByteOfAnyReprInSeq() const
673 for(vector< pair<string,TypeCode*> >::const_iterator iter=_members.begin();iter!=_members.end();iter++)
674 ret+=(*iter).second->getSizeInByteOfAnyReprInSeq();
678 const TypeCode *TypeCodeStruct::contentType() const throw(YACS::Exception)
680 const char what[]="Content type is specified by giving a key.";
681 throw Exception(what);
684 //! Check if this TypeCode is derived from a TypeCode with a given id
686 * \param id : a given id
687 * \return 1 if true, 0 if false
689 int TypeCodeStruct::isA(const char* id) const throw(YACS::Exception)
691 if(_repoId == id)return 1;
695 //! Check if this TypeCode is derived from a given TypeCode
697 * \param tc : the given TypeCode
698 * \return 1 if true, 0 if false
700 int TypeCodeStruct::isA(const TypeCode* tc) const
702 if(_kind != tc->kind()) return 0;
703 if(_repoId == tc->id())return 1;
704 int nMember=memberCount();
705 if(nMember != ((TypeCodeStruct*)tc)->memberCount())return 0;
706 for(int i=0;i<nMember;i++)
708 const char * name=memberName(i);
709 if(strcmp(memberName(i),((TypeCodeStruct*)tc)->memberName(i)) != 0)return 0;
710 if(!memberType(i)->isA(((TypeCodeStruct*)tc)->memberType(i)))return 0;
715 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
717 * \param tc : the given TypeCode
718 * \return 1 if true, 0 if false
720 int TypeCodeStruct::isAdaptable(const TypeCode* tc) const
722 if (_kind != tc->kind()) return 0;
723 if (_repoId == tc->id()) return 1;
724 int nMember = memberCount();
725 if (nMember != ((TypeCodeStruct*)tc)->memberCount()) return 0;
726 for (int i=0 ; i<nMember ; i++)
728 const char * name = memberName(i);
729 if (strcmp(memberName(i), ((TypeCodeStruct*)tc)->memberName(i)) != 0) return 0;
730 if (!memberType(i)->isAdaptable(((TypeCodeStruct*)tc)->memberType(i))) return 0;
735 //! Check if this TypeCode can be used in place of tc
737 * this TypeCode is equivalent to tc if they have the same kind
739 * \param tc : the TypeCode to compare
741 int TypeCodeStruct::isEquivalent(const TypeCode* tc) const
743 if(_kind != tc->kind()) return 0;
744 int nMember=memberCount();
745 if(nMember != ((TypeCodeStruct*)tc)->memberCount())return 0;
746 for(int i=0;i<nMember;i++)
748 const char * name=memberName(i);
749 if(strcmp(memberName(i),((TypeCodeStruct*)tc)->memberName(i)) != 0)return 0;
750 if(!memberType(i)->isEquivalent(((TypeCodeStruct*)tc)->memberType(i)))return 0;
755 void TypeCodeStruct::addMember(const std::string& name,TypeCode* tc)
757 DEBTRACE(name << " " << tc->name());
758 std::vector< std::pair<std::string,TypeCode*> >::const_iterator iter;
759 for(iter=_members.begin();iter != _members.end(); iter++)
761 if((*iter).first == name)
762 throw Exception("Struct member " + name + " already defined");
764 _members.push_back(std::pair<std::string,TypeCode*>(name,tc));
768 //! Get typecode of struct member given its name
770 * If name is not an existing key, 0 is returned.
771 * \param name : the member name
772 * \param offset : Out parameter, that specified the location of start of data discriminated by name key.
773 * \return the member TypeCode
775 const TypeCode *TypeCodeStruct::getMember(const std::string& name, unsigned& offset) const
777 std::vector< std::pair<std::string,TypeCode*> >::const_iterator iter;
779 for(iter=_members.begin();iter != _members.end(); iter++)
781 if((*iter).first==name)
782 return (*iter).second;
783 offset+=(*iter).second->getSizeInByteOfAnyReprInSeq();
788 int TypeCodeStruct::memberCount() const
790 return _members.size();
793 const char* TypeCodeStruct::memberName(int index) const
795 if(index > _members.size())
798 msg << "Struct size less than " << index;
799 msg << " : " << __FILE__ << ":" << __LINE__;
800 throw Exception(msg.str());
802 return _members[index].first.c_str();
805 TypeCode* TypeCodeStruct::memberType(int index) const
807 if(index > _members.size())
810 msg << "Struct size less than " << index;
811 msg << " : " << __FILE__ << ":" << __LINE__;
812 throw Exception(msg.str());
814 return _members[index].second;