aboutsummaryrefslogtreecommitdiffstats
path: root/src/querykv1/main.cpp
diff options
context:
space:
mode:
authorLibravatar Rutger Broekhoff2024-05-02 20:27:40 +0200
committerLibravatar Rutger Broekhoff2024-05-02 20:27:40 +0200
commit17a3ea880402338420699e03bcb24181e4ff3924 (patch)
treeda666ef91e0b60d20aa0b01529644c136fd1f4ab /src/querykv1/main.cpp
downloadoeuf-17a3ea880402338420699e03bcb24181e4ff3924.tar.gz
oeuf-17a3ea880402338420699e03bcb24181e4ff3924.zip
Initial commit
Based on dc4ba6a
Diffstat (limited to 'src/querykv1/main.cpp')
-rw-r--r--src/querykv1/main.cpp198
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
21using namespace std::string_view_literals;
22
23using TimingClock = std::conditional_t<
24 std::chrono::high_resolution_clock::is_steady,
25 std::chrono::high_resolution_clock,
26 std::chrono::steady_clock>;
27
28std::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
58std::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
84bool 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
108void 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
141void 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
172int 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}