Salome HOME
Useful access method to available resources
[modules/yacs.git] / src / engine / TypeCode.cxx
index 9aeb6ba7290793fb44433137d4cc4b72df536690..38560cf0cf28e265a07644e6d6f7ba60e15ae9df 100644 (file)
@@ -1,7 +1,26 @@
+// Copyright (C) 2006-2016  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
 
 #include "TypeCode.hxx"
 #include <sstream>
 #include <iostream>
+#include <cstring>
 
 //#define _DEVDEBUG_
 #include "YacsTrace.hxx"
@@ -9,7 +28,7 @@
 using namespace YACS::ENGINE;
 using namespace std;
 
-const char *TypeCode::KIND_STR_REPR []={ "None", "Double", "Int", "String", "Bool", "Objref", "Sequence", "Array","Struct" };
+const char *TypeCode::KIND_STR_REPR []={ "None", "double", "int", "string", "bool", "Objref", "Sequence", "Array","Struct" };
 
 // --- TypeCode
 
@@ -50,7 +69,7 @@ AnyPtr TypeCode::getOrBuildAnyFromZippedData(char *data) const
   return AtomAny::getOrBuildFromData(data,this);
 }
 
-const char * TypeCode::name() const throw(Exception)
+const char * TypeCode::name() const throw(YACS::Exception)
 {
   //throw Exception("No name");
   return id();
@@ -62,24 +81,24 @@ const char * TypeCode::shortName() const
   return id();
 }
 
-const char * TypeCode::id() const throw(Exception)
+const char * TypeCode::id() const throw(YACS::Exception)
 {
   switch(_kind)
     {
     case Double:
-      return "Double";
+      return "double";
     case Int:
-      return "Int";
+      return "int";
     case String:
-      return "String";
+      return "string";
     case Bool:
-      return "Bool";
+      return "bool";
     default:
       return "";
     }
 }
 
-int TypeCode::isA(const char* id) const throw(Exception)
+int TypeCode::isA(const char* id) const throw(YACS::Exception)
 {
   throw Exception("Not implemented for this type");
 }
@@ -120,6 +139,18 @@ int TypeCode::isAdaptable(const TypeCode* tc) const
     }
 }
 
+//! Check if this TypeCode can be used in place of tc
+/*!
+ * this TypeCode is equivalent to tc if they have the same kind
+ *
+ *   \param tc : the TypeCode to compare
+ */
+int TypeCode::isEquivalent(const TypeCode* tc) const 
+{
+  if(_kind == tc->kind()) return 1;
+  return 0;
+}
+
 unsigned TypeCode::getSizeInByteOfAnyReprInSeq() const
 {
   switch(_kind)
@@ -137,7 +168,7 @@ unsigned TypeCode::getSizeInByteOfAnyReprInSeq() const
     }
 }
 
-const TypeCode * TypeCode::contentType() const throw(Exception)
+const TypeCode * TypeCode::contentType() const throw(YACS::Exception)
 {
   throw Exception("No content type");
 };
@@ -204,6 +235,14 @@ TypeCode * TypeCode::sequenceTc(const char* id,
                                  const char* name,
                                  TypeCode *content)
 {
+  std::string typname;
+  if(std::string(name)=="")
+    {
+      typname="seq"+std::string(content->name());
+      name=typname.c_str();
+    }
+  if(std::string(id)=="")
+    id=name;
   return new TypeCodeSeq(id, name,content);
 };
 //! static factory of struct type given an id and a name 
@@ -213,18 +252,28 @@ TypeCode * TypeCode::structTc(const char* id,
   return new TypeCodeStruct(id, name);
 };
 
+TypeCodeComposed::TypeCodeComposed(const TypeCodeComposed& other):TypeCode(other),
+                                                                  _name(other._name),_repoId(other._repoId),
+                                                                  _shortName(other._shortName)
+{
+}
+
+TypeCodeComposed::TypeCodeComposed(DynType kind, const char* repositoryId, const char* name):TypeCode(kind),
+                                                                                             _repoId(repositoryId),_name(name)
+{
+  string::size_type debut =_name.find_last_of('/');
+  if(debut == std::string::npos)
+    _shortName= name;
+  else
+    _shortName=_name.substr(debut+1);
+}
 
 // --- TypeCodeObjref
 
 
 TypeCodeObjref::TypeCodeObjref(const char* repositoryId, 
-                                 const char* name) : TypeCode(Objref)
+                               const char* name) : TypeCodeComposed(Objref,repositoryId,name)
 {
-  _repoId = repositoryId;
-  _name = name;
-  string::size_type debut =_name.find_last_of('/');
-  if(debut == std::string::npos)_shortName= name;
-  else _shortName=_name.substr(debut+1);
 }
 
 
@@ -255,12 +304,12 @@ AnyPtr TypeCodeObjref::getOrBuildAnyFromZippedData(char *data) const
   throw Exception("Not implemented yet : YACS::Any for objs ref");
 }
 
-const char * TypeCodeObjref::id() const throw(Exception)
+const char * TypeCodeObjref::id() const throw(YACS::Exception)
 {
   return _repoId.c_str();
 };
 
-const char * TypeCodeObjref::name() const throw(Exception)
+const char * TypeCodeObjref::name() const throw(YACS::Exception)
 {
   return _name.c_str();
 }
@@ -271,14 +320,9 @@ const char * TypeCodeObjref::shortName() const
 }
 
 TypeCodeObjref::TypeCodeObjref(const char* repositoryId,
-                                 const char* name,
-                                 const std::list<TypeCodeObjref *>& ltc) : TypeCode(Objref)
+                               const char* name,
+                               const std::list<TypeCodeObjref *>& ltc) : TypeCodeComposed(Objref,repositoryId,name)
 {
-  _repoId = repositoryId;
-  _name = name;
-  string::size_type debut =_name.find_last_of('/');
-  if(debut == std::string::npos)_shortName= name;
-  else _shortName=_name.substr(debut+1);
   _listOfBases=ltc;
   list<TypeCodeObjref *>::const_iterator iter;
   for(iter=_listOfBases.begin();iter != _listOfBases.end(); iter++)
@@ -290,7 +334,7 @@ TypeCodeObjref::TypeCodeObjref(const char* repositoryId,
  *   \param id :  a given id
  *   \return     1 if true, 0 if false
  */
-int TypeCodeObjref::isA(const char* id) const throw(Exception)
+int TypeCodeObjref::isA(const char* id) const throw(YACS::Exception)
 {
   if(_repoId == id)return 1;
   list<TypeCodeObjref *>::const_iterator iter;
@@ -322,9 +366,21 @@ int TypeCodeObjref::isAdaptable(const TypeCode* tc) const
   return 0;
 }
 
-TypeCodeObjref::TypeCodeObjref(const TypeCodeObjref& other):TypeCode(other),_name(other._name),
-                                                               _repoId(other._shortName),
-                                                               _listOfBases(other._listOfBases)
+//! Check if this TypeCode can be used in place of tc
+/*!
+ * this TypeCode is equivalent to tc if they have the same kind
+ *
+ *   \param tc : the TypeCode to compare
+ */
+int TypeCodeObjref::isEquivalent(const TypeCode* tc) const 
+{
+  if(_kind != tc->kind())return 0;
+  if(_repoId == tc->id())return 1;
+  return 0;
+}
+
+TypeCodeObjref::TypeCodeObjref(const TypeCodeObjref& other):TypeCodeComposed(other),
+                                                            _listOfBases(other._listOfBases)
 {
   list<TypeCodeObjref *>::const_iterator iter;
   for(iter=other._listOfBases.begin();iter!=other._listOfBases.end();iter++)
@@ -341,14 +397,9 @@ TypeCodeObjref::TypeCodeObjref(const TypeCodeObjref& other):TypeCode(other),_nam
  *   \param content : the given contained TypeCode
  */
 TypeCodeSeq::TypeCodeSeq(const char* repositoryId,
-                           const char* name, 
-                           const TypeCode *content) : TypeCode(Sequence), _content(content)
+                         const char* name, 
+                         const TypeCode *content) : TypeCodeComposed(Sequence,repositoryId,name), _content(content)
 {
-  _repoId = repositoryId;
-  _name = name;
-  string::size_type debut =_name.find_last_of('/');
-  if(debut == std::string::npos)_shortName= name;
-  else _shortName=_name.substr(debut+1);
   _content->incrRef();
 }
 
@@ -372,17 +423,22 @@ void TypeCodeSeq::destroyZippedAny(char *data) const
   SequenceAny::destroyReprAtPlace(data,this);
 }
 
+unsigned TypeCodeSeq::getSizeInByteOfAnyReprInSeq() const
+{
+  return sizeof(void*);
+}
+
 AnyPtr TypeCodeSeq::getOrBuildAnyFromZippedData(char *data) const
 {
   return SequenceAny::getOrBuildFromData(data,this);
 }
 
-const char * TypeCodeSeq::id() const throw(Exception)
+const char * TypeCodeSeq::id() const throw(YACS::Exception)
 {
   return _repoId.c_str();
 }
 
-const char * TypeCodeSeq::name() const throw(Exception)
+const char * TypeCodeSeq::name() const throw(YACS::Exception)
 {
   return _name.c_str();
 }
@@ -391,7 +447,7 @@ const char * TypeCodeSeq::shortName() const
   return _shortName.c_str();
 }
 
-const TypeCode * TypeCodeSeq::contentType() const throw(Exception)
+const TypeCode * TypeCodeSeq::contentType() const throw(YACS::Exception)
 {
   return _content;
 }
@@ -415,10 +471,21 @@ int TypeCodeSeq::isAdaptable(const TypeCode* tc) const
   return 0;
 }
 
-TypeCodeSeq::TypeCodeSeq(const TypeCodeSeq& tc):TypeCode(tc),
-                                                   _name(tc._name),_shortName(tc._shortName),
-                                                   _repoId(tc._repoId),
-                                                   _content(tc._content)
+//! Check if this TypeCode can be used in place of tc
+/*!
+ * this TypeCode is equivalent to tc if they have the same kind
+ *
+ *   \param tc : the TypeCode to compare
+ */
+int TypeCodeSeq::isEquivalent(const TypeCode* tc) const 
+{
+  if(_kind == tc->kind())
+    return _content->isEquivalent(tc->contentType());
+  return 0;
+}
+
+TypeCodeSeq::TypeCodeSeq(const TypeCodeSeq& tc):TypeCodeComposed(tc),
+                                                _content(tc._content)
 {
   _content->incrRef();
 }
@@ -431,17 +498,13 @@ TypeCodeSeq::TypeCodeSeq(const TypeCodeSeq& tc):TypeCode(tc),
  *   \param repositoryId : the given id
  *   \param name : the given name
  *   \param content : the given contained TypeCode
+ *   \param staticLgth : the length
  */
 TypeCodeArray::TypeCodeArray(const char* repositoryId,
                              const char* name, 
                              const TypeCode *content,
-                             unsigned staticLgth) : TypeCode(Array), _content(content),_staticLgth(staticLgth)
+                             unsigned staticLgth) : TypeCodeComposed(Array,repositoryId,name), _content(content),_staticLgth(staticLgth)
 {
-  _repoId = repositoryId;
-  _name = name;
-  string::size_type debut =_name.find_last_of('/');
-  if(debut == std::string::npos)_shortName= name;
-  else _shortName=_name.substr(debut+1);
   _content->incrRef();
 }
 
@@ -470,12 +533,12 @@ AnyPtr TypeCodeArray::getOrBuildAnyFromZippedData(char *data) const
   return ArrayAny::getOrBuildFromData(data,this);
 }
 
-const char * TypeCodeArray::id() const throw(Exception)
+const char * TypeCodeArray::id() const throw(YACS::Exception)
 {
   return _repoId.c_str();
 }
 
-const char * TypeCodeArray::name() const throw(Exception)
+const char * TypeCodeArray::name() const throw(YACS::Exception)
 {
   return _name.c_str();
 }
@@ -489,7 +552,7 @@ unsigned TypeCodeArray::getStaticLgth() const
   return _staticLgth;
 }
 
-const TypeCode * TypeCodeArray::contentType() const throw(Exception)
+const TypeCode * TypeCodeArray::contentType() const throw(YACS::Exception)
 {
   return _content;
 }
@@ -519,9 +582,20 @@ int TypeCodeArray::isAdaptable(const TypeCode* tc) const
   return 0;
 }
 
-TypeCodeArray::TypeCodeArray(const TypeCodeArray& tc):TypeCode(tc),
-                                                      _name(tc._name),_shortName(tc._shortName),
-                                                      _repoId(tc._repoId),
+//! Check if this TypeCode can be used in place of tc
+/*!
+ * this TypeCode is equivalent to tc if they have the same kind
+ *
+ *   \param tc : the TypeCode to compare
+ */
+int TypeCodeArray::isEquivalent(const TypeCode* tc) const 
+{
+  if(_kind == tc->kind())
+    return _content->isEquivalent(tc->contentType());
+  return 0;
+}
+
+TypeCodeArray::TypeCodeArray(const TypeCodeArray& tc):TypeCodeComposed(tc),
                                                       _content(tc._content),
                                                       _staticLgth(tc._staticLgth)
 {
@@ -542,15 +616,14 @@ unsigned TypeCodeArray::getSizeInByteOfAnyReprInSeq() const
  *   \param name : the given name
  */
 TypeCodeStruct::TypeCodeStruct(const char* repositoryId, 
-                         const char* name) : TypeCode(Struct), _name(name),_repoId(repositoryId)
+                               const char* name) : TypeCodeComposed(Struct,repositoryId,name)
 {
-  string::size_type debut =_name.find_last_of('/');
-  if(debut == std::string::npos)_shortName= name;
-  else _shortName=_name.substr(debut+1);
 }
 
 TypeCodeStruct::~TypeCodeStruct()
 {
+  for(vector< pair<string,TypeCode*> >::iterator iter=_members.begin();iter!=_members.end();iter++)
+    (*iter).second->decrRef();
 }
 
 TypeCode *TypeCodeStruct::clone() const
@@ -558,33 +631,33 @@ TypeCode *TypeCodeStruct::clone() const
   return new TypeCodeStruct(*this);
 }
 
-TypeCodeStruct::TypeCodeStruct(const TypeCodeStruct& tc):TypeCode(tc),
-                                                         _name(tc._name),_shortName(tc._shortName),
-                                                         _repoId(tc._repoId)
+TypeCodeStruct::TypeCodeStruct(const TypeCodeStruct& tc):TypeCodeComposed(tc),_members(tc._members)
 {
+  for(vector< std::pair<std::string,TypeCode*> >::iterator iter=_members.begin();iter!=_members.end();iter++)
+    (*iter).second->incrRef();
 }
 
 void TypeCodeStruct::putReprAtPlace(char *pt, const char *val, bool deepCpy) const
 {
-  throw Exception("Not implemented yet : YACS::Any for struct");
+  StructAny::putReprAtPlace(pt,val,this,deepCpy);
 }
 
 void TypeCodeStruct::destroyZippedAny(char *data) const
 {
-  throw Exception("Not implemented yet : YACS::Any for struct");
+  StructAny::destroyReprAtPlace(data,this);
 }
 
 AnyPtr TypeCodeStruct::getOrBuildAnyFromZippedData(char *data) const
 {
-  throw Exception("Not implemented yet : YACS::Any for struct");
+  return StructAny::getOrBuildFromData(data,this);
 }
 
-const char * TypeCodeStruct::id() const throw(Exception)
+const char * TypeCodeStruct::id() const throw(YACS::Exception)
 {
   return _repoId.c_str();
 };
 
-const char * TypeCodeStruct::name() const throw(Exception)
+const char * TypeCodeStruct::name() const throw(YACS::Exception)
 {
   return _name.c_str();
 }
@@ -594,14 +667,28 @@ const char * TypeCodeStruct::shortName() const
   return _shortName.c_str();
 }
 
+unsigned TypeCodeStruct::getSizeInByteOfAnyReprInSeq() const
+{
+  unsigned ret=0;
+  for(vector< pair<string,TypeCode*> >::const_iterator iter=_members.begin();iter!=_members.end();iter++)
+    ret+=(*iter).second->getSizeInByteOfAnyReprInSeq();
+  return ret;
+}
+
+const TypeCode *TypeCodeStruct::contentType() const throw(YACS::Exception)
+{
+  const char what[]="Content type is specified by giving a key.";
+  throw Exception(what);
+}
+
 //! Check if this TypeCode is derived from a TypeCode with a given id
 /*!
  *   \param id :  a given id
  *   \return     1 if true, 0 if false
  */
-int TypeCodeStruct::isA(const char* id) const throw(Exception)
+int TypeCodeStruct::isA(const char* id) const throw(YACS::Exception)
 {
-  if(_repoId.c_str() == id)return 1;
+  if(_repoId == id)return 1;
   return 0;
 }
 
@@ -612,7 +699,17 @@ int TypeCodeStruct::isA(const char* id) const throw(Exception)
  */
 int TypeCodeStruct::isA(const TypeCode* tc) const 
 {
-  return isA(tc->id());
+  if(_kind != tc->kind()) return 0;
+  if(_repoId == tc->id())return 1;
+  int nMember=memberCount();
+  if(nMember != ((TypeCodeStruct*)tc)->memberCount())return 0;
+  for(int i=0;i<nMember;i++)
+    {
+       const char * name=memberName(i);
+       if(strcmp(memberName(i),((TypeCodeStruct*)tc)->memberName(i)) != 0)return 0;
+       if(!memberType(i)->isA(((TypeCodeStruct*)tc)->memberType(i)))return 0;
+    }
+  return 1;
 }
 
 //! Check if this TypeCode is adaptable to a given TypeCode (tc)
@@ -622,8 +719,37 @@ int TypeCodeStruct::isA(const TypeCode* tc) const
  */
 int TypeCodeStruct::isAdaptable(const TypeCode* tc) const
 {
-  if(_kind == tc->kind()) return isA(tc->id());
-  return 0;
+  if (_kind != tc->kind()) return 0;
+  if (_repoId == tc->id()) return 1;
+  int nMember = memberCount();
+  if (nMember != ((TypeCodeStruct*)tc)->memberCount()) return 0;
+  for (int i=0 ; i<nMember ; i++)
+    {
+      const char * name = memberName(i);
+      if (strcmp(memberName(i), ((TypeCodeStruct*)tc)->memberName(i)) != 0) return 0;
+      if (!memberType(i)->isAdaptable(((TypeCodeStruct*)tc)->memberType(i))) return 0;
+    }
+  return 1;
+}
+
+//! Check if this TypeCode can be used in place of tc
+/*!
+ * this TypeCode is equivalent to tc if they have the same kind
+ *
+ *   \param tc : the TypeCode to compare
+ */
+int TypeCodeStruct::isEquivalent(const TypeCode* tc) const 
+{
+  if(_kind != tc->kind()) return 0;
+  int nMember=memberCount();
+  if(nMember != ((TypeCodeStruct*)tc)->memberCount())return 0;
+  for(int i=0;i<nMember;i++)
+    {
+       const char * name=memberName(i);
+       if(strcmp(memberName(i),((TypeCodeStruct*)tc)->memberName(i)) != 0)return 0;
+       if(!memberType(i)->isEquivalent(((TypeCodeStruct*)tc)->memberType(i)))return 0;
+    }
+  return 1;
 }
 
 void TypeCodeStruct::addMember(const std::string& name,TypeCode* tc)
@@ -636,6 +762,27 @@ void TypeCodeStruct::addMember(const std::string& name,TypeCode* tc)
         throw Exception("Struct member " + name + " already defined");
     }
   _members.push_back(std::pair<std::string,TypeCode*>(name,tc));
+  tc->incrRef();
+}
+
+//! Get typecode of struct member given its name
+/*!
+ * If name is not an existing key, 0 is returned.
+ * \param name : the member name
+ * \param offset : Out parameter, that specified the location of start of data discriminated by name key.
+ * \return the member TypeCode
+ */
+const TypeCode *TypeCodeStruct::getMember(const std::string& name, unsigned& offset) const
+{
+  std::vector< std::pair<std::string,TypeCode*> >::const_iterator iter;
+  offset=0;
+  for(iter=_members.begin();iter != _members.end(); iter++)
+    {
+      if((*iter).first==name)
+        return (*iter).second;
+      offset+=(*iter).second->getSizeInByteOfAnyReprInSeq();
+    }
+  return 0;
 }
 
 int TypeCodeStruct::memberCount() const