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