Belle II Software development
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
18using namespace Belle2;
19
20namespace {
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
32std::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
64std::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
72TObject* 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.