Line data Source code
1 : //
2 : // DUNE DAQ modification notice:
3 : // This file has been modified from the original ATLAS config source for the DUNE DAQ project.
4 : // Fork baseline commit: 67a24e731 (2022-10-27).
5 : // Renamed since fork: yes (from bin/config_export_data.cpp to apps/config_export_data.cxx).
6 : //
7 :
8 : #include <stdlib.h>
9 :
10 : #include <iostream>
11 :
12 : #include <boost/program_options.hpp>
13 :
14 : #include <boost/property_tree/info_parser.hpp>
15 : #include <boost/property_tree/json_parser.hpp>
16 : #include <boost/property_tree/xml_parser.hpp>
17 :
18 : #include "conffwk/Configuration.hpp"
19 :
20 : using namespace dunedaq::conffwk;
21 :
22 : int
23 0 : main(int argc, char *argv[])
24 : {
25 0 : std::string output_file, db_name, classes, objects, files, format("json");
26 0 : bool apply_fix(false);
27 :
28 0 : boost::program_options::options_description desc("Export config data using boost property tree.\n\nOptions/Arguments");
29 :
30 0 : try
31 : {
32 0 : desc.add_options()
33 0 : (
34 : "database,d",
35 0 : boost::program_options::value<std::string>(&db_name)->required(),
36 : "database specification in format plugin-name:parameters"
37 : )
38 0 : (
39 : "classes,c",
40 0 : boost::program_options::value<std::string>(&classes),
41 : "regex defining class names; ignore if empty"
42 : )
43 0 : (
44 : "objects,i",
45 0 : boost::program_options::value<std::string>(&objects),
46 : "regex defining object IDs; ignore if empty"
47 : )
48 0 : (
49 : "files,f",
50 0 : boost::program_options::value<std::string>(&files),
51 : "regex defining data files; ignore if empty"
52 : )
53 0 : (
54 : "output,o",
55 0 : boost::program_options::value<std::string>(&output_file),
56 : "output file name; print to standard out, if not defined"
57 : )
58 0 : (
59 : "format,t",
60 0 : boost::program_options::value<std::string>(&format)->default_value(format),
61 : "output format (\"json\", \"xml\" or \"info\")"
62 : )
63 0 : (
64 : "fix,x",
65 : "fix arrays output format:\n* enforce empty arrays for json;\n* remove unnamed xml tags"
66 : )
67 0 : (
68 : "help,h",
69 : "Print help message"
70 : );
71 :
72 0 : boost::program_options::variables_map vm;
73 0 : boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
74 :
75 0 : if (vm.count("help"))
76 : {
77 0 : std::cout << desc << std::endl;
78 0 : return EXIT_SUCCESS;
79 : }
80 :
81 0 : boost::program_options::notify(vm);
82 :
83 0 : if (vm.count("fix"))
84 0 : apply_fix = true;
85 :
86 0 : auto valid_formats = {"json", "xml", "info"};
87 0 : if (std::none_of(valid_formats.begin(), valid_formats.end(), [&format](auto p){ return p == format; }))
88 0 : throw std::runtime_error("unsupported format \"" + format + '\"');
89 0 : }
90 0 : catch (std::exception& ex)
91 : {
92 0 : std::cerr << "command line error: " << ex.what() << std::endl;
93 0 : return EXIT_FAILURE;
94 0 : }
95 :
96 0 : try
97 : {
98 0 : Configuration db(db_name);
99 :
100 0 : boost::property_tree::ptree pt;
101 0 : std::string fix_empty_arrays((apply_fix && format == "json") ? "<-- empty-p3-element -->" : "");
102 :
103 0 : db.export_data(pt, classes, objects, files, fix_empty_arrays);
104 :
105 0 : std::string in, out;
106 :
107 0 : {
108 0 : std::ostringstream buf;
109 0 : if (format == "json")
110 0 : boost::property_tree::json_parser::write_json(buf, pt);
111 0 : else if (format == "xml")
112 0 : boost::property_tree::xml_parser::write_xml(buf, pt, boost::property_tree::xml_writer_make_settings<std::string>(' ', 4));
113 : else
114 0 : boost::property_tree::info_parser::write_info(buf, pt, boost::property_tree::info_writer_make_settings(' ', 4));
115 :
116 0 : in = buf.str();
117 0 : }
118 :
119 0 : if (!apply_fix || format == "info")
120 0 : out = std::move(in);
121 : else
122 : {
123 0 : out.reserve(in.size());
124 0 : std::string::size_type pos = 0, fix_pos;
125 :
126 0 : if (format == "json")
127 : {
128 0 : while ((fix_pos = in.find(fix_empty_arrays, pos)) != std::string::npos)
129 : {
130 0 : std::string::size_type start = in.rfind('[', fix_pos);
131 0 : std::string::size_type end = in.find(']', fix_pos);
132 :
133 0 : if (start != std::string::npos && end != std::string::npos)
134 : {
135 0 : out.append(in, pos, start + 1 - pos);
136 : pos = end;
137 : }
138 : else
139 : break;
140 : }
141 : }
142 : else
143 : {
144 : // remove unnamed xml tags: replace "<>FOO</>" by "FOO"
145 0 : while ((fix_pos = in.find("<>", pos)) != std::string::npos)
146 : {
147 0 : std::string::size_type next = in.find("</>", fix_pos);
148 :
149 0 : if (next != std::string::npos)
150 : {
151 0 : out.append(in, pos, fix_pos - pos);
152 0 : out.append(in, fix_pos+2, next - fix_pos - 2);
153 0 : pos = next + 3;
154 : }
155 : else
156 : break;
157 : }
158 : }
159 :
160 0 : out.append(in, pos);
161 : }
162 :
163 0 : if (!output_file.empty())
164 : {
165 0 : std::ofstream f(output_file);
166 0 : f.exceptions ( std::ifstream::failbit | std::ifstream::badbit );
167 0 : f << out;
168 0 : f.close();
169 0 : }
170 : else
171 0 : std::cout << out;
172 :
173 0 : return EXIT_SUCCESS;
174 0 : }
175 0 : catch (const dunedaq::conffwk::Exception &ex)
176 : {
177 0 : std::cout << "config error: " << ex << std::endl;
178 0 : }
179 0 : catch (const boost::property_tree::json_parser_error &ex)
180 : {
181 0 : std::cout << "ptree json error: " << ex.what() << std::endl;
182 0 : }
183 0 : catch (const std::exception &ex)
184 : {
185 0 : std::cout << "error: " << ex.what() << std::endl;
186 0 : }
187 :
188 : return EXIT_FAILURE;
189 0 : }
|