From b4851bcd05cfc08d1a59e87f9e2a0b17bb94639b Mon Sep 17 00:00:00 2001 From: Anthony Geay Date: Tue, 14 May 2019 13:58:36 +0200 Subject: [PATCH] base64 is used to store pickelized objects into XML --- src/engine/Any.cxx | 50 +++++++++++++++++++++ src/engine/Any.hxx | 4 ++ src/engine/CMakeLists.txt | 3 ++ src/engine/ForEachLoop.cxx | 4 +- src/runtime/TypeConversions.cxx | 7 ++- src/yacsloader_swig/Test/testSaveLoadRun.py | 2 +- 6 files changed, 65 insertions(+), 5 deletions(-) diff --git a/src/engine/Any.cxx b/src/engine/Any.cxx index 37e24f11c..70458bddc 100644 --- a/src/engine/Any.cxx +++ b/src/engine/Any.cxx @@ -22,6 +22,13 @@ #include "TypeCode.hxx" #include "InvalidExtractionException.hxx" +#include +#include +#include +#include +#include + +#include #include #include @@ -31,6 +38,49 @@ using namespace std; // forbidden value int=-269488145 double=-1.54947e+231 bool=239 const char SeqAlloc::DFT_CHAR_VAR=-17;//0xEF +std::string YACS::ENGINE::ToBase64(const std::string& bytes) +{ + std::string input(bytes); + // The input must be in multiples of 3, otherwise the transformation + // may overflow the input buffer, so pad with zero. + size_t num_pad_chars((3 - input.size() % 3) % 3); + input.append(num_pad_chars, 0); + + // Transform to Base64 with line breaks every 76 characters + using namespace boost::archive::iterators; + typedef insert_linebreaks >, 76> ItBase64T; + std::string output(ItBase64T(input.begin()), ItBase64T(input.end() - num_pad_chars)); + + // Pad blank characters with '=' + output.append(num_pad_chars, '='); + + return output; +} + +std::string YACS::ENGINE::FromBase64(const std::string& base64Str) +{ + std::string input(base64Str); + using namespace boost::archive::iterators; + typedef transform_width >, 8, 6> ItBinaryT; + + try + { + // If the input isn't a multiple of 4, pad with = + size_t num_pad_chars((4 - input.size() % 4) % 4); + input.append(num_pad_chars, '='); + + size_t pad_chars(std::count(input.begin(), input.end(), '=')); + std::replace(input.begin(), input.end(), '=', 'A'); + std::string output(ItBinaryT(input.begin()), ItBinaryT(input.end())); + output.erase(output.end() - pad_chars, output.end()); + return output; + } + catch (std::exception const&) + { + return std::string(); + } +} + StringOnHeap::StringOnHeap(const char *val):_str(strdup(val)),_len(strlen(val)),_dealloc(0) { } diff --git a/src/engine/Any.hxx b/src/engine/Any.hxx index 026bd29d8..e09064e9a 100644 --- a/src/engine/Any.hxx +++ b/src/engine/Any.hxx @@ -42,6 +42,10 @@ namespace YACS class TypeCodeStruct; typedef void (*Deallocator)(void *); + + YACSLIBENGINE_EXPORT std::string ToBase64(const std::string& bytes); + YACSLIBENGINE_EXPORT std::string FromBase64(const std::string& bytes); + class YACSLIBENGINE_EXPORT StringOnHeap { friend class Any; diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt index e884eaa8a..630781421 100644 --- a/src/engine/CMakeLists.txt +++ b/src/engine/CMakeLists.txt @@ -23,6 +23,9 @@ IF(SALOME_BUILD_TESTS) ENDIF(SALOME_BUILD_TESTS) # --- options --- +ADD_DEFINITIONS( + ${BOOST_DEFINITIONS} + ) # additional include directories INCLUDE_DIRECTORIES( diff --git a/src/engine/ForEachLoop.cxx b/src/engine/ForEachLoop.cxx index 4605bbada..b3d87fdfa 100644 --- a/src/engine/ForEachLoop.cxx +++ b/src/engine/ForEachLoop.cxx @@ -180,7 +180,7 @@ std::string SeqAnyInputPort::dump() for (int i = 0; i < nbElem; i++) { Any *val = getValueAtRank(i); - switch (val->getType()->kind()) + switch (((YACS::ENGINE::TypeCodeSeq *)edGetType())->contentType()->kind()) { case Double: xmldump << "" << setprecision(16) << val->getDoubleValue() << "" << endl; @@ -195,7 +195,7 @@ std::string SeqAnyInputPort::dump() xmldump << "" << val->getStringValue() << "" << endl; break; case Objref: - xmldump << "" << val->getStringValue() << "" << endl; + xmldump << "" << ToBase64(val->getStringValue()) << "" << endl; break; default: xmldump << " NO_SERIALISATION_AVAILABLE " << endl; diff --git a/src/runtime/TypeConversions.cxx b/src/runtime/TypeConversions.cxx index a3da28270..3143d4366 100644 --- a/src/runtime/TypeConversions.cxx +++ b/src/runtime/TypeConversions.cxx @@ -1328,7 +1328,10 @@ namespace YACS { DEBTRACE("############### workaround to improve..."); } - return mystr; + if(strncmp(t->id(),"python",6)==0 ) + return FromBase64(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 { @@ -1498,7 +1501,7 @@ namespace YACS static inline std::string convert(const TypeCode *t,std::string& o) { if(strncmp(t->id(),"python",6)==0 ) - return "\n"; + return "\n"; else if(strncmp(t->id(),"json",4)==0) return "\n"; else diff --git a/src/yacsloader_swig/Test/testSaveLoadRun.py b/src/yacsloader_swig/Test/testSaveLoadRun.py index 12cddf687..5c2e755fe 100755 --- a/src/yacsloader_swig/Test/testSaveLoadRun.py +++ b/src/yacsloader_swig/Test/testSaveLoadRun.py @@ -1171,7 +1171,7 @@ for i in i8: self.assertEqual(p.getState(),pilot.DONE) pass - def tess14(self): + def test14(self): """ Non regression EDF11027. Problem after Save/Load of a foreach node with type pyobj with input "SmplsCollection" manually set before. Correction in convertToYacsObjref from XML->Neutral. Objref can hide a string !""" xmlFileName="test14.xml" SALOMERuntime.RuntimeSALOME_setRuntime() -- 2.39.2