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
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error s
std::string columnLabel
std::string matcherStr
uint16_t pos
Definition RawData.h:3
GLuint GLsizei const GLchar * label
Definition glcorearb.h:2519
GLubyte GLubyte GLubyte GLubyte w
Definition glcorearb.h:852
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
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