Project
Loading...
Searching...
No Matches
IndexJSONHelpers.cxx
Go to the documentation of this file.
1// Copyright 2019-2025 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11#include "IndexJSONHelpers.h"
12
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>
18
19#include <stack>
20#include <iostream>
21
22namespace o2::framework
23{
24namespace
25{
26struct IndexRecordsReader : public rapidjson::BaseReaderHandler<rapidjson::UTF8<>, IndexRecordsReader> {
27 using Ch = rapidjson::UTF8<>::Ch;
28 using SizeType = rapidjson::SizeType;
29
30 enum struct State {
32 IN_LIST,
33 IN_RECORD,
35 };
36
37 std::stack<State> states;
38 std::ostringstream debug;
39
40 std::vector<o2::soa::IndexRecord> records;
41 std::string currentKey;
42 std::string label;
43 std::string columnLabel;
44 std::string matcherStr;
46 int pos;
47
48 IndexRecordsReader()
49 {
50 debug << ">>> Start" << std::endl;
51 states.push(State::IN_START);
52 }
53
54 bool StartArray()
55 {
56 debug << "StartArray()" << std::endl;
57 if (states.top() == State::IN_START && currentKey.compare("records") == 0) {
58 states.push(State::IN_LIST);
59 return true;
60 }
61 states.push(State::IN_ERROR);
62 return false;
63 }
64
65 bool EndArray(SizeType)
66 {
67 debug << "EndArray()" << std::endl;
68 if (states.top() == State::IN_LIST) {
69 // records done
70 states.pop();
71 return true;
72 }
73 states.push(State::IN_ERROR);
74 return false;
75 }
76
77 bool Key(const Ch* str, SizeType, bool)
78 {
79 debug << "Key(" << str << ")" << std::endl;
81 if (states.top() == State::IN_START) {
82 if (currentKey.compare("records") == 0) {
83 return true;
84 }
85 }
86
87 if (states.top() == State::IN_RECORD) {
88 if (currentKey.compare("label") == 0) {
89 return true;
90 }
91 if (currentKey.compare("matcher") == 0) {
92 return true;
93 }
94 if (currentKey.compare("column") == 0) {
95 return true;
96 }
97 if (currentKey.compare("kind") == 0) {
98 return true;
99 }
100 if (currentKey.compare("pos") == 0) {
101 return true;
102 }
103 }
104
105 states.push(State::IN_ERROR);
106 return false;
107 }
108
109 bool StartObject()
110 {
111 debug << "StartObject()" << std::endl;
112 if (states.top() == State::IN_START) {
113 return true;
114 }
115
116 if (states.top() == State::IN_LIST) {
117 states.push(State::IN_RECORD);
118 label = "";
120 pos = -2;
121 return true;
122 }
123
124 states.push(State::IN_ERROR);
125 return false;
126 }
127
128 bool EndObject(SizeType)
129 {
130 debug << "EndObject()" << std::endl;
131 if (states.top() == State::IN_RECORD) {
132 states.pop();
133 // add a record
134 records.emplace_back(label, DataSpecUtils::fromString(matcherStr), columnLabel, kind, pos);
135 return true;
136 }
137
138 if (states.top() == State::IN_START) {
139 return true;
140 }
141
142 states.push(State::IN_ERROR);
143 return false;
144 }
145
146 bool Uint(unsigned i)
147 {
148 debug << "Uint(" << i << ") passed to Int()" << std::endl;
149 return Int(i);
150 }
151
152 bool Int(int i)
153 {
154 debug << "Int(" << i << ")" << std::endl;
155 if (states.top() == State::IN_RECORD) {
156 if (currentKey.compare("kind") == 0) {
158 return true;
159 }
160 if (currentKey.compare("pos") == 0) {
161 pos = i;
162 return true;
163 }
164 }
165
166 states.push(State::IN_ERROR);
167 return false;
168 }
169
170 bool String(const Ch* str, SizeType, bool)
171 {
172 debug << "String(" << str << ")" << std::endl;
173 if (states.top() == State::IN_RECORD) {
174 if (currentKey.compare("label") == 0) {
175 label = str;
176 return true;
177 }
178 if (currentKey.compare("column") == 0) {
180 return true;
181 }
182 if (currentKey.compare("matcher") == 0) {
183 matcherStr = str;
184 return true;
185 }
186 }
187
188 states.push(State::IN_ERROR);
189 return false;
190 }
191};
192} // namespace
193
194std::vector<o2::soa::IndexRecord> IndexJSONHelpers::read(std::istream& s)
195{
196 rapidjson::Reader reader;
197 rapidjson::IStreamWrapper isw(s);
198 IndexRecordsReader irreader;
199
200 bool ok = reader.Parse(isw, irreader);
201
202 if (!ok) {
203 throw framework::runtime_error_f("Cannot parse serialized index records vector, error: %s at offset: %d", rapidjson::GetParseError_En(reader.GetParseErrorCode()), reader.GetErrorOffset());
204 }
205 return irreader.records;
206}
207
208namespace
209{
210void writeRecords(rapidjson::Writer<rapidjson::OStreamWrapper>& w, std::vector<o2::soa::IndexRecord>& records)
211{
212 for (auto& r : records) {
213 w.StartObject();
214 w.Key("label");
215 w.String(r.label.c_str());
216 w.Key("matcher");
217 w.String(DataSpecUtils::describe(r.matcher).c_str());
218 w.Key("column");
219 w.String(r.columnLabel.c_str());
220 w.Key("kind");
221 w.Int((int)r.kind);
222 w.Key("pos");
223 w.Int(r.pos);
224 w.EndObject();
225 }
226}
227} // namespace
228
229void IndexJSONHelpers::write(std::ostream& o, std::vector<o2::soa::IndexRecord>& irs)
230{
231 rapidjson::OStreamWrapper osw(o);
232 rapidjson::Writer<rapidjson::OStreamWrapper> w(osw);
233 w.StartObject();
234 w.Key("records");
235 w.StartArray();
236 writeRecords(w, irs);
237 w.EndArray();
238 w.EndObject();
239}
240} // namespace o2::framework
std::vector< o2::soa::IndexRecord > records
o2::monitoring::tags::Key Key
std::string currentKey
std::ostringstream debug
int32_t i
std::string columnLabel
std::string matcherStr
uint16_t pos
Definition RawData.h:3
GLuint GLsizei const GLchar * label
Definition glcorearb.h:2519
GLboolean r
Definition glcorearb.h:1233
GLubyte GLubyte GLubyte GLubyte w
Definition glcorearb.h:852
GLuint * states
Definition glcorearb.h:4932
Defining PrimaryVertex explicitly as messageable.
RuntimeErrorRef runtime_error_f(const char *,...)
static std::string describe(InputSpec const &spec)
static ConcreteDataMatcher fromString(std::string s)
Create a concrete data matcher from serialized string.
static void write(std::ostream &o, std::vector< o2::soa::IndexRecord > &irs)
static std::vector< o2::soa::IndexRecord > read(std::istream &s)
const std::string str