Belle II Software  release-08-01-10
Stream.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 #include <framework/utilities/Stream.h>
9 
10 #include <framework/logging/Logger.h>
11 
12 #include <TBase64.h>
13 #include <TObject.h>
14 #include <TMessage.h>
15 
16 #include <boost/algorithm/string/replace.hpp>
17 
18 using namespace Belle2;
19 
20 namespace {
22  class StreamMsg : public TMessage {
23  public:
24  StreamMsg(const void* buf, int len) : TMessage(const_cast<void*>(buf), len)
25  {
26  this->SetBit(kIsOwner, false);
27  }
28  };
29 }
30 
31 
32 std::string Stream::serializeAndEncode(const TObject* obj)
33 {
34  TMessage::EnableSchemaEvolutionForAll();
35 
36  TMessage msg(kMESS_OBJECT);
37  msg.SetWriteMode();
38 
39  // Currently disabled, but can be made to work by copying the input buffer in deserializeEncodedRawData
40  // However, this is a workaround and thus doesn't seem like a good idea.
41  // Once https://sft.its.cern.ch/jira/browse/ROOT-4550 is fixed, this can simply be turned on,
42  // but make sure to check that old (uncompressed) data can still be deserialized.
43  msg.SetCompressionLevel(0);
44 
45  msg.WriteObject(obj);
46  msg.Compress(); //only does something if compression active
47 
48  //convert TMessage into base64-encoded string
49  char* buf = msg.Buffer();
50  UInt_t len = msg.Length();
51 
52  if (msg.CompBuffer()) {
53  B2FATAL("compression used, but broken thanks to ROOT");
54  /* for future use?
55  buf = msg.CompBuffer();
56  len = msg.CompLength();
57  */
58  }
59 
60  const std::string& encodedStr(TBase64::Encode(buf, len).Data());
61  return encodedStr;
62 }
63 
64 std::string Stream::escapeXML(const std::string& xmlString)
65 {
66  //avoid nesting CDATA sections...
67  std::string newString(xmlString);
68  boost::replace_all(newString, "]]>", "]]]]><![CDATA[>");
69  return "<![CDATA[" + newString + "]]>";
70 }
71 
72 TObject* Stream::deserializeEncodedRawData(const std::string& base64Data)
73 {
74  if (base64Data.empty())
75  return nullptr;
76 
77  //convert data back into raw byte stream
78  const TString& data(TBase64::Decode(base64Data.c_str()));
79 
80  StreamMsg msg(data.Data(), data.Length());
81  //some checking
82  if (msg.What() != kMESS_OBJECT or msg.GetClass() == nullptr) {
83  return nullptr;
84  }
85  auto* obj = static_cast<TObject*>(msg.ReadObjectAny(msg.GetClass()));
86 
87  return obj;
88 }
std::string escapeXML(const std::string &xmlString)
Escape given XML string as CDATA sequence.
Definition: Stream.cc:64
std::string serializeAndEncode(const TObject *obj)
Convert given TObject into encoded byte stream (for storing in XML).
Definition: Stream.cc:32
TObject * deserializeEncodedRawData(const std::string &base64Data)
Convert given serialized raw data back into TObject.
Definition: Stream.cc:72
Abstract base class for different kinds of events.