Salome HOME
Cleaning before merge to master.
[modules/yacs.git] / src / runtime / TypeConversions.cxx
index adabc6439d53812e5010cc5952c6f125b0099aaa..fd883aa099d87f454098913d04b6c528640768ad 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2006-2016  CEA/DEN, EDF R&D
+// Copyright (C) 2006-2020  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
@@ -618,8 +618,10 @@ namespace YACS
     inline TOUT convertObjref(const TypeCode *t,TIN o,TIN2 aux)
     {
       int protocol=-1;
-      if(IMPLOUT==XMLImpl || IMPLOUT==NEUTRALImpl)
-        protocol=0;
+      if(IMPLOUT==XMLImpl)
+        protocol=0;//to avoid presence of \0 into XML generated file
+      if(IMPLOUT==NEUTRALImpl)
+        protocol=4;
       std::string d=convertToYacsObjref<IMPLIN,TIN,TIN2,IMPLOUT,TOUT>::convert(t,o,aux,protocol);
       DEBTRACE( d );
       TOUT r=convertFromYacsObjref<IMPLOUT,TOUT>::convert(t,d);
@@ -740,7 +742,7 @@ namespace YACS
           if (PyUnicode_Check(o))
             {
               Py_ssize_t size;
-              char *ptr = PyUnicode_AsUTF8AndSize(o, &size);
+              const char *ptr = PyUnicode_AsUTF8AndSize(o, &size);
               if (!ptr)
                 throw YACS::ENGINE::ConversionException("Conversion from PyUnicode to string failed");
               s.assign(ptr, size);
@@ -791,7 +793,7 @@ namespace YACS
               // the objref is used by Python as a string (prefix:value) keep it as a string
               Py_ssize_t size;
               std::string s;
-              char *ptr = PyUnicode_AsUTF8AndSize(o, &size);
+              const char *ptr = PyUnicode_AsUTF8AndSize(o, &size);
               if (!ptr)
                 throw YACS::ENGINE::ConversionException("Conversion from PyUnicode to string failed");
               s.assign(ptr, size);
@@ -844,7 +846,7 @@ namespace YACS
                 }
               Py_ssize_t size;
               std::string mystr;
-              char *ptr = PyUnicode_AsUTF8AndSize(pystring, &size);
+              const char *ptr = PyUnicode_AsUTF8AndSize(pystring, &size);
               if (!ptr)
                 throw YACS::ENGINE::ConversionException("Conversion from PyUnicode to string failed");
               mystr.assign(ptr, size);
@@ -991,11 +993,11 @@ namespace YACS
               //It's an objref file. Convert it specially
               return PyUnicode_FromString(o.c_str());
             }
-          if(strncmp(t->id(),"python",6)==0)
+          if(strncmp(t->id(),"python",6)==0) //ex: "python:obj:1.0"
             {
               //It's a python pickled object, unpickled it
               PyObject* mod=PyImport_ImportModule("pickle");
-              PyObject *ob=PyObject_CallMethod(mod,(char *)"loads",(char *)"s#",o.c_str(),o.length());
+              PyObject *ob=PyObject_CallMethod(mod,(char *)"loads",(char *)"y#",o.c_str(),o.length());
               DEBTRACE(PyObject_Repr(ob));
               Py_DECREF(mod);
               if(ob==NULL)
@@ -1014,7 +1016,7 @@ namespace YACS
                   PyErr_Print();
                   throw YACS::ENGINE::ConversionException("Problem in convertToYacsObjref<PYTHONImpl: no simplejson module");
                 }
-              PyObject *ob=PyObject_CallMethod(mod,(char *)"loads",(char *)"s",o.c_str());
+              PyObject *ob=PyObject_CallMethod(mod,(char *)"loads",(char *)"y",o.c_str());
               Py_DECREF(mod);
               if(ob==NULL)
                 {
@@ -1326,7 +1328,10 @@ namespace YACS
                     {
                       DEBTRACE("############### workaround to improve...");
                     }
-                  return mystr;
+                  if(strncmp(t->id(),"python",6)==0 )
+                    return FromBase64Safe(mystr);
+                  else
+                    return mystr;
                 }
               else if ((!xmlStrcmp(cur->name, (const xmlChar *)"string")))// <- here case where pyobj value has been stored in XML. pyobj has kind==ObjRef. And the stored format is String ! EDF11027
                 {
@@ -1496,7 +1501,7 @@ namespace YACS
       static inline std::string convert(const TypeCode *t,std::string& o)
         {
           if(strncmp(t->id(),"python",6)==0 )
-            return "<value><objref><![CDATA[" + o + "]]></objref></value>\n";
+            return "<value><objref><![CDATA[" + ToBase64(o) + "]]></objref></value>\n";
           else if(strncmp(t->id(),"json",4)==0)
             return "<value><objref><![CDATA[" + o + "]]></objref></value>\n";
           else
@@ -1611,7 +1616,7 @@ namespace YACS
     {
       static inline std::string convert(const TypeCode *t,YACS::ENGINE::Any* o,void*,int protocol)
         {
-          if(o->getType()->kind()==String)
+          if(o->getType()->kind()==String || o->getType()->kind()==Objref)
             return o->getStringValue();
           stringstream msg;
           msg << "Problem in conversion: a objref(string) is expected " ;
@@ -1697,7 +1702,7 @@ namespace YACS
         {
           //Check if objref is a GenericObj and register it if it is the case (workaround for bad management of GenericObj)
           if(o=="" || (t->isA(Runtime::_tc_file)) || (strncmp(t->id(),"python",6)==0) || (strncmp(t->id(),"json",4)==0))
-            return YACS::ENGINE::AtomAny::New(o);
+            return YACS::ENGINE::AtomAny::New(o, const_cast<TypeCode *>(t));
 
           //Objref CORBA. prefix=IOR,corbaname,corbaloc
           CORBA::Object_var obref;
@@ -1731,7 +1736,7 @@ namespace YACS
           else
               DEBTRACE("It's a CORBA::Object but not a SALOME::GenericObj");
 
-          return YACS::ENGINE::AtomAny::New(o);
+          return YACS::ENGINE::AtomAny::New(o, const_cast<TypeCode *>(t));
         }
     };
 
@@ -1868,7 +1873,7 @@ namespace YACS
                 {
                   s=(const char*)buffer->get_buffer();
 
-                  if(protocol !=0)
+                  if(protocol !=4)
                     {
                       std::string mystr(s,buffer->length());
                       return mystr;
@@ -1876,7 +1881,7 @@ namespace YACS
 
                   PyGILState_STATE gstate = PyGILState_Ensure(); 
                   PyObject* mod=PyImport_ImportModule("pickle");
-                  PyObject *ob=PyObject_CallMethod(mod,(char *)"loads",(char *)"s#",s,buffer->length());
+                  PyObject *ob=PyObject_CallMethod(mod,(char *)"loads",(char *)"y#",s,buffer->length());
                   PyObject *pickled=PyObject_CallMethod(mod,(char *)"dumps",(char *)"Oi",ob,protocol);
                   DEBTRACE(PyObject_Repr(pickled));
                   std::string mystr=PyBytes_AsString(pickled);
@@ -2301,8 +2306,17 @@ namespace YACS
     {
       PyObject *s;
       PyGILState_STATE gstate = PyGILState_Ensure(); 
+      // TODO: separate treatment for string (maybe with bad encoding?) and other types of PyObject ?
+      // Do we need str() or repr() and what are the possible causes of failure of str() ?
+      // not clear, needs more analysis.
       s=PyObject_Str(ob);
-      std::string ss(PyBytes_AsString(s),PyBytes_Size(s));
+      if (s == NULL) // for instance string with bad encoding, non utf-8
+      {
+       s=PyObject_ASCII(ob); // escape non ASCII characters and like repr(), which is not the same as str()...
+      }
+      Py_ssize_t size;
+      const char* characters =  PyUnicode_AsUTF8AndSize(s, &size);
+      std::string ss( characters, size);
       Py_DECREF(s);
       PyGILState_Release(gstate);
       return ss;