Skip to content

Commit db07ee2

Browse files
committed
Use argparse.hpp and reimplement the main function
Signed-off-by: Kunlin Yu <yukunlin@syriusrobotics.com>
1 parent 0de5725 commit db07ee2

File tree

3 files changed

+150
-72
lines changed

3 files changed

+150
-72
lines changed
File renamed without changes.

scripts/test.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
./cql2 -query="NOT TRUE OR NOT TRUE AND FALSE" -dot="test" && dot -Tpng test.dot -o test.png && eog test.png
2-
./cql2 -query="S_INTERSECTS (geom, POLYGON((-64 32, -65 18, -80 25, -64 32)))" -geojson=../test/geojson/1.geojson -dot="test" && dot -Tpng test.dot -o test.png && eog test.png
1+
./cql2 parse "NOT TRUE OR NOT TRUE AND FALSE" -O "test" && dot -Tpng test.dot -o test.png && eog test.png
2+
./cql2 evaluate --features=../test/geojson/1.geojson --index 0 -O test "S_INTERSECTS (geom, POLYGON((-64 32, -65 18, -80 25, -64 32)))" && dot -Tpng test.dot -o test.png
3+
./cql2 filter --features=../test/geojson/1.geojson "S_INTERSECTS (geom, POLYGON((-1 -1, 1 -1, 1 1, -1 1, -1 -1)))" && dot -Tpng test.dot -o test.png && eog test.png

src/main.cc

Lines changed: 147 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -19,102 +19,132 @@
1919
#include <gflags/gflags.h>
2020
#include <glog/logging.h>
2121

22+
#include <argparse/argparse.hpp>
2223
#include <fstream>
2324

2425
#ifndef VERSION
2526
#define VERSION "0.0.0"
2627
#endif
2728

28-
DEFINE_string(query, "", "cql2 query string");
29-
DEFINE_string(geojson, "",
30-
"geojson data set with multiple features in one feature "
31-
"collection to be queried");
32-
DEFINE_string(dot, "", "generate dot file");
33-
DEFINE_uint32(index, 0,
34-
"the dot file will generated according to the feature with this "
35-
"index in geojson file");
36-
DEFINE_bool(verbose, false, "Enable verbose output");
37-
3829
int main(int argc, char** argv) {
39-
gflags::SetUsageMessage(
40-
"Usage: cql2 -query=\"city='Toronto'\" "
41-
"-geojson=\"path/to/feature_collection.geojson\" -index=0");
42-
gflags::SetVersionString(VERSION);
43-
gflags::ParseCommandLineFlags(&argc, &argv, true);
30+
argparse::ArgumentParser program("cql2", VERSION);
31+
32+
argparse::ArgumentParser parse_command("parse", "",
33+
argparse::default_arguments::help);
34+
parse_command.add_description("parse a cql2 query and print dot file");
35+
parse_command.add_argument("query").help("cql2 query string");
36+
parse_command.add_argument("-V", "--verbose")
37+
.help("print verbose debug log")
38+
.flag();
39+
parse_command.add_argument("-O", "--output").help("the output dot file");
40+
41+
argparse::ArgumentParser filter_command("filter", "",
42+
argparse::default_arguments::help);
43+
filter_command.add_description(
44+
"filter features from geojson data collection");
45+
filter_command.add_argument("query").help("cql2 query string");
46+
filter_command.add_argument("--features")
47+
.help(
48+
"geojson file contains multiple features in one feature collection");
49+
filter_command.add_argument("-V", "--verbose")
50+
.help("print verbose debug log")
51+
.flag();
52+
53+
argparse::ArgumentParser sql_command("sql", "",
54+
argparse::default_arguments::help);
55+
sql_command.add_argument("query").help("cql2 query string");
56+
sql_command.add_argument("-V", "--verbose")
57+
.help("print verbose debug log")
58+
.flag();
59+
60+
argparse::ArgumentParser eval_command("evaluate", "",
61+
argparse::default_arguments::help);
62+
eval_command.add_argument("query").help("cql2 query string");
63+
eval_command.add_argument("--features")
64+
.help(
65+
"geojson file contains multiple features in one feature collection");
66+
eval_command.add_argument("--index")
67+
.help("index of feature in the geojson file to be evaluated")
68+
.scan<'i', int>();
69+
eval_command.add_argument("-O", "--output").help("the output dot file");
70+
eval_command.add_argument("-V", "--verbose")
71+
.help("print verbose debug log")
72+
.flag();
73+
74+
program.add_subparser(parse_command);
75+
program.add_subparser(filter_command);
76+
program.add_subparser(sql_command);
77+
program.add_subparser(eval_command);
78+
79+
if (argc == 1) {
80+
std::cout << program;
81+
return 0;
82+
}
83+
84+
try {
85+
program.parse_args(argc, argv);
86+
} catch (const std::exception& e) {
87+
LOG(ERROR) << e.what();
88+
return 1;
89+
}
4490

4591
google::InitGoogleLogging(argv[0]);
4692
FLAGS_colorlogtostderr = true;
4793
google::InstallFailureSignalHandler();
4894
google::LogToStderr();
4995

50-
if (FLAGS_query.empty()) {
51-
gflags::ShowUsageWithFlagsRestrict(argv[0], "main.cc");
52-
LOG(ERROR) << "you should provide query";
53-
return -1;
54-
}
55-
56-
// print flags
57-
LOG(INFO) << "==== flags ====";
58-
LOG(INFO) << "query: " << FLAGS_query;
59-
LOG(INFO) << "geojson: " << FLAGS_geojson;
60-
LOG(INFO) << "dot: " << FLAGS_dot;
61-
62-
if (FLAGS_verbose) cql2cpp::AstNode::set_ostream(&std::cout);
63-
64-
std::string error_msg;
65-
66-
// case 1:
67-
// we have only query without any feature
68-
// just parse the query and may dump a dot file
69-
if (FLAGS_geojson.empty()) {
96+
if (program.is_subcommand_used("parse")) {
97+
if (parse_command.get<bool>("--verbose"))
98+
cql2cpp::AstNode::set_ostream(&std::cout);
7099
std::string dot;
100+
std::string error_msg;
71101
cql2cpp::Cql2Cpp<geos::io::GeoJSONFeature> cql2cpp;
72-
if (cql2cpp.ToDot(FLAGS_query, &dot, &error_msg)) {
73-
LOG(INFO) << error_msg;
74-
if (not FLAGS_dot.empty()) {
75-
std::string dot_filename = FLAGS_dot;
102+
if (cql2cpp.ToDot(parse_command.get<std::string>("query"), &dot,
103+
&error_msg)) {
104+
if (parse_command.is_used("--output")) {
105+
std::string dot_filename = parse_command.get<std::string>("--output");
76106
if (dot_filename.find(".dot") == std::string::npos)
77107
dot_filename += ".dot";
78108

79109
std::ofstream fout(dot_filename);
80110
if (fout.is_open()) {
81111
fout << dot;
82112
fout.close();
83-
LOG(INFO) << "dump dot file into " << dot_filename;
113+
LOG(INFO) << "save dot file: " << dot_filename;
84114
} else {
85115
LOG(ERROR) << "Can not open file " << dot_filename;
86116
}
117+
} else {
118+
LOG(INFO) << dot;
87119
}
88120
} else {
89121
LOG(ERROR) << error_msg;
90-
goto FAILED;
91122
}
92-
} else {
93-
// case 2:
94-
// we have query and a feature collection
95-
// filter matched features from the feature collection
123+
} else if (program.is_subcommand_used("filter")) {
124+
if (filter_command.get<bool>("--verbose"))
125+
cql2cpp::AstNode::set_ostream(&std::cout);
96126
std::string geojson_text;
97-
std::ifstream fin(FLAGS_geojson);
98-
if (fin.good()) {
99-
if (fin.is_open()) {
100-
geojson_text.assign(std::istreambuf_iterator<char>(fin),
101-
std::istreambuf_iterator<char>());
102-
fin.close();
103-
} else {
104-
LOG(ERROR) << "can not open " << FLAGS_geojson;
105-
goto FAILED;
106-
}
107-
} else {
108-
LOG(ERROR) << FLAGS_geojson << " not exist";
127+
std::string features = filter_command.get<std::string>("--features");
128+
std::ifstream fin(features);
129+
130+
if (not fin.good()) {
131+
LOG(ERROR) << features << " not exist";
132+
goto FAILED;
133+
}
134+
if (not fin.is_open()) {
135+
LOG(ERROR) << "can not open " << features;
109136
goto FAILED;
110137
}
138+
geojson_text.assign(std::istreambuf_iterator<char>(fin),
139+
std::istreambuf_iterator<char>());
140+
fin.close();
111141

112142
geos::io::GeoJSONFeatureCollection fc({});
113143
// read geojson features
114144
geos::io::GeoJSONReader reader;
115145
fc = reader.readFeatures(geojson_text);
116146
LOG(INFO) << "load " << fc.getFeatures().size() << " features from "
117-
<< FLAGS_geojson;
147+
<< features;
118148

119149
std::map<cql2cpp::FeatureSourcePtr, const geos::io::GeoJSONFeature*>
120150
fs_feature;
@@ -124,31 +154,73 @@ int main(int argc, char** argv) {
124154
fs_feature[fp] = &feature;
125155
}
126156

157+
std::string query = filter_command.get<std::string>("query");
158+
127159
cql2cpp::Cql2Cpp<const geos::io::GeoJSONFeature*> cql2cpp;
128160
cql2cpp.set_feature_source(fs_feature);
129161
std::vector<const geos::io::GeoJSONFeature*> result;
130-
if (cql2cpp.filter(FLAGS_query, &result)) {
131-
LOG(INFO) << "get feature count: " << result.size();
132-
for (const auto& feature : result) {
133-
LOG(INFO) << "get feature geometry: "
134-
<< feature->getGeometry()->toText();
135-
}
162+
if (cql2cpp.filter(query, &result)) {
163+
LOG(INFO) << result.size() << " features match the filter:";
164+
geos::io::GeoJSONWriter writer;
165+
for (const auto& feature : result) LOG(INFO) << writer.write(*feature);
136166
} else {
137167
LOG(ERROR) << "filter error: " << cql2cpp.error_msg();
138168
}
169+
} else if (program.is_subcommand_used("sql")) {
170+
if (sql_command.get<bool>("--verbose"))
171+
cql2cpp::AstNode::set_ostream(&std::cout);
172+
std::string query = sql_command.get<std::string>("query");
173+
std::string sql_where;
174+
std::string error_msg;
175+
if (cql2cpp::Cql2Cpp<void*>::ConvertToSQL(query, &sql_where, &error_msg)) {
176+
LOG(INFO) << sql_where;
177+
} else {
178+
LOG(ERROR) << error_msg;
179+
goto FAILED;
180+
}
181+
} else if (program.is_subcommand_used("evaluate")) {
182+
if (eval_command.get<bool>("--verbose")) {
183+
cql2cpp::AstNode::set_ostream(&std::cout);
184+
}
185+
std::string geojson_text;
186+
std::string features = eval_command.get<std::string>("--features");
187+
std::ifstream fin(features);
188+
if (not fin.good()) {
189+
LOG(ERROR) << features << " not exist";
190+
goto FAILED;
191+
}
192+
if (not fin.is_open()) {
193+
LOG(ERROR) << "can not open " << features;
194+
goto FAILED;
195+
}
196+
geojson_text.assign(std::istreambuf_iterator<char>(fin),
197+
std::istreambuf_iterator<char>());
198+
fin.close();
139199

140-
if (FLAGS_index >= fc.getFeatures().size()) {
141-
LOG(ERROR) << "index(" << FLAGS_index << ") out of range [0.."
200+
geos::io::GeoJSONFeatureCollection fc({});
201+
// read geojson features
202+
geos::io::GeoJSONReader reader;
203+
fc = reader.readFeatures(geojson_text);
204+
LOG(INFO) << "load " << fc.getFeatures().size() << " features from "
205+
<< features;
206+
207+
int index = eval_command.get<int>("index");
208+
if (index >= fc.getFeatures().size()) {
209+
LOG(ERROR) << "index(" << index << ") out of range [0.."
142210
<< fc.getFeatures().size() - 1 << "]";
143211
goto FAILED;
144212
}
145-
cql2cpp::FeatureSourceGeoJson fs(fc.getFeatures().at(FLAGS_index));
213+
cql2cpp::FeatureSourceGeoJson fs(fc.getFeatures().at(index));
214+
std::string query = eval_command.get<std::string>("query");
215+
216+
cql2cpp::Cql2Cpp<const geos::io::GeoJSONFeature*> cql2cpp;
146217

147218
std::string dot;
148219
bool eval_result;
149-
if (cql2cpp.Evaluate(FLAGS_query, fs, &eval_result, &error_msg, &dot)) {
150-
if (not FLAGS_dot.empty()) {
151-
std::string dot_filename = FLAGS_dot;
220+
std::string error_msg;
221+
if (cql2cpp.Evaluate(query, fs, &eval_result, &error_msg, &dot)) {
222+
if (eval_command.is_used("--output")) {
223+
std::string dot_filename = eval_command.get<std::string>("--output");
152224
if (dot_filename.find(".dot") == std::string::npos)
153225
dot_filename += ".dot";
154226

@@ -160,10 +232,15 @@ int main(int argc, char** argv) {
160232
} else {
161233
LOG(ERROR) << "Can not open file " << dot_filename;
162234
}
235+
} else {
236+
LOG(INFO) << dot;
163237
}
164238
} else {
165239
LOG(ERROR) << error_msg;
166240
}
241+
242+
} else {
243+
LOG(ERROR) << "unknown sub-command";
167244
}
168245

169246
gflags::ShutDownCommandLineFlags();

0 commit comments

Comments
 (0)