2222
2323namespace o2 ::framework
2424{
25-
25+ namespace
26+ {
2627using nodes = expressions::Node::self_t ;
2728enum struct Nodes : int {
2829 NLITERAL = 0 ,
@@ -46,7 +47,8 @@ struct Entry {
4647 ToWrite toWrite = ToWrite::FULL;
4748};
4849
49- std::array<std::string_view, 10 > validKeys{
50+ std::array<std::string_view, 11 > validKeys{
51+ " projectors" ,
5052 " kind" ,
5153 " binding" ,
5254 " index" ,
@@ -58,30 +60,30 @@ std::array<std::string_view, 10> validKeys{
5860 " right" ,
5961 " condition" };
6062
61- namespace
62- {
6363struct ExpressionReader : public rapidjson ::BaseReaderHandler<rapidjson::UTF8<>, ExpressionReader> {
6464 using Ch = rapidjson::UTF8<>::Ch;
6565 using SizeType = rapidjson::SizeType;
6666
6767 enum struct State {
68- IN_START,
69- IN_STOP,
70- IN_NODE_LITERAL,
71- IN_NODE_BINDING,
72- IN_NODE_OP,
73- IN_NODE_CONDITIONAL,
74- IN_ROOT,
75- IN_LEFT,
76- IN_RIGHT,
77- IN_COND,
78- IN_ERROR
68+ IN_START, // global start
69+ IN_LIST, // opening brace of the list
70+ IN_ROOT, // after encountering the opening of the expression object
71+ IN_LEFT, // in "left" key - subexpression
72+ IN_RIGHT, // in "right" key - subexpression
73+ IN_COND, // in "condition" key - subexpression
74+ IN_NODE_LITERAL, // in literal node
75+ IN_NODE_BINDING, // in binding node
76+ IN_NODE_OP, // in operation node
77+ IN_NODE_CONDITIONAL, // in conditional node
78+ IN_ERROR // generic error state
7979 };
8080
8181 std::stack<State> states;
8282 std::stack<Entry> path;
8383 std::ostringstream debug;
8484
85+ std::vector<expressions::Projector> result;
86+
8587 std::unique_ptr<expressions::Node> rootNode = nullptr ;
8688 std::unique_ptr<expressions::Node> node = nullptr ;
8789 expressions::LiteralValue::stored_type value;
@@ -101,6 +103,28 @@ struct ExpressionReader : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>,
101103 states.push (State::IN_START);
102104 }
103105
106+ bool StartArray ()
107+ {
108+ debug << " Starting array" << std::endl;
109+ if (states.top () == State::IN_START) {
110+ states.push (State::IN_LIST);
111+ return true ;
112+ }
113+ states.push (State::IN_ERROR);
114+ return false ;
115+ }
116+
117+ bool EndArray (SizeType)
118+ {
119+ debug << " Ending array" << std::endl;
120+ if (states.top () == State::IN_LIST) {
121+ states.pop ();
122+ return true ;
123+ }
124+ states.push (State::IN_ERROR);
125+ return false ;
126+ }
127+
104128 bool Key (const Ch* str, SizeType, bool )
105129 {
106130 debug << " Key(" << str << " )" << std::endl;
@@ -112,8 +136,13 @@ struct ExpressionReader : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>,
112136 }
113137
114138 if (states.top () == State::IN_START) {
139+ if (currentKey.compare (" projectors" ) == 0 ) {
140+ return true ;
141+ }
142+ }
143+
144+ if (states.top () == State::IN_ROOT) {
115145 if (currentKey.compare (" kind" ) == 0 ) {
116- states.push (State::IN_ROOT);
117146 return true ;
118147 } else {
119148 states.push (State::IN_ERROR); // should start from root node
@@ -228,38 +257,62 @@ struct ExpressionReader : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>,
228257
229258 bool StartObject ()
230259 {
260+ // opening brace encountered
231261 debug << " StartObject()" << std::endl;
232- if (states.top () == State::IN_LEFT || states.top () == State::IN_RIGHT || states.top () == State::IN_COND) { // ready to start a new node
262+ // the first opening brace in the input
263+ if (states.top () == State::IN_START) {
233264 return true ;
234265 }
235- if (states.top () == State::IN_START) {
266+ // the opening of an expression
267+ if (states.top () == State::IN_LIST) {
268+ states.push (State::IN_ROOT);
236269 return true ;
237270 }
271+ // if we are looking at subexpression
272+ if (states.top () == State::IN_LEFT || states.top () == State::IN_RIGHT || states.top () == State::IN_COND) { // ready to start a new node
273+ return true ;
274+ }
275+ // no other object starts are expected
238276 states.push (State::IN_ERROR);
239277 return false ;
240278 }
241279
242280 bool EndObject (SizeType)
243281 {
282+ // closing brace encountered
244283 debug << " EndObject()" << std::endl;
284+ // we are closing up an expression
245285 if (states.top () == State::IN_NODE_LITERAL || states.top () == State::IN_NODE_OP || states.top () == State::IN_NODE_BINDING || states.top () == State::IN_NODE_CONDITIONAL) { // finalize node
246286 // finalize the current node and pop it from the stack (the pointers should be already set
247287 states.pop ();
288+ // subexpression
248289 if (states.top () == State::IN_LEFT || states.top () == State::IN_RIGHT || states.top () == State::IN_COND) {
249290 states.pop ();
291+ return true ;
292+ }
293+
294+ // expression
295+ if (states.top () == State::IN_ROOT) {
296+ result.emplace_back (std::move (rootNode));
297+ states.pop ();
298+ return true ;
250299 }
251- return true ;
252300 }
253- if (states.top () == State::IN_ROOT) {
301+
302+ // we are closing the list
303+ if (states.top () == State::IN_START) {
254304 return true ;
255305 }
306+ // no other object ends are expectedd
256307 states.push (State::IN_ERROR);
257308 return false ;
258309 }
259310
260311 bool Null ()
261312 {
313+ // null value
262314 debug << " Null()" << std::endl;
315+ // the subexpression can be empty
263316 if (states.top () == State::IN_LEFT || states.top () == State::IN_RIGHT || states.top () == State::IN_COND) {
264317 // empty node, nothing to do
265318 // move the path state to the next
@@ -281,6 +334,7 @@ struct ExpressionReader : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>,
281334 bool Bool (bool b)
282335 {
283336 debug << " Bool(" << b << " )" << std::endl;
337+ // can be a value in a literal node
284338 if (states.top () == State::IN_NODE_LITERAL && currentKey.compare (" value" ) == 0 ) {
285339 value = b;
286340 return true ;
@@ -292,6 +346,7 @@ struct ExpressionReader : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>,
292346 bool Int (int i)
293347 {
294348 debug << " Int(" << i << " )" << std::endl;
349+ // can be a value in a literal node
295350 if (states.top () == State::IN_NODE_LITERAL && currentKey.compare (" value" ) == 0 ) { // literal
296351 switch (type) {
297352 case atype::INT8:
@@ -312,12 +367,19 @@ struct ExpressionReader : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>,
312367 case atype::UINT32:
313368 value = i;
314369 break ;
370+ case atype::UINT64:
371+ value = (uint64_t )i;
372+ break ;
373+ case atype::INT64:
374+ value = (int64_t )i;
375+ break ;
315376 default :
316377 states.push (State::IN_ERROR);
317378 return false ;
318379 }
319380 return true ;
320381 }
382+ // can be a node kind designator
321383 if (states.top () == State::IN_ROOT || states.top () == State::IN_LEFT || states.top () == State::IN_RIGHT || states.top () == State::IN_COND) {
322384 if (currentKey.compare (" kind" ) == 0 ) {
323385 kind = (Nodes)i;
@@ -347,18 +409,21 @@ struct ExpressionReader : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>,
347409 }
348410 }
349411 }
412+ // can be node index
350413 if (states.top () == State::IN_NODE_BINDING || states.top () == State::IN_NODE_CONDITIONAL || states.top () == State::IN_NODE_LITERAL || states.top () == State::IN_NODE_OP) {
351414 if (currentKey.compare (" index" ) == 0 ) {
352415 index = (size_t )i;
353416 return true ;
354417 }
355418 }
419+ // can be a node type designator
356420 if (states.top () == State::IN_NODE_LITERAL || states.top () == State::IN_NODE_BINDING) {
357421 if (currentKey.compare (" arrow_type" ) == 0 ) {
358422 type = (atype::type)i;
359423 return true ;
360424 }
361425 }
426+ // can be a node operation designato
362427 if (states.top () == State::IN_NODE_OP && currentKey.compare (" operation" ) == 0 ) {
363428 operation = (BasicOp)i;
364429 return true ;
@@ -370,17 +435,20 @@ struct ExpressionReader : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>,
370435 bool Uint (unsigned i)
371436 {
372437 debug << " Uint(" << i << " )" << std::endl;
438+ // can be node hash
373439 if (states.top () == State::IN_NODE_BINDING && currentKey.compare (" hash" ) == 0 ) {
374440 hash = i;
375441 return true ;
376442 }
443+ // any positive value will be first read as unsigned, however the actual type is determined by node's arrow_type
377444 debug << " >> falling back to Int" << std::endl;
378445 return Int (i);
379446 }
380447
381448 bool Int64 (int64_t i)
382449 {
383450 debug << " Int64(" << i << " )" << std::endl;
451+ // can only be a literal node value
384452 if (states.top () == State::IN_NODE_LITERAL && currentKey.compare (" value" ) == 0 ) {
385453 value = i;
386454 return true ;
@@ -392,6 +460,7 @@ struct ExpressionReader : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>,
392460 bool Uint64 (uint64_t i)
393461 {
394462 debug << " Uint64(" << i << " )" << std::endl;
463+ // can only be a literal node value
395464 if (states.top () == State::IN_NODE_LITERAL && currentKey.compare (" value" ) == 0 ) {
396465 value = i;
397466 return true ;
@@ -403,6 +472,7 @@ struct ExpressionReader : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>,
403472 bool Double (double d)
404473 {
405474 debug << " Double(" << d << " )" << std::endl;
475+ // can only be a literal node value
406476 if (states.top () == State::IN_NODE_LITERAL) {
407477 switch (type) {
408478 case atype::FLOAT:
@@ -424,6 +494,7 @@ struct ExpressionReader : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>,
424494 bool String (const Ch* str, SizeType, bool )
425495 {
426496 debug << " String(" << str << " )" << std::endl;
497+ // can only be a binding node
427498 if (states.top () == State::IN_NODE_BINDING && currentKey.compare (" binding" ) == 0 ) {
428499 binding = str;
429500 return true ;
@@ -434,7 +505,7 @@ struct ExpressionReader : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>,
434505};
435506} // namespace
436507
437- std::unique_ptr <expressions::Node > o2::framework::ExpressionJSONHelpers::read (std::istream& s)
508+ std::vector <expressions::Projector > o2::framework::ExpressionJSONHelpers::read (std::istream& s)
438509{
439510 rapidjson::Reader reader;
440511 rapidjson::IStreamWrapper isw (s);
@@ -446,9 +517,11 @@ std::unique_ptr<expressions::Node> o2::framework::ExpressionJSONHelpers::read(st
446517 error << " Cannot parse serialized Expression, error: " << rapidjson::GetParseError_En (reader.GetParseErrorCode ()) << " at offset: " << reader.GetErrorOffset ();
447518 throw std::runtime_error (error.str ());
448519 }
449- return std::move (ereader.rootNode );
520+ return std::move (ereader.result );
450521}
451522
523+ namespace
524+ {
452525void writeNodeHeader (rapidjson::Writer<rapidjson::OStreamWrapper>& w, expressions::Node const * node)
453526{
454527 w.Key (" kind" );
@@ -491,11 +564,8 @@ void writeNodeHeader(rapidjson::Writer<rapidjson::OStreamWrapper>& w, expression
491564 node->self );
492565}
493566
494- void writeExpression (std::ostream& o , expressions::Node* n)
567+ void writeExpression (rapidjson::Writer<rapidjson::OStreamWrapper>& w , expressions::Node* n)
495568{
496- rapidjson::OStreamWrapper osw (o);
497- rapidjson::Writer<rapidjson::OStreamWrapper> w (osw);
498-
499569 std::stack<Entry> path;
500570 path.emplace (n, ToWrite::FULL);
501571 while (!path.empty ()) {
@@ -551,9 +621,20 @@ void writeExpression(std::ostream& o, expressions::Node* n)
551621 }
552622 }
553623}
554- } // namespace o2::framework
624+ } // namespace
555625
556- void o2::framework::ExpressionJSONHelpers::write (std::ostream& o, expressions::Node* n )
626+ void o2::framework::ExpressionJSONHelpers::write (std::ostream& o, std::vector<o2::framework:: expressions::Projector>& projectors )
557627{
558- writeExpression (o, n);
628+ rapidjson::OStreamWrapper osw (o);
629+ rapidjson::Writer<rapidjson::OStreamWrapper> w (osw);
630+ w.StartObject ();
631+ w.Key (" projectors" );
632+ w.StartArray ();
633+ for (auto & p : projectors) {
634+ writeExpression (w, p.node .get ());
635+ }
636+ w.EndArray ();
637+ w.EndObject ();
559638}
639+
640+ } // namespace o2::framework
0 commit comments