1 // Copyright (C) 2006-2008 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.
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
19 #include "TypeCode.hxx"
25 #include "YacsTrace.hxx"
27 using namespace YACS::ENGINE;
30 const char *TypeCode::KIND_STR_REPR []={ "None", "double", "int", "string", "bool", "Objref", "Sequence", "Array","Struct" };
34 TypeCode::TypeCode(DynType kind):_kind(kind)
38 TypeCode::TypeCode(const TypeCode& tc):_kind(tc._kind)
46 DynType TypeCode::kind() const
51 TypeCode *TypeCode::clone() const
53 return new TypeCode(*this);
56 void TypeCode::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
58 AtomAny::putReprAtPlace(pt,val,this,deepCpy);
61 void TypeCode::destroyZippedAny(char *data) const
63 AtomAny::destroyReprAtPlace(data,this);
66 AnyPtr TypeCode::getOrBuildAnyFromZippedData(char *data) const
68 return AtomAny::getOrBuildFromData(data,this);
71 const char * TypeCode::name() const throw(Exception)
73 //throw Exception("No name");
77 const char * TypeCode::shortName() const
79 //throw Exception("No shortName");
83 const char * TypeCode::id() const throw(Exception)
100 int TypeCode::isA(const char* id) const throw(Exception)
102 throw Exception("Not implemented for this type");
105 int TypeCode::isA(const TypeCode* tc) const
107 if(_kind == tc->kind()) return 1;
111 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
113 * this TypeCode is adaptable to tc if tc type can be converted to this type
115 * \param tc : the TypeCode that must be convertible to this
117 int TypeCode::isAdaptable(const TypeCode* tc) const
122 if (tc->kind() == Double) return 1;
123 if (tc->kind() == Int) return 1;
126 if (tc->kind() == Int) return 1;
129 if (tc->kind() == String) return 1;
132 if (tc->kind() == Bool) return 1;
133 if (tc->kind() == Int) return 1;
136 //objref, sequence, ...
141 //! Check if this TypeCode can be used in place of tc
143 * this TypeCode is equivalent to tc if they have the same kind
145 * \param tc : the TypeCode to compare
147 int TypeCode::isEquivalent(const TypeCode* tc) const
149 if(_kind == tc->kind()) return 1;
153 unsigned TypeCode::getSizeInByteOfAnyReprInSeq() const
158 return sizeof(double);
162 return sizeof(StringOnHeap *);
166 return sizeof(void *);
170 const TypeCode * TypeCode::contentType() const throw(Exception)
172 throw Exception("No content type");
175 static inline int validChar0(char c)
177 return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
180 static inline int validNextChar(char c)
182 return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
183 (c >= '0' && c <= '9') || (c == '_') || (c == '/'));
186 static void checkValidName(const char* name)
191 if (!validChar0(*name++)) ok = 0;
192 for(; ok && *name; name++) if (!validNextChar(*name)) ok = 0;
194 if (!ok)throw YACS::Exception("Invalid Name");
197 const char *TypeCode::getKindRepr(DynType kind)
199 return KIND_STR_REPR[(int)kind];
202 const char * TypeCode::getKindRepr() const
204 return KIND_STR_REPR[(int)_kind];
207 //! static factory of object reference type given an id and a name
208 TypeCode * TypeCode::interfaceTc(const char* id,
211 checkValidName(name);
212 return new TypeCodeObjref(id, name);
215 //! static factory of object reference type given an id, a name and a list of base types
218 * \param name : the name
219 * \param ltc : the list of base types
221 * The name must be a valid one (throw Exception is not)
223 TypeCode * TypeCode::interfaceTc(const char* id,
225 const std::list<TypeCodeObjref *>& ltc)
227 checkValidName(name);
228 return new TypeCodeObjref(id, name,ltc);
232 //! static factory of sequence type given an id, a name and a content type
233 TypeCode * TypeCode::sequenceTc(const char* id,
238 if(std::string(name)=="")
240 typname="seq"+std::string(content->name());
241 name=typname.c_str();
243 return new TypeCodeSeq(id, name,content);
245 //! static factory of struct type given an id and a name
246 TypeCode * TypeCode::structTc(const char* id,
249 return new TypeCodeStruct(id, name);
252 TypeCodeComposed::TypeCodeComposed(const TypeCodeComposed& other):TypeCode(other),
253 _name(other._name),_repoId(other._repoId),
254 _shortName(other._shortName)
258 TypeCodeComposed::TypeCodeComposed(DynType kind, const char* repositoryId, const char* name):TypeCode(kind),
259 _repoId(repositoryId),_name(name)
261 string::size_type debut =_name.find_last_of('/');
262 if(debut == std::string::npos)
265 _shortName=_name.substr(debut+1);
268 // --- TypeCodeObjref
271 TypeCodeObjref::TypeCodeObjref(const char* repositoryId,
272 const char* name) : TypeCodeComposed(Objref,repositoryId,name)
277 TypeCodeObjref::~TypeCodeObjref()
279 list<TypeCodeObjref *>::iterator iter;
280 for(iter=_listOfBases.begin();iter != _listOfBases.end(); iter++)
284 TypeCode *TypeCodeObjref::clone() const
286 return new TypeCodeObjref(*this);
289 void TypeCodeObjref::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
291 throw Exception("Not implemented yet : YACS::Any for objs ref");
294 void TypeCodeObjref::destroyZippedAny(char *data) const
296 throw Exception("Not implemented yet : YACS::Any for objs ref");
299 AnyPtr TypeCodeObjref::getOrBuildAnyFromZippedData(char *data) const
301 throw Exception("Not implemented yet : YACS::Any for objs ref");
304 const char * TypeCodeObjref::id() const throw(Exception)
306 return _repoId.c_str();
309 const char * TypeCodeObjref::name() const throw(Exception)
311 return _name.c_str();
314 const char * TypeCodeObjref::shortName() const
316 return _shortName.c_str();
319 TypeCodeObjref::TypeCodeObjref(const char* repositoryId,
321 const std::list<TypeCodeObjref *>& ltc) : TypeCodeComposed(Objref,repositoryId,name)
324 list<TypeCodeObjref *>::const_iterator iter;
325 for(iter=_listOfBases.begin();iter != _listOfBases.end(); iter++)
329 //! Check if this TypeCode is derived from a TypeCode with a given id
331 * \param id : a given id
332 * \return 1 if true, 0 if false
334 int TypeCodeObjref::isA(const char* id) const throw(Exception)
336 if(_repoId == id)return 1;
337 list<TypeCodeObjref *>::const_iterator iter;
338 for(iter=_listOfBases.begin();iter != _listOfBases.end(); iter++)
340 if ((*iter)->isA(id)) return 1;
345 //! Check if this TypeCode is derived from a given TypeCode
347 * \param tc : the given TypeCode
348 * \return 1 if true, 0 if false
350 int TypeCodeObjref::isA(const TypeCode* tc) const
352 return isA(tc->id());
355 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
357 * \param tc : the given TypeCode
358 * \return 1 if true, 0 if false
360 int TypeCodeObjref::isAdaptable(const TypeCode* tc) const
362 if(_kind == tc->kind()) return isA(tc->id());
366 //! Check if this TypeCode can be used in place of tc
368 * this TypeCode is equivalent to tc if they have the same kind
370 * \param tc : the TypeCode to compare
372 int TypeCodeObjref::isEquivalent(const TypeCode* tc) const
374 if(_kind != tc->kind())return 0;
375 if(_repoId == tc->id())return 1;
379 TypeCodeObjref::TypeCodeObjref(const TypeCodeObjref& other):TypeCodeComposed(other),
380 _listOfBases(other._listOfBases)
382 list<TypeCodeObjref *>::const_iterator iter;
383 for(iter=other._listOfBases.begin();iter!=other._listOfBases.end();iter++)
390 //! Create a sequence type with a given name, a given id and a given contained type.
392 * \param repositoryId : the given id
393 * \param name : the given name
394 * \param content : the given contained TypeCode
396 TypeCodeSeq::TypeCodeSeq(const char* repositoryId,
398 const TypeCode *content) : TypeCodeComposed(Sequence,repositoryId,name), _content(content)
403 TypeCodeSeq::~TypeCodeSeq()
405 ((TypeCode *)_content)->decrRef();
408 TypeCode *TypeCodeSeq::clone() const
410 return new TypeCodeSeq(*this);
413 void TypeCodeSeq::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
415 SequenceAny::putReprAtPlace(pt,val,this,deepCpy);
418 void TypeCodeSeq::destroyZippedAny(char *data) const
420 SequenceAny::destroyReprAtPlace(data,this);
423 unsigned TypeCodeSeq::getSizeInByteOfAnyReprInSeq() const
425 return sizeof(void*);
428 AnyPtr TypeCodeSeq::getOrBuildAnyFromZippedData(char *data) const
430 return SequenceAny::getOrBuildFromData(data,this);
433 const char * TypeCodeSeq::id() const throw(Exception)
435 return _repoId.c_str();
438 const char * TypeCodeSeq::name() const throw(Exception)
440 return _name.c_str();
442 const char * TypeCodeSeq::shortName() const
444 return _shortName.c_str();
447 const TypeCode * TypeCodeSeq::contentType() const throw(Exception)
452 int TypeCodeSeq::isA(const TypeCode* tc) const
454 if(_kind == tc->kind())
455 return _content->isA(tc->contentType());
459 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
461 * \param tc : the given TypeCode
462 * \return 1 if true, 0 if false
464 int TypeCodeSeq::isAdaptable(const TypeCode* tc) const
466 if(_kind == tc->kind())
467 return contentType()->isAdaptable(tc->contentType());
471 //! Check if this TypeCode can be used in place of tc
473 * this TypeCode is equivalent to tc if they have the same kind
475 * \param tc : the TypeCode to compare
477 int TypeCodeSeq::isEquivalent(const TypeCode* tc) const
479 if(_kind == tc->kind())
480 return _content->isEquivalent(tc->contentType());
484 TypeCodeSeq::TypeCodeSeq(const TypeCodeSeq& tc):TypeCodeComposed(tc),
485 _content(tc._content)
493 //! Create an Array type with a given name, a given id and a given contained type.
495 * \param repositoryId : the given id
496 * \param name : the given name
497 * \param content : the given contained TypeCode
499 TypeCodeArray::TypeCodeArray(const char* repositoryId,
501 const TypeCode *content,
502 unsigned staticLgth) : TypeCodeComposed(Array,repositoryId,name), _content(content),_staticLgth(staticLgth)
507 TypeCodeArray::~TypeCodeArray()
509 ((TypeCode *)_content)->decrRef();
512 TypeCode *TypeCodeArray::clone() const
514 return new TypeCodeArray(*this);
517 void TypeCodeArray::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
519 ArrayAny::putReprAtPlace(pt,val,this,deepCpy);
522 void TypeCodeArray::destroyZippedAny(char *data) const
524 ArrayAny::destroyReprAtPlace(data,this);
527 AnyPtr TypeCodeArray::getOrBuildAnyFromZippedData(char *data) const
529 return ArrayAny::getOrBuildFromData(data,this);
532 const char * TypeCodeArray::id() const throw(Exception)
534 return _repoId.c_str();
537 const char * TypeCodeArray::name() const throw(Exception)
539 return _name.c_str();
541 const char * TypeCodeArray::shortName() const
543 return _shortName.c_str();
546 unsigned TypeCodeArray::getStaticLgth() const
551 const TypeCode * TypeCodeArray::contentType() const throw(Exception)
556 int TypeCodeArray::isA(const TypeCode* tc) const
558 if(_kind == tc->kind())
559 if(_content->isA(tc->contentType()))
561 const TypeCodeArray *tcC=dynamic_cast<const TypeCodeArray *>(tc);
563 return tcC->getStaticLgth()==_staticLgth;
569 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
571 * \param tc : the given TypeCode
572 * \return 1 if true, 0 if false
574 int TypeCodeArray::isAdaptable(const TypeCode* tc) const
576 if(_kind == tc->kind())
577 return contentType()->isAdaptable(tc->contentType());
581 //! Check if this TypeCode can be used in place of tc
583 * this TypeCode is equivalent to tc if they have the same kind
585 * \param tc : the TypeCode to compare
587 int TypeCodeArray::isEquivalent(const TypeCode* tc) const
589 if(_kind == tc->kind())
590 return _content->isEquivalent(tc->contentType());
594 TypeCodeArray::TypeCodeArray(const TypeCodeArray& tc):TypeCodeComposed(tc),
595 _content(tc._content),
596 _staticLgth(tc._staticLgth)
601 unsigned TypeCodeArray::getSizeInByteOfAnyReprInSeq() const
603 return _staticLgth*_content->getSizeInByteOfAnyReprInSeq();
606 // --- TypeCodeStruct
609 //! Create a struct type with a given name and a given id
611 * \param repositoryId : the given id
612 * \param name : the given name
614 TypeCodeStruct::TypeCodeStruct(const char* repositoryId,
615 const char* name) : TypeCodeComposed(Struct,repositoryId,name)
619 TypeCodeStruct::~TypeCodeStruct()
623 TypeCode *TypeCodeStruct::clone() const
625 return new TypeCodeStruct(*this);
628 TypeCodeStruct::TypeCodeStruct(const TypeCodeStruct& tc):TypeCodeComposed(tc),_members(tc._members)
630 for(vector< std::pair<std::string,TypeCode*> >::iterator iter=_members.begin();iter!=_members.end();iter++)
631 (*iter).second->incrRef();
634 void TypeCodeStruct::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
636 StructAny::putReprAtPlace(pt,val,this,deepCpy);
639 void TypeCodeStruct::destroyZippedAny(char *data) const
641 StructAny::destroyReprAtPlace(data,this);
644 AnyPtr TypeCodeStruct::getOrBuildAnyFromZippedData(char *data) const
646 return StructAny::getOrBuildFromData(data,this);
649 const char * TypeCodeStruct::id() const throw(Exception)
651 return _repoId.c_str();
654 const char * TypeCodeStruct::name() const throw(Exception)
656 return _name.c_str();
659 const char * TypeCodeStruct::shortName() const
661 return _shortName.c_str();
664 unsigned TypeCodeStruct::getSizeInByteOfAnyReprInSeq() const
667 for(vector< pair<string,TypeCode*> >::const_iterator iter=_members.begin();iter!=_members.end();iter++)
668 ret+=(*iter).second->getSizeInByteOfAnyReprInSeq();
672 const TypeCode *TypeCodeStruct::contentType() const throw(Exception)
674 const char what[]="Content type is specified by giving a key.";
675 throw Exception(what);
678 //! Check if this TypeCode is derived from a TypeCode with a given id
680 * \param id : a given id
681 * \return 1 if true, 0 if false
683 int TypeCodeStruct::isA(const char* id) const throw(Exception)
685 if(_repoId == id)return 1;
689 //! Check if this TypeCode is derived from a given TypeCode
691 * \param tc : the given TypeCode
692 * \return 1 if true, 0 if false
694 int TypeCodeStruct::isA(const TypeCode* tc) const
696 if(_kind != tc->kind()) return 0;
697 if(_repoId == tc->id())return 1;
698 int nMember=memberCount();
699 if(nMember != ((TypeCodeStruct*)tc)->memberCount())return 0;
700 for(int i=0;i<nMember;i++)
702 const char * name=memberName(i);
703 if(strcmp(memberName(i),((TypeCodeStruct*)tc)->memberName(i)) != 0)return 0;
704 if(!memberType(i)->isA(((TypeCodeStruct*)tc)->memberType(i)))return 0;
709 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
711 * \param tc : the given TypeCode
712 * \return 1 if true, 0 if false
714 int TypeCodeStruct::isAdaptable(const TypeCode* tc) const
716 if(_kind == tc->kind()) return isA(tc->id());
720 //! Check if this TypeCode can be used in place of tc
722 * this TypeCode is equivalent to tc if they have the same kind
724 * \param tc : the TypeCode to compare
726 int TypeCodeStruct::isEquivalent(const TypeCode* tc) const
728 if(_kind != tc->kind()) return 0;
729 int nMember=memberCount();
730 if(nMember != ((TypeCodeStruct*)tc)->memberCount())return 0;
731 for(int i=0;i<nMember;i++)
733 const char * name=memberName(i);
734 if(strcmp(memberName(i),((TypeCodeStruct*)tc)->memberName(i)) != 0)return 0;
735 if(!memberType(i)->isEquivalent(((TypeCodeStruct*)tc)->memberType(i)))return 0;
740 void TypeCodeStruct::addMember(const std::string& name,TypeCode* tc)
742 DEBTRACE(name << " " << tc->name());
743 std::vector< std::pair<std::string,TypeCode*> >::const_iterator iter;
744 for(iter=_members.begin();iter != _members.end(); iter++)
746 if((*iter).first == name)
747 throw Exception("Struct member " + name + " already defined");
749 _members.push_back(std::pair<std::string,TypeCode*>(name,tc));
753 * If name is not an existing key, 0 is returned.
754 * \param offset : Out parameter, that specified the location of start of data discriminated by name key.
756 const TypeCode *TypeCodeStruct::getMember(const std::string& name, unsigned& offset) const
758 std::vector< std::pair<std::string,TypeCode*> >::const_iterator iter;
760 for(iter=_members.begin();iter != _members.end(); iter++)
762 if((*iter).first==name)
763 return (*iter).second;
764 offset+=(*iter).second->getSizeInByteOfAnyReprInSeq();
769 int TypeCodeStruct::memberCount() const
771 return _members.size();
774 const char* TypeCodeStruct::memberName(int index) const
776 if(index > _members.size())
779 msg << "Struct size less than " << index;
780 msg << " : " << __FILE__ << ":" << __LINE__;
781 throw Exception(msg.str());
783 return _members[index].first.c_str();
786 TypeCode* TypeCodeStruct::memberType(int index) const
788 if(index > _members.size())
791 msg << "Struct size less than " << index;
792 msg << " : " << __FILE__ << ":" << __LINE__;
793 throw Exception(msg.str());
795 return _members[index].second;