Salome HOME
Merge branch 'V9_2_2_BR'
[modules/yacs.git] / src / engine / Any.cxx
index e77a310fce86f0aea441a6d7409da1f7cb20dfcc..37e24f11ce73be44ed654778cb6085d209c7db21 100644 (file)
@@ -1,29 +1,62 @@
+// Copyright (C) 2006-2019  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 "Any.hxx"
 #include "Runtime.hxx"
 #include "TypeCode.hxx"
 #include "InvalidExtractionException.hxx"
 
 #include <cstring>
+#include <cstdlib>
 
 using namespace YACS::ENGINE;
 using namespace std;
 
-StringOnHeap::StringOnHeap(const char *val):_dealloc(0),_str(strdup(val))
+// forbidden value int=-269488145 double=-1.54947e+231 bool=239
+const char SeqAlloc::DFT_CHAR_VAR=-17;//0xEF
+
+StringOnHeap::StringOnHeap(const char *val):_str(strdup(val)),_len(strlen(val)),_dealloc(0)
+{
+}
+
+StringOnHeap::StringOnHeap(const char *val, std::size_t len):_dealloc(0),_len(len)
 {
+  _str=(char *)malloc(len+1);
+  std::copy(val,val+len,_str);
+  _str[len]='\0';
 }
 
-StringOnHeap::StringOnHeap(const std::string& val):_dealloc(0),_str(strdup(val.c_str()))
+StringOnHeap::StringOnHeap(const std::string& val):_dealloc(0),_len(val.size()),_str(nullptr)
 {
+  _str=(char *)malloc(val.size()+1);
+  std::copy(val.cbegin(),val.cend(),_str);
+  _str[val.size()]='\0';
 }
 
 /*! 
- * \Note : no copy is performed if a deallocator is given.
+ * \note : no copy is performed if a deallocator is given.
  * \param val     : String in C format that is NOT copied if
  *                  deAlloc != 0
  * \param deAlloc : pointer on function to deallocate val after
  *                  last use.
  */
-StringOnHeap::StringOnHeap(char *val, Deallocator deAlloc):_dealloc(deAlloc)
+StringOnHeap::StringOnHeap(char *val, Deallocator deAlloc):_len(0),_dealloc(deAlloc)
 {
   if(deAlloc)
     _str=val;
@@ -38,7 +71,10 @@ bool StringOnHeap::operator ==(const StringOnHeap& other) const
 
 StringOnHeap *StringOnHeap::deepCopy() const
 {
-  return new StringOnHeap(_str);
+  if(_len==0)
+    return new StringOnHeap(_str);
+  else
+    return new StringOnHeap(_str,_len);
 }
 
 StringOnHeap::~StringOnHeap()
@@ -64,6 +100,16 @@ Any::~Any()
   _type->decrRef();
 }
 
+bool Any::IsNull(char *data)
+{
+  if(!data)
+    return true;
+  bool isNull(true);
+  for(std::size_t i=0;i<sizeof(void *) && isNull;i++)
+    isNull=(data[i]==SeqAlloc::DFT_CHAR_VAR);
+  return isNull;
+}
+
 AtomAny::AtomAny(int val):Any(Runtime::_tc_int)
 {
   _value._i=val;
@@ -135,11 +181,16 @@ AtomAny *AtomAny::New(char *val,Deallocator dealloc)
   return new AtomAny(val,dealloc);
 }
 
-AnyPtr AtomAny::operator[](int i) const
+AnyPtr AtomAny::operator[](int i) const throw(YACS::Exception)
 {
   throw InvalidExtractionException(_type->kind(),Sequence);
 }
 
+AnyPtr AtomAny::operator[](const char *key) const throw(YACS::Exception)
+{
+  throw Exception("AtomAny::operator[] : try to get a part of a partitionned data whereas atomical.");
+}
+
 bool AtomAny::operator ==(const Any& other) const
 {
   if(!_type->isA(other.getType()))
@@ -157,36 +208,53 @@ bool AtomAny::operator ==(const Any& other) const
     return false;
 }
 
-int AtomAny::getIntValue() const throw(Exception)
+int AtomAny::getIntValue() const throw(YACS::Exception)
 {
   if(_type->isA(Runtime::_tc_int))
     return _value._i;
   else
-    throw Exception("Value is not an Int");
+    throw Exception("Value is not an int");
 }
 
-bool AtomAny::getBoolValue() const throw(Exception)
+bool AtomAny::getBoolValue() const throw(YACS::Exception)
 {
   if(_type->isA(Runtime::_tc_bool))
     return _value._b;
   else
-    throw Exception("Value is not a Bool");
+    throw Exception("Value is not a bool");
 }
 
-double AtomAny::getDoubleValue() const throw(Exception)
+double AtomAny::getDoubleValue() const throw(YACS::Exception)
 {
   if(_type->isA(Runtime::_tc_double))
     return _value._d;
   else
-    throw Exception("Value is not a Double");
+    throw Exception("Value is not a double");
+}
+
+std::string AtomAny::getStringValue() const throw(YACS::Exception)
+{
+  if(_type->isA(Runtime::_tc_string))
+    {
+      std::size_t sz(_value._s->size());
+      if(sz==0)
+        return string(_value._s->cStr());
+      else
+        return string(_value._s->cStr(),sz);
+    }
+  else
+    throw Exception("Value is not a string");
 }
 
-std::string AtomAny::getStringValue() const throw(Exception)
+const char *AtomAny::getBytesValue(std::size_t& len) const
 {
   if(_type->isA(Runtime::_tc_string))
-    return string(_value._s->cStr());
+    {
+      len=_value._s->size();
+      return _value._s->cStr();
+    }
   else
-    throw Exception("Value is not a String");
+    throw Exception("Value is not a string");
 }
 
 /*!
@@ -218,6 +286,9 @@ void AtomAny::putMyReprAtPlace(char *data) const
  *         For memory space minimal use, not all of '*this' is pushed at data location.
  *         'deepCpy' param is not used here because by definition of AtomAny deep copy is performed.
  * \param data : already allocated memory zone where to put compressed content of 'this'
+ * \param src :
+ * \param type :
+ * \param deepCpy :
  */
 void AtomAny::putReprAtPlace(char *data, const char *src, const TypeCode *type, bool deepCpy)
 {
@@ -244,8 +315,11 @@ void AtomAny::destroyReprAtPlace(char *data, const TypeCode *type)
   DynType typ=type->kind();
   if(typ==String)
     {
-      void **tmp=(void **)data;
-      delete ((StringOnHeap *)(*tmp));
+      if(!Any::IsNull(data))
+        {
+          void **tmp=(void **)data;
+          delete ((StringOnHeap *)(*tmp));
+        }
     }
 }
 
@@ -264,7 +338,7 @@ bool AtomAny::takeInChargeStorageOf(TypeCode *type)
 
 AtomAny::~AtomAny()
 {
-  if(_type->isA(Runtime::_tc_string))
+  if(_type->kind() == String)
     delete _value._s;
 }
 
@@ -272,27 +346,39 @@ ComposedAny::ComposedAny(const ComposedAny& other):Any(other)
 {
 }
 
-ComposedAny::ComposedAny(TypeCode* type):Any(type)
+ComposedAny::ComposedAny(TypeCode* type, bool isNew):Any(type)
 {
-  _type->decrRef();
+  if(isNew)
+    _type->decrRef();
+}
+
+AnyPtr ComposedAny::operator[](const char *key) const throw(YACS::Exception)
+{
+  throw Exception("AtomAny::operator[] : try to get a part of a partitionned data not localizable by a string.");
+}
+
+void ComposedAny::checkTypeOf(const Any *elem) const throw(YACS::Exception)
+{
+  if(!elem->getType()->isA(_type->contentType()))
+    throw Exception("ComposedAny::checkTypeOf : invalid type.");
 }
 
-int ComposedAny::getIntValue() const throw(Exception)
+int ComposedAny::getIntValue() const throw(YACS::Exception)
 {
  throw InvalidExtractionException(_type->kind(),Runtime::_tc_int->kind());
 }
 
-bool ComposedAny::getBoolValue() const throw(Exception)
+bool ComposedAny::getBoolValue() const throw(YACS::Exception)
 {
   throw InvalidExtractionException(_type->kind(),Runtime::_tc_bool->kind());
 }
 
-double ComposedAny::getDoubleValue() const throw(Exception)
+double ComposedAny::getDoubleValue() const throw(YACS::Exception)
 {
   throw InvalidExtractionException(_type->kind(),Runtime::_tc_double->kind());
 }
 
-std::string ComposedAny::getStringValue() const throw(Exception)
+std::string ComposedAny::getStringValue() const throw(YACS::Exception)
 {
   throw InvalidExtractionException(_type->kind(),Runtime::_tc_string->kind());
 }
@@ -342,7 +428,7 @@ void SeqAlloc::initCoarseMemory(char *mem, unsigned int size, Deallocator deallo
         memcpy(_start,mem,sizeInByte);
       else
         {
-          for(unsigned int i=0;i<sizeInByte;i++) _start[i]=0;
+          for(unsigned int i=0;i<sizeInByte;i++) _start[i]=DFT_CHAR_VAR;// see getSetItems
         }
     }
   _finish=_start+sizeInByte;
@@ -356,7 +442,9 @@ void SeqAlloc::construct(char *pt, const Any *val)
 
 /*!
  * \note: This performs the placement new or zip info into pt.
+ * \param pt :
  * \param val     : the source from which the construction will be performed.
+ * \param tc  :
  * \param deepCpy : If true in pt place a deep copy pointed by val will be put.
  */
 void SeqAlloc::construct(char *pt, const char *val, const TypeCode *tc, bool deepCpy)
@@ -397,6 +485,20 @@ unsigned int SeqAlloc::size() const
   return (_finish-_start)/_sizeOf1Elm;
 }
 
+std::vector<unsigned int> SeqAlloc::getSetItems() const
+{
+  std::vector<unsigned int> ret;
+  unsigned int sz(size());
+  for(unsigned int i=0;i<sz;i++)
+    {
+      const char *pt(_start+i*_sizeOf1Elm);
+      for(unsigned j=0;j<_sizeOf1Elm && *pt==DFT_CHAR_VAR;j++,pt++); //see initCoarseMemory
+      if(pt!=_start+(i+1)*_sizeOf1Elm)
+        ret.push_back(i);
+    }
+  return ret;
+}
+
 void SequenceAny::clear()
 {
   for (char *cur=_alloc._start;cur!=_alloc._finish;cur+=_alloc._sizeOf1Elm)
@@ -436,13 +538,14 @@ bool SequenceAny::operator ==(const Any& other) const
   return true;
 }
 
-void SequenceAny::setEltAtRank(int i, const Any *elem)
+void SequenceAny::setEltAtRank(int i, const Any *elem) throw(YACS::Exception)
 {
+  checkTypeOf(elem);
   _alloc.destroy(_alloc._start+i*_alloc._sizeOf1Elm,_type->contentType());
   _alloc.construct(_alloc._start+i*_alloc._sizeOf1Elm,elem);
 }
 
-AnyPtr SequenceAny::operator[](int i) const
+AnyPtr SequenceAny::operator[](int i) const throw(YACS::Exception)
 {
   return _type->contentType()->getOrBuildAnyFromZippedData(_alloc._start+i*_alloc._sizeOf1Elm);
 }
@@ -479,7 +582,7 @@ void SequenceAny::putReprAtPlace(char *data, const char *src, const TypeCode *ty
 void SequenceAny::destroyReprAtPlace(char *data, const TypeCode *type)
 {
   void **tmp=(void **) data;
-  if(*tmp)
+  if(!Any::IsNull(data))
     ((SequenceAny *)(*tmp))->decrRef();
   //((SequenceAny *)data)->~SequenceAny();
 }
@@ -496,6 +599,19 @@ Any *SequenceAny::clone() const
   return new SequenceAny(*this);
 }
 
+SequenceAny *SequenceAny::removeUnsetItemsFromThis() const
+{
+  std::vector<unsigned int> its(getSetItems());
+  std::size_t sz(its.size());
+  SequenceAny *ret(SequenceAny::New(getType()->contentType(),sz));
+  for(std::size_t i=0;i<sz;i++)
+    {
+      AnyPtr obj((*this)[its[i]]);
+      ret->setEltAtRank(i,obj);
+    }
+  return ret;
+}
+
 SequenceAny *SequenceAny::New(const TypeCode *typeOfContent)
 {
   if(typeOfContent->kind() == Objref)
@@ -630,16 +746,29 @@ char *SequenceAny::performCpy(char *srcStart, char *srcFinish, char *destStart)
 
 ArrayAny::~ArrayAny()
 {
+  const TypeCode *subType=_type->contentType();
+  unsigned sizePerContent=subType->getSizeInByteOfAnyReprInSeq();
+  unsigned int size=((TypeCodeArray *)_type)->getStaticLgth();
+  char *tmp=_data;
+  for(unsigned i=0;i<size;i++,tmp+=sizePerContent)
+    subType->destroyZippedAny(tmp);
   delete [] _data;
 }
 
-ArrayAny::ArrayAny(char *data, TypeCodeArray * type):ComposedAny(type),_data(0)
+ArrayAny::ArrayAny(const TypeCode *typeOfContent, unsigned int lgth):ComposedAny(new TypeCodeArray("","",typeOfContent,lgth))
+{
+  _data=new char[_type->getSizeInByteOfAnyReprInSeq()];
+  for(unsigned int i=0;i<_type->getSizeInByteOfAnyReprInSeq();i++)
+    _data[i]=SeqAlloc::DFT_CHAR_VAR;
+}
+
+ArrayAny::ArrayAny(char *data, TypeCodeArray * type):ComposedAny(type,false),_data(0)
 {
   _data=new char[_type->getSizeInByteOfAnyReprInSeq()];
   const TypeCode *subType=_type->contentType();
   unsigned sizePerContent=subType->getSizeInByteOfAnyReprInSeq();
   for(unsigned i=0;i<type->getStaticLgth();i++)
-    subType->putReprAtPlace(_data+i*sizePerContent,data+i*sizePerContent,true);
+    subType->putReprAtPlace(_data+i*sizePerContent,data+i*sizePerContent,false);
 }
 
 ArrayAny::ArrayAny(const ArrayAny& other):ComposedAny(other)
@@ -700,6 +829,14 @@ ArrayAny::ArrayAny(const std::vector<std::string>& val):ComposedAny(new TypeCode
     }
 }
 
+void ArrayAny::setEltAtRank(int i, const Any *elem) throw(YACS::Exception)
+{
+  checkTypeOf(elem);
+  const TypeCode *subType=_type->contentType();
+  subType->destroyZippedAny(_data+i*subType->getSizeInByteOfAnyReprInSeq());
+  elem->putMyReprAtPlace(_data+i*subType->getSizeInByteOfAnyReprInSeq());
+}
+
 bool ArrayAny::operator ==(const Any& other) const
 {
   if(!_type->isA(other.getType()))
@@ -711,13 +848,18 @@ bool ArrayAny::operator ==(const Any& other) const
   return true;
 }
 
-AnyPtr ArrayAny::operator[](int i) const
+AnyPtr ArrayAny::operator[](int i) const throw(YACS::Exception)
 {
   const TypeCode *subType=_type->contentType();
   unsigned sizePerContent=subType->getSizeInByteOfAnyReprInSeq();
   if(i<0 || i>=((TypeCodeArray *)_type)->getStaticLgth())
     throw Exception("Trying to access to an invalid index in an Any Tuple");
-  return _type->getOrBuildAnyFromZippedData(_data+i*sizePerContent);
+  return _type->contentType()->getOrBuildAnyFromZippedData(_data+i*sizePerContent);
+}
+
+unsigned int ArrayAny::size() const
+{
+  return ((TypeCodeArray *)_type)->getStaticLgth();
 }
 
 Any *ArrayAny::clone() const
@@ -725,6 +867,11 @@ Any *ArrayAny::clone() const
   return new ArrayAny(*this);
 }
 
+ArrayAny *ArrayAny::New(const TypeCode *typeOfContent, unsigned int lgth)
+{
+  return new ArrayAny(typeOfContent,lgth);
+}
+
 void ArrayAny::putMyReprAtPlace(char *data) const
 {
   const TypeCode *subType=_type->contentType();
@@ -752,7 +899,6 @@ void ArrayAny::destroyReprAtPlace(char *data, const TypeCodeArray *type)
 AnyPtr ArrayAny::getOrBuildFromData(char *data, const TypeCodeArray *type)
 {
   Any *ret;
-  type->incrRef();
   ret=new ArrayAny(data,(TypeCodeArray *)type);
   return AnyPtr(ret);
 }
@@ -762,3 +908,154 @@ bool ArrayAny::takeInChargeStorageOf(TypeCode *type)
   DynType typ=type->kind();
   return (typ==Array);
 }
+
+Any *StructAny::clone() const
+{
+  return new StructAny(*this);
+}
+
+bool StructAny::operator ==(const Any& other) const
+{
+  if(!_type->isA(other.getType()))
+    return false;
+  const TypeCodeStruct *typeC=(const TypeCodeStruct *)_type;
+  vector< pair<string,TypeCode*> >::const_iterator iter;
+  for(iter=typeC->_members.begin();iter!=typeC->_members.end();iter++)
+    if(!((*(*this)[(*iter).first.c_str()]==(*other[(*iter).first.c_str()]))))
+      return false;
+  return true;
+}
+
+AnyPtr StructAny::operator[](int i) const throw(YACS::Exception)
+{
+  const char what[]="StructAny::operator[](int i) : Struct key are strings not integers.";
+  throw Exception(what);
+}
+
+AnyPtr StructAny::operator[](const char *key) const throw(YACS::Exception)
+{
+  const TypeCodeStruct *typeC=(const TypeCodeStruct *)_type;
+  char *whereToGet=_data;
+  vector< pair<string,TypeCode*> >::const_iterator iter;
+  for(iter=typeC->_members.begin();iter!=typeC->_members.end();iter++)
+    if((*iter).first!=key)
+      whereToGet+=(*iter).second->getSizeInByteOfAnyReprInSeq();
+    else
+      break;
+  if(iter==typeC->_members.end())
+    {
+      string what("Unexisting key \""); what+=key; what+="\" for struct extraction.";
+      throw Exception(what);
+    }
+  return (*iter).second->getOrBuildAnyFromZippedData(whereToGet);
+}
+
+void StructAny::setEltAtRank(int i, const Any *elem) throw(YACS::Exception)
+{
+  const char what[]="Struct key are strings not integers.";
+  throw Exception(what);
+}
+
+void StructAny::setEltAtRank(const char *key, const Any *elem) throw(YACS::Exception)
+{
+  const TypeCodeStruct *typeC=(const TypeCodeStruct *)_type;
+  unsigned offset;
+  const TypeCode *tcOnKey=typeC->getMember(key,offset);
+  if(!tcOnKey)
+    throw Exception("StructAny::setEltAtRank : invalid key given.");
+  if(!elem->getType()->isA(tcOnKey))
+    throw Exception("StructAny::setEltAtRank : invalid data type on the specified given key.");
+  tcOnKey->destroyZippedAny(_data+offset);
+  elem->putMyReprAtPlace(_data+offset);
+}
+
+void StructAny::putMyReprAtPlace(char *data) const
+{
+  const TypeCodeStruct *typeC=(const TypeCodeStruct *)_type;
+  unsigned offset=0;
+  vector< pair<string,TypeCode*> >::const_iterator iter;
+  for(iter=typeC->_members.begin();iter!=typeC->_members.end();iter++)
+    {
+      (*iter).second->putReprAtPlace(data+offset,_data+offset,false);
+      offset+=(*iter).second->getSizeInByteOfAnyReprInSeq();
+    }
+}
+
+void StructAny::putReprAtPlace(char *data, const char *src, const TypeCodeStruct *type, bool deepCpy)
+{
+  unsigned offset=0;
+  vector< pair<string,TypeCode*> >::const_iterator iter;
+  for(iter=type->_members.begin();iter!=type->_members.end();iter++)
+    {
+      (*iter).second->putReprAtPlace(data+offset,src+offset,deepCpy);
+      offset+=(*iter).second->getSizeInByteOfAnyReprInSeq();
+    }
+}
+
+void StructAny::destroyReprAtPlace(char *data, const TypeCodeStruct *type)
+{
+  char *whereToGet=data;
+  vector< pair<string,TypeCode*> >::const_iterator iter;
+  for(iter=type->_members.begin();iter!=type->_members.end();iter++)
+    {
+      (*iter).second->destroyZippedAny(whereToGet);
+      whereToGet+=(*iter).second->getSizeInByteOfAnyReprInSeq();
+    }
+}
+
+AnyPtr StructAny::getOrBuildFromData(char *data, const TypeCodeStruct *type)
+{
+  Any *ret;
+  ret=new StructAny(data,(TypeCodeStruct *)type);
+  return AnyPtr(ret);
+}
+
+StructAny::~StructAny()
+{
+  const TypeCodeStruct *typeC=(const TypeCodeStruct *)_type;
+  vector< pair<string,TypeCode*> >::const_iterator iter;
+  char *whereToGet=_data;
+  for(iter=typeC->_members.begin();iter!=typeC->_members.end();iter++)
+    {
+      (*iter).second->destroyZippedAny(whereToGet);
+      whereToGet+=(*iter).second->getSizeInByteOfAnyReprInSeq();
+    }
+  delete [] _data;
+}
+
+StructAny::StructAny(TypeCodeStruct *type):ComposedAny(type,false)
+{
+  _data=new char[_type->getSizeInByteOfAnyReprInSeq()];
+  for(unsigned int i=0;i<_type->getSizeInByteOfAnyReprInSeq();i++)
+    _data[i]=SeqAlloc::DFT_CHAR_VAR;
+}
+
+StructAny::StructAny(const StructAny& other):ComposedAny(other)
+{
+  _data=new char[_type->getSizeInByteOfAnyReprInSeq()];
+  const TypeCodeStruct *typeC=(const TypeCodeStruct *)_type;
+  vector< pair<string,TypeCode*> >::const_iterator iter;
+  unsigned offset=0;
+  for(iter=typeC->_members.begin();iter!=typeC->_members.end();iter++)
+    {
+     (*iter).second->putReprAtPlace(_data+offset,other._data+offset,true);
+     offset+=(*iter).second->getSizeInByteOfAnyReprInSeq();
+    }
+}
+
+StructAny::StructAny(char *data, TypeCodeStruct * type):ComposedAny(type,false),_data(0)
+{
+  _data=new char[_type->getSizeInByteOfAnyReprInSeq()];
+  vector< pair<string,TypeCode*> >::const_iterator iter;
+  unsigned offset=0;
+  for(iter=type->_members.begin();iter!=type->_members.end();iter++)
+    {
+      (*iter).second->putReprAtPlace(_data+offset,data+offset,false);
+      offset+=(*iter).second->getSizeInByteOfAnyReprInSeq();
+    }
+}
+
+StructAny *StructAny::New(TypeCodeStruct *type)
+{
+  return new StructAny(type);
+}