13#include <rapidjson/reader.h>
14#include <rapidjson/prettywriter.h>
15#include <rapidjson/istreamwrapper.h>
16#include <rapidjson/ostreamwrapper.h>
17#include <rapidjson/error/en.h>
27using nodes = expressions::Node::self_t;
28enum struct Nodes :
int {
46 expressions::Node*
ptr =
nullptr;
50std::array<std::string_view, 11> validKeys{
63struct ExpressionReader :
public rapidjson::BaseReaderHandler<rapidjson::UTF8<>, ExpressionReader> {
64 using Ch = rapidjson::UTF8<>::Ch;
65 using SizeType = rapidjson::SizeType;
85 std::vector<expressions::Projector>
result;
87 std::unique_ptr<expressions::Node>
rootNode =
nullptr;
88 std::unique_ptr<expressions::Node>
node =
nullptr;
102 debug <<
">>> Start" << std::endl;
103 states.push(State::IN_START);
108 debug <<
"StartArray()" << std::endl;
109 if (
states.top() == State::IN_START) {
110 states.push(State::IN_LIST);
113 states.push(State::IN_ERROR);
117 bool EndArray(SizeType)
119 debug <<
"EndArray()" << std::endl;
120 if (
states.top() == State::IN_LIST) {
124 states.push(State::IN_ERROR);
128 bool Key(
const Ch*
str, SizeType,
bool)
130 debug <<
"Key(" <<
str <<
")" << std::endl;
133 if (std::find(validKeys.begin(), validKeys.end(), currentKey) == validKeys.end()) {
134 states.push(State::IN_ERROR);
138 if (
states.top() == State::IN_START) {
144 if (
states.top() == State::IN_ROOT) {
148 states.push(State::IN_ERROR);
153 if (
states.top() == State::IN_LEFT ||
states.top() == State::IN_RIGHT ||
states.top() == State::IN_COND) {
159 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) {
168 case State::IN_NODE_LITERAL:
169 node = std::make_unique<expressions::Node>(expressions::LiteralNode{
value,
type});
171 case State::IN_NODE_BINDING:
174 case State::IN_NODE_OP:
175 node = std::make_unique<expressions::Node>(expressions::OpNode{
operation}, expressions::LiteralNode{-1});
177 case State::IN_NODE_CONDITIONAL:
178 node = std::make_unique<expressions::Node>(expressions::ConditionalNode{}, expressions::LiteralNode{-1}, expressions::LiteralNode{-1}, expressions::LiteralNode{
true});
181 states.push(State::IN_ERROR);
189 auto*
n =
path.top().ptr;
190 switch (
path.top().toWrite) {
192 n->left = std::move(node);
193 path.top().toWrite = ToWrite::RIGHT;
194 path.emplace(
n->left.get(), ToWrite::LEFT);
197 n->right = std::move(node);
198 path.top().toWrite = ToWrite::COND;
199 path.emplace(
n->right.get(), ToWrite::LEFT);
202 n->condition = std::move(node);
204 path.emplace(
n->condition.get(), ToWrite::LEFT);
207 states.push(State::IN_ERROR);
212 states.push(State::IN_LEFT);
216 if (
states.top() == State::IN_LEFT) {
220 path.top().toWrite = ToWrite::RIGHT;
221 states.push(State::IN_RIGHT);
225 if (
states.top() == State::IN_RIGHT) {
229 path.top().toWrite = ToWrite::COND;
230 states.push(State::IN_COND);
235 if (
states.top() == State::IN_NODE_LITERAL) {
241 if (
states.top() == State::IN_NODE_BINDING) {
247 if (
states.top() == State::IN_NODE_OP) {
253 debug <<
">>> Unrecognized" << std::endl;
254 states.push(State::IN_ERROR);
261 debug <<
"StartObject()" << std::endl;
263 if (
states.top() == State::IN_START) {
267 if (
states.top() == State::IN_LIST) {
268 states.push(State::IN_ROOT);
272 if (
states.top() == State::IN_LEFT ||
states.top() == State::IN_RIGHT ||
states.top() == State::IN_COND) {
276 states.push(State::IN_ERROR);
280 bool EndObject(SizeType)
283 debug <<
"EndObject()" << std::endl;
285 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) {
289 if (
states.top() == State::IN_LEFT ||
states.top() == State::IN_RIGHT ||
states.top() == State::IN_COND) {
295 if (
states.top() == State::IN_ROOT) {
296 result.emplace_back(std::move(rootNode));
303 if (
states.top() == State::IN_START) {
307 states.push(State::IN_ERROR);
314 debug <<
"Null()" << std::endl;
316 if (
states.top() == State::IN_LEFT ||
states.top() == State::IN_RIGHT ||
states.top() == State::IN_COND) {
319 if (
path.top().toWrite == ToWrite::LEFT) {
320 path.top().toWrite = ToWrite::RIGHT;
321 }
else if (
path.top().toWrite == ToWrite::RIGHT) {
322 path.top().toWrite = ToWrite::COND;
323 }
else if (
path.top().toWrite == ToWrite::COND) {
330 states.push(State::IN_ERROR);
336 debug <<
"Bool(" <<
b <<
")" << std::endl;
338 if (
states.top() == State::IN_NODE_LITERAL &&
currentKey.compare(
"value") == 0) {
342 states.push(State::IN_ERROR);
348 debug <<
"Int(" <<
i <<
")" << std::endl;
350 if (
states.top() == State::IN_NODE_LITERAL &&
currentKey.compare(
"value") == 0) {
371 states.push(State::IN_ERROR);
377 if (
states.top() == State::IN_ROOT ||
states.top() == State::IN_LEFT ||
states.top() == State::IN_RIGHT ||
states.top() == State::IN_COND) {
381 case Nodes::NLITERAL:
384 states.push(State::IN_NODE_LITERAL);
385 debug <<
">>> Literal node" << std::endl;
388 case Nodes::NBINDING: {
389 states.push(State::IN_NODE_BINDING);
390 debug <<
">>> Binding node" << std::endl;
394 states.push(State::IN_NODE_OP);
395 debug <<
">>> Operation node" << std::endl;
399 states.push(State::IN_NODE_CONDITIONAL);
400 debug <<
">>> Conditional node" << std::endl;
407 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) {
414 if (
states.top() == State::IN_NODE_LITERAL ||
states.top() == State::IN_NODE_BINDING) {
416 type = (atype::type)
i;
421 if (
states.top() == State::IN_NODE_OP &&
currentKey.compare(
"operation") == 0) {
425 states.push(State::IN_ERROR);
429 bool Uint(
unsigned i)
431 debug <<
"Uint(" <<
i <<
")" << std::endl;
433 if (
states.top() == State::IN_NODE_BINDING &&
currentKey.compare(
"hash") == 0) {
438 debug <<
">> falling back to Int" << std::endl;
444 debug <<
"Int64(" <<
i <<
")" << std::endl;
446 if (
states.top() == State::IN_NODE_LITERAL &&
currentKey.compare(
"value") == 0) {
455 states.push(State::IN_ERROR);
460 states.push(State::IN_ERROR);
466 debug <<
"Uint64(" <<
i <<
")" << std::endl;
468 debug <<
">> falling back to Int64" << std::endl;
474 debug <<
"Double(" << d <<
")" << std::endl;
476 if (
states.top() == State::IN_NODE_LITERAL) {
485 states.push(State::IN_ERROR);
490 states.push(State::IN_ERROR);
494 bool String(
const Ch*
str, SizeType,
bool)
496 debug <<
"String(" <<
str <<
")" << std::endl;
498 if (
states.top() == State::IN_NODE_BINDING &&
currentKey.compare(
"binding") == 0) {
502 states.push(State::IN_ERROR);
510 rapidjson::Reader reader;
511 rapidjson::IStreamWrapper isw(s);
512 ExpressionReader ereader;
513 bool ok = reader.Parse(isw, ereader);
516 throw framework::runtime_error_f(
"Cannot parse serialized Expression, error: %s at offset: %d", rapidjson::GetParseError_En(reader.GetParseErrorCode()), reader.GetErrorOffset());
518 return std::move(ereader.result);
526 w.Int((
int)
node->self.index());
528 w.Uint64(
node->index);
535 [&
w](
bool v) {
w.Bool(
v); },
536 [&
w](
float v) {
w.Double(
v); },
537 [&
w](
double v) {
w.Double(
v); },
539 [&
w](uint16_t
v) {
w.Uint(
v); },
540 [&
w](uint32_t
v) {
w.Uint(
v); },
541 [&
w](uint64_t
v) {
w.Uint64(
v); },
542 [&
w](int8_t
v) {
w.Int(
v); },
543 [&
w](int16_t
v) {
w.Int(
v); },
544 [&
w](
int v) {
w.Int(
v); },
545 [&
w](int64_t
v) {
w.Int64(
v); }},
548 [&
w](expressions::BindingNode
const&
node) {
556 [&
w](expressions::OpNode
const&
node) {
560 [](expressions::ConditionalNode
const&) {
565void writeExpression(rapidjson::Writer<rapidjson::OStreamWrapper>&
w, expressions::Node*
n)
567 std::stack<Entry>
path;
568 path.emplace(
n, ToWrite::FULL);
569 while (!
path.empty()) {
572 if (
top.toWrite == ToWrite::FULL) {
574 writeNodeHeader(
w,
top.ptr);
575 top.toWrite = ToWrite::LEFT;
579 if (
top.toWrite == ToWrite::LEFT) {
581 top.toWrite = ToWrite::RIGHT;
582 auto*
left =
top.ptr->left.get();
583 if (
left !=
nullptr) {
591 if (
top.toWrite == ToWrite::RIGHT) {
593 top.toWrite = ToWrite::COND;
595 if (
right !=
nullptr) {
603 if (
top.toWrite == ToWrite::COND) {
605 top.toWrite = ToWrite::POP;
606 auto* cond =
top.ptr->condition.get();
607 if (cond !=
nullptr) {
608 path.emplace(cond, ToWrite::FULL);
615 if (
top.toWrite == ToWrite::POP) {
626 rapidjson::OStreamWrapper osw(o);
627 rapidjson::Writer<rapidjson::OStreamWrapper>
w(osw);
632 writeExpression(
w, p.node.get());
640struct SchemaReader :
public rapidjson::BaseReaderHandler<rapidjson::UTF8<>, SchemaReader> {
641 using Ch = rapidjson::UTF8<>::Ch;
642 using SizeType = rapidjson::SizeType;
652 std::ostringstream
debug;
654 std::shared_ptr<arrow::Schema>
schema =
nullptr;
655 std::vector<std::shared_ptr<arrow::Field>>
fields;
664 debug <<
">>> Start" << std::endl;
665 states.push(State::IN_START);
670 debug <<
"Starting array" << std::endl;
672 states.push(State::IN_LIST);
675 states.push(State::IN_ERROR);
679 bool EndArray(SizeType)
681 debug <<
"Ending array" << std::endl;
682 if (
states.top() == State::IN_LIST) {
684 schema = std::make_shared<arrow::Schema>(fields);
688 states.push(State::IN_ERROR);
692 bool Key(
const Ch*
str, SizeType,
bool)
694 debug <<
"Key(" <<
str <<
")" << std::endl;
696 if (
states.top() == State::IN_START) {
702 if (
states.top() == State::IN_FIELD) {
711 states.push(State::IN_ERROR);
717 debug <<
"StartObject()" << std::endl;
718 if (
states.top() == State::IN_START) {
722 if (
states.top() == State::IN_LIST) {
723 states.push(State::IN_FIELD);
727 states.push(State::IN_ERROR);
731 bool EndObject(SizeType)
733 debug <<
"EndObject()" << std::endl;
734 if (
states.top() == State::IN_FIELD) {
741 if (
states.top() == State::IN_START) {
745 states.push(State::IN_ERROR);
749 bool Uint(
unsigned i)
751 debug <<
"Uint(" <<
i <<
")" << std::endl;
752 if (
states.top() == State::IN_FIELD) {
754 type = (atype::type)
i;
759 states.push(State::IN_ERROR);
763 bool String(
const Ch*
str, SizeType,
bool)
765 debug <<
"String(" <<
str <<
")" << std::endl;
766 if (
states.top() == State::IN_FIELD) {
773 states.push(State::IN_ERROR);
779 debug <<
"Int(" <<
i <<
")" << std::endl;
787 rapidjson::Reader reader;
788 rapidjson::IStreamWrapper isw(s);
789 SchemaReader sreader;
791 bool ok = reader.Parse(isw, sreader);
794 throw framework::runtime_error_f(
"Cannot parse serialized Expression, error: %s at offset: %d", rapidjson::GetParseError_En(reader.GetParseErrorCode()), reader.GetErrorOffset());
796 return sreader.schema;
801void writeSchema(rapidjson::Writer<rapidjson::OStreamWrapper>&
w, arrow::Schema*
schema)
806 w.String(
f->name().c_str());
808 w.Int(
f->type()->id());
816 rapidjson::OStreamWrapper osw(o);
817 rapidjson::Writer<rapidjson::OStreamWrapper>
w(osw);
std::shared_ptr< arrow::Schema > schema
std::vector< expressions::Projector > projectors
o2::monitoring::tags::Key Key
std::unique_ptr< expressions::Node > rootNode
std::vector< std::shared_ptr< arrow::Field > > fields
std::unique_ptr< expressions::Node > node
GLdouble GLdouble GLdouble GLdouble top
GLuint const GLchar * name
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * value
GLint GLint GLsizei GLint GLenum GLenum type
GLsizei const GLchar *const * path
GLubyte GLubyte GLubyte GLubyte w
uint8_t itsSharedClusterMap uint8_t
std::shared_ptr< arrow::DataType > concreteArrowType(atype::type type)
Defining PrimaryVertex explicitly as messageable.
RuntimeErrorRef runtime_error_f(const char *,...)
static void write(std::ostream &o, std::shared_ptr< arrow::Schema > &schema)
static std::shared_ptr< arrow::Schema > read(std::istream &s)
static std::vector< expressions::Projector > read(std::istream &s)
static void write(std::ostream &o, std::vector< expressions::Projector > &projectors)
An expression tree node corresponding to a literal value.
std::variant< T... > stored_type
From https://en.cppreference.com/w/cpp/utility/variant/visit.