diff options
author | Rutger Broekhoff | 2024-05-02 20:27:40 +0200 |
---|---|---|
committer | Rutger Broekhoff | 2024-05-02 20:27:40 +0200 |
commit | 17a3ea880402338420699e03bcb24181e4ff3924 (patch) | |
tree | da666ef91e0b60d20aa0b01529644c136fd1f4ab /src/querykv1/main.cpp | |
download | oeuf-17a3ea880402338420699e03bcb24181e4ff3924.tar.gz oeuf-17a3ea880402338420699e03bcb24181e4ff3924.zip |
Initial commit
Based on dc4ba6a
Diffstat (limited to 'src/querykv1/main.cpp')
-rw-r--r-- | src/querykv1/main.cpp | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/src/querykv1/main.cpp b/src/querykv1/main.cpp new file mode 100644 index 0000000..6c606ba --- /dev/null +++ b/src/querykv1/main.cpp | |||
@@ -0,0 +1,198 @@ | |||
1 | // vim:set sw=2 ts=2 sts et: | ||
2 | |||
3 | #include <chrono> | ||
4 | #include <cstdio> | ||
5 | #include <string> | ||
6 | #include <string_view> | ||
7 | #include <vector> | ||
8 | |||
9 | #include <tmi8/kv1_types.hpp> | ||
10 | #include <tmi8/kv1_index.hpp> | ||
11 | #include <tmi8/kv1_lexer.hpp> | ||
12 | #include <tmi8/kv1_parser.hpp> | ||
13 | |||
14 | #include "cliopts.hpp" | ||
15 | #include "joparoute.hpp" | ||
16 | #include "journeyinfo.hpp" | ||
17 | #include "journeyroute.hpp" | ||
18 | #include "journeys.hpp" | ||
19 | #include "schedule.hpp" | ||
20 | |||
21 | using namespace std::string_view_literals; | ||
22 | |||
23 | using TimingClock = std::conditional_t< | ||
24 | std::chrono::high_resolution_clock::is_steady, | ||
25 | std::chrono::high_resolution_clock, | ||
26 | std::chrono::steady_clock>; | ||
27 | |||
28 | std::string readKv1(const char *path) { | ||
29 | FILE *in = stdin; | ||
30 | if (path != "-"sv) in = fopen(path, "rb"); | ||
31 | else fputs("Reading KV1 from standard input\n", stderr); | ||
32 | if (!in) { | ||
33 | fprintf(stderr, "Open %s: %s\n", path, strerrordesc_np(errno)); | ||
34 | exit(1); | ||
35 | } | ||
36 | |||
37 | char buf[4096]; | ||
38 | std::string data; | ||
39 | while (!feof(in) && !ferror(in)) { | ||
40 | size_t read = fread(buf, sizeof(char), 4096, in); | ||
41 | data.append(buf, read); | ||
42 | } | ||
43 | if (ferror(in)) { | ||
44 | if (path == "-"sv) | ||
45 | fputs("Error when reading from stdin\n", stderr); | ||
46 | else | ||
47 | fprintf(stderr, "Error reading from file \"%s\"\n", path); | ||
48 | exit(1); | ||
49 | } | ||
50 | fprintf(stderr, "Read %lu bytes\n", data.size()); | ||
51 | |||
52 | if (path != "-"sv) | ||
53 | fclose(in); | ||
54 | |||
55 | return data; | ||
56 | } | ||
57 | |||
58 | std::vector<Kv1Token> lex(const char *path) { | ||
59 | std::string data = readKv1(path); | ||
60 | |||
61 | auto start = TimingClock::now(); | ||
62 | Kv1Lexer lexer(data); | ||
63 | lexer.lex(); | ||
64 | auto end = TimingClock::now(); | ||
65 | |||
66 | std::chrono::duration<double> elapsed{end - start}; | ||
67 | double bytes = static_cast<double>(data.size()) / 1'000'000; | ||
68 | double speed = bytes / elapsed.count(); | ||
69 | |||
70 | if (!lexer.errors.empty()) { | ||
71 | fputs("Lexer reported errors:\n", stderr); | ||
72 | for (const auto &error : lexer.errors) | ||
73 | fprintf(stderr, "- %s\n", error.c_str()); | ||
74 | exit(1); | ||
75 | } | ||
76 | |||
77 | fprintf(stderr, "Got %lu tokens\n", lexer.tokens.size()); | ||
78 | fprintf(stderr, "Duration: %f s\n", elapsed.count()); | ||
79 | fprintf(stderr, "Speed: %f MB/s\n", speed); | ||
80 | |||
81 | return std::move(lexer.tokens); | ||
82 | } | ||
83 | |||
84 | bool parse(const char *path, Kv1Records &into) { | ||
85 | std::vector<Kv1Token> tokens = lex(path); | ||
86 | |||
87 | Kv1Parser parser(tokens, into); | ||
88 | parser.parse(); | ||
89 | |||
90 | bool ok = true; | ||
91 | if (!parser.gerrors.empty()) { | ||
92 | ok = false; | ||
93 | fputs("Parser reported errors:\n", stderr); | ||
94 | for (const auto &error : parser.gerrors) | ||
95 | fprintf(stderr, "- %s\n", error.c_str()); | ||
96 | } | ||
97 | if (!parser.warns.empty()) { | ||
98 | fputs("Parser reported warnings:\n", stderr); | ||
99 | for (const auto &warn : parser.warns) | ||
100 | fprintf(stderr, "- %s\n", warn.c_str()); | ||
101 | } | ||
102 | |||
103 | fprintf(stderr, "Parsed %lu records\n", into.size()); | ||
104 | |||
105 | return ok; | ||
106 | } | ||
107 | |||
108 | void printParsedRecords(const Kv1Records &records) { | ||
109 | fputs("Parsed records:\n", stderr); | ||
110 | fprintf(stderr, " organizational_units: %lu\n", records.organizational_units.size()); | ||
111 | fprintf(stderr, " higher_organizational_units: %lu\n", records.higher_organizational_units.size()); | ||
112 | fprintf(stderr, " user_stop_points: %lu\n", records.user_stop_points.size()); | ||
113 | fprintf(stderr, " user_stop_areas: %lu\n", records.user_stop_areas.size()); | ||
114 | fprintf(stderr, " timing_links: %lu\n", records.timing_links.size()); | ||
115 | fprintf(stderr, " links: %lu\n", records.links.size()); | ||
116 | fprintf(stderr, " lines: %lu\n", records.lines.size()); | ||
117 | fprintf(stderr, " destinations: %lu\n", records.destinations.size()); | ||
118 | fprintf(stderr, " journey_patterns: %lu\n", records.journey_patterns.size()); | ||
119 | fprintf(stderr, " concession_financer_relations: %lu\n", records.concession_financer_relations.size()); | ||
120 | fprintf(stderr, " concession_areas: %lu\n", records.concession_areas.size()); | ||
121 | fprintf(stderr, " financers: %lu\n", records.financers.size()); | ||
122 | fprintf(stderr, " journey_pattern_timing_links: %lu\n", records.journey_pattern_timing_links.size()); | ||
123 | fprintf(stderr, " points: %lu\n", records.points.size()); | ||
124 | fprintf(stderr, " point_on_links: %lu\n", records.point_on_links.size()); | ||
125 | fprintf(stderr, " icons: %lu\n", records.icons.size()); | ||
126 | fprintf(stderr, " notices: %lu\n", records.notices.size()); | ||
127 | fprintf(stderr, " notice_assignments: %lu\n", records.notice_assignments.size()); | ||
128 | fprintf(stderr, " time_demand_groups: %lu\n", records.time_demand_groups.size()); | ||
129 | fprintf(stderr, " time_demand_group_run_times: %lu\n", records.time_demand_group_run_times.size()); | ||
130 | fprintf(stderr, " period_groups: %lu\n", records.period_groups.size()); | ||
131 | fprintf(stderr, " specific_days: %lu\n", records.specific_days.size()); | ||
132 | fprintf(stderr, " timetable_versions: %lu\n", records.timetable_versions.size()); | ||
133 | fprintf(stderr, " public_journeys: %lu\n", records.public_journeys.size()); | ||
134 | fprintf(stderr, " period_group_validities: %lu\n", records.period_group_validities.size()); | ||
135 | fprintf(stderr, " exceptional_operating_days: %lu\n", records.exceptional_operating_days.size()); | ||
136 | fprintf(stderr, " schedule_versions: %lu\n", records.schedule_versions.size()); | ||
137 | fprintf(stderr, " public_journey_passing_times: %lu\n", records.public_journey_passing_times.size()); | ||
138 | fprintf(stderr, " operating_days: %lu\n", records.operating_days.size()); | ||
139 | } | ||
140 | |||
141 | void printIndexSize(const Kv1Index &index) { | ||
142 | fputs("Index size:\n", stderr); | ||
143 | fprintf(stderr, " organizational_units: %lu\n", index.organizational_units.size()); | ||
144 | fprintf(stderr, " user_stop_points: %lu\n", index.user_stop_points.size()); | ||
145 | fprintf(stderr, " user_stop_areas: %lu\n", index.user_stop_areas.size()); | ||
146 | fprintf(stderr, " timing_links: %lu\n", index.timing_links.size()); | ||
147 | fprintf(stderr, " links: %lu\n", index.links.size()); | ||
148 | fprintf(stderr, " lines: %lu\n", index.lines.size()); | ||
149 | fprintf(stderr, " destinations: %lu\n", index.destinations.size()); | ||
150 | fprintf(stderr, " journey_patterns: %lu\n", index.journey_patterns.size()); | ||
151 | fprintf(stderr, " concession_financer_relations: %lu\n", index.concession_financer_relations.size()); | ||
152 | fprintf(stderr, " concession_areas: %lu\n", index.concession_areas.size()); | ||
153 | fprintf(stderr, " financers: %lu\n", index.financers.size()); | ||
154 | fprintf(stderr, " journey_pattern_timing_links: %lu\n", index.journey_pattern_timing_links.size()); | ||
155 | fprintf(stderr, " points: %lu\n", index.points.size()); | ||
156 | fprintf(stderr, " point_on_links: %lu\n", index.point_on_links.size()); | ||
157 | fprintf(stderr, " icons: %lu\n", index.icons.size()); | ||
158 | fprintf(stderr, " notices: %lu\n", index.notices.size()); | ||
159 | fprintf(stderr, " time_demand_groups: %lu\n", index.time_demand_groups.size()); | ||
160 | fprintf(stderr, " time_demand_group_run_times: %lu\n", index.time_demand_group_run_times.size()); | ||
161 | fprintf(stderr, " period_groups: %lu\n", index.period_groups.size()); | ||
162 | fprintf(stderr, " specific_days: %lu\n", index.specific_days.size()); | ||
163 | fprintf(stderr, " timetable_versions: %lu\n", index.timetable_versions.size()); | ||
164 | fprintf(stderr, " public_journeys: %lu\n", index.public_journeys.size()); | ||
165 | fprintf(stderr, " period_group_validities: %lu\n", index.period_group_validities.size()); | ||
166 | fprintf(stderr, " exceptional_operating_days: %lu\n", index.exceptional_operating_days.size()); | ||
167 | fprintf(stderr, " schedule_versions: %lu\n", index.schedule_versions.size()); | ||
168 | fprintf(stderr, " public_journey_passing_times: %lu\n", index.public_journey_passing_times.size()); | ||
169 | fprintf(stderr, " operating_days: %lu\n", index.operating_days.size()); | ||
170 | } | ||
171 | |||
172 | int main(int argc, char *argv[]) { | ||
173 | Options options = parseOptions(argc, argv); | ||
174 | |||
175 | Kv1Records records; | ||
176 | if (!parse(options.kv1_file_path, records)) { | ||
177 | fputs("Error parsing records, exiting\n", stderr); | ||
178 | return EXIT_FAILURE; | ||
179 | } | ||
180 | printParsedRecords(records); | ||
181 | fputs("Indexing...\n", stderr); | ||
182 | Kv1Index index(&records); | ||
183 | fprintf(stderr, "Indexed %lu records\n", index.size()); | ||
184 | // Only notice assignments are not indexed. If this equality is not valid, | ||
185 | // then this means that we had duplicate keys or that something else went | ||
186 | // wrong. That would really not be great. | ||
187 | assert(index.size() == records.size() - records.notice_assignments.size()); | ||
188 | printIndexSize(index); | ||
189 | fputs("Linking records...\n", stderr); | ||
190 | kv1LinkRecords(index); | ||
191 | fputs("Done linking\n", stderr); | ||
192 | |||
193 | if (options.subcommand == "joparoute"sv) jopaRoute(options, records, index); | ||
194 | if (options.subcommand == "journeyroute"sv) journeyRoute(options, records, index); | ||
195 | if (options.subcommand == "journeys"sv) journeys(options, records, index); | ||
196 | if (options.subcommand == "journeyinfo"sv) journeyInfo(options, records, index); | ||
197 | if (options.subcommand == "schedule"sv) schedule(options, records, index); | ||
198 | } | ||