12
12
#include " cgimap/backend/apidb/utils.hpp"
13
13
14
14
#include < chrono>
15
+ #include < charconv>
15
16
16
17
17
18
namespace {
@@ -122,10 +123,12 @@ struct comments_columns
122
123
123
124
// -------------------------------------------------------------------------------------
124
125
125
- void extract_elem (const pqxx_tuple &row, element_info &elem ,
126
+ [[nodiscard]] element_info extract_elem (const pqxx_tuple &row,
126
127
std::map<osm_changeset_id_t , changeset> &changeset_cache,
127
128
const elem_columns& col) {
128
129
130
+ element_info elem;
131
+
129
132
elem.id = row[col.id_col ].as <osm_nwr_id_t >();
130
133
elem.version = row[col.version_col ].as <int >();
131
134
elem.timestamp = row[col.timestamp_col ].c_str ();
@@ -141,6 +144,7 @@ void extract_elem(const pqxx_tuple &row, element_info &elem,
141
144
elem.uid = {};
142
145
elem.display_name = {};
143
146
}
147
+ return elem;
144
148
}
145
149
146
150
template <typename T>
@@ -152,10 +156,12 @@ std::optional<T> extract_optional(const pqxx_field &f) {
152
156
}
153
157
}
154
158
155
- void extract_changeset (const pqxx_tuple &row,
156
- changeset_info &elem,
159
+ [[nodiscard]] changeset_info extract_changeset (const pqxx_tuple &row,
157
160
std::map<osm_changeset_id_t , changeset> &changeset_cache,
158
161
const changeset_columns& col) {
162
+
163
+ changeset_info elem;
164
+
159
165
elem.id = row[col.id_col ].as <osm_changeset_id_t >();
160
166
elem.created_at = row[col.created_at_col ].c_str ();
161
167
elem.closed_at = row[col.closed_at_col ].c_str ();
@@ -185,30 +191,50 @@ void extract_changeset(const pqxx_tuple &row,
185
191
}
186
192
187
193
elem.num_changes = row[col.num_changes_col ].as <size_t >();
194
+
195
+ return elem;
188
196
}
189
197
190
- void extract_tags (const pqxx_tuple &row, tags_t &tags, const tag_columns& col) {
191
- tags.clear ();
198
+ [[nodiscard]] tags_t extract_tags (const pqxx_tuple &row, const tag_columns& col) {
199
+
200
+ tags_t tags;
192
201
193
202
auto keys = psql_array_to_vector (row[col.tag_k_col ].c_str ());
194
203
auto values = psql_array_to_vector (row[col.tag_v_col ].c_str ());
195
204
196
- if (keys.size ()!= values.size ()) {
205
+ if (keys.size () != values.size ()) {
197
206
throw std::runtime_error (" Mismatch in tags key and value size" );
198
207
}
199
208
209
+ tags.reserve (keys.size ());
210
+
200
211
for (std::size_t i=0 ; i<keys.size (); i++)
201
212
tags.push_back (std::make_pair (keys[i], values[i]));
213
+
214
+ return tags;
202
215
}
203
216
204
- struct way ;
205
- struct relation ;
217
+ [[nodiscard]] nodes_t extract_nodes (const pqxx_tuple &row, const way_extra_columns& col) {
218
+
219
+ nodes_t nodes;
206
220
207
- void extract_nodes (const pqxx_tuple &row, nodes_t &nodes, const way_extra_columns& col) {
208
- nodes.clear ();
209
221
auto ids = psql_array_to_vector (row[col.node_ids_col ].c_str ());
210
- for (const auto & id : ids)
211
- nodes.push_back (std::stol (id));
222
+
223
+ nodes.reserve (ids.size ());
224
+
225
+ for (const auto & id : ids) {
226
+ osm_nwr_id_t node;
227
+
228
+ auto [_, ec] = std::from_chars (id.data (), id.data () + id.size (), node);
229
+
230
+ if (ec != std::errc ()) {
231
+ throw std::runtime_error (" Node id conversion to integer failed" );
232
+ }
233
+
234
+ nodes.push_back (node);
235
+ }
236
+
237
+ return nodes;
212
238
}
213
239
214
240
element_type type_from_name (const char *name) {
@@ -239,56 +265,90 @@ element_type type_from_name(const char *name) {
239
265
return type;
240
266
}
241
267
242
- struct relation ;
268
+ [[nodiscard]] members_t extract_members ( const pqxx_tuple &row, const relation_extra_columns& col) {
243
269
244
- void extract_members (const pqxx_tuple &row, members_t &members, const relation_extra_columns& col) {
245
- member_info member;
246
- members.clear ();
270
+ members_t members;
247
271
248
272
auto types = psql_array_to_vector (row[col.member_types_col ].c_str ());
249
273
auto ids = psql_array_to_vector (row[col.member_ids_col ].c_str ());
250
274
auto roles = psql_array_to_vector (row[col.member_roles_col ].c_str ());
251
275
252
- if (types.size ()!=ids.size () || ids.size ()!=roles.size ()) {
276
+ if (types.size () != ids.size () ||
277
+ ids.size () != roles.size ()) {
253
278
throw std::runtime_error (" Mismatch in members types, ids and roles size" );
254
279
}
255
280
281
+ members.reserve (ids.size ());
282
+
256
283
for (std::size_t i=0 ; i<ids.size (); i++) {
284
+ member_info member;
257
285
member.type = type_from_name (types[i].c_str ());
258
- member.ref = std::stol (ids[i]);
286
+
287
+ {
288
+ auto [_, ec] = std::from_chars (ids[i].data (), ids[i].data () + ids[i].size (), member.ref );
289
+
290
+ if (ec != std::errc ()) {
291
+ throw std::runtime_error (" Member ref conversion to integer failed" );
292
+ }
293
+ }
294
+
259
295
member.role = roles[i];
260
296
members.push_back (member);
261
297
}
298
+
299
+ return members;
262
300
}
263
301
264
- void extract_comments (const pqxx_tuple &row, comments_t &comments , const comments_columns& col) {
265
- changeset_comment_info comment;
266
- comments. clear () ;
302
+ [[nodiscard]] comments_t extract_comments (const pqxx_tuple &row, const comments_columns& col) {
303
+
304
+ comments_t comments;
267
305
268
306
auto id = psql_array_to_vector (row[col.comment_id_col ].c_str ());
269
307
auto author_id = psql_array_to_vector (row[col.comment_author_id_col ].c_str ());
270
308
auto display_name = psql_array_to_vector (row[col.comment_display_name_col ].c_str ());
271
309
auto body = psql_array_to_vector (row[col.comment_body_col ].c_str ());
272
310
auto created_at = psql_array_to_vector (row[col.comment_created_at_col ].c_str ());
273
311
274
- if (id.size ()!=author_id.size () || author_id.size ()!=display_name.size ()
275
- || display_name.size ()!=body.size () || body.size ()!=created_at.size ()) {
312
+ if (id.size () != author_id.size () ||
313
+ author_id.size () != display_name.size () ||
314
+ display_name.size () != body.size () ||
315
+ body.size () != created_at.size ()) {
276
316
throw std::runtime_error (" Mismatch in comments author_id, display_name, body and created_at size" );
277
317
}
278
318
319
+ comments.reserve (id.size ());
320
+
279
321
for (std::size_t i=0 ; i<id.size (); i++) {
280
- comment.id = std::stol (id[i]);
281
- comment.author_id = std::stol (author_id[i]);
322
+
323
+ changeset_comment_info comment;
324
+
325
+ {
326
+ auto [_, ec] = std::from_chars (id[i].data (), id[i].data () + id[i].size (), comment.id );
327
+
328
+ if (ec != std::errc ()) {
329
+ throw std::runtime_error (" Comment id conversion to integer failed" );
330
+ }
331
+ }
332
+
333
+ {
334
+ auto [_, ec] = std::from_chars (author_id[i].data (), author_id[i].data () + author_id[i].size (), comment.author_id );
335
+
336
+ if (ec != std::errc ()) {
337
+ throw std::runtime_error (" Author id conversion to integer failed" );
338
+ }
339
+ }
340
+
282
341
comment.author_display_name = display_name[i];
283
342
comment.body = body[i];
284
343
comment.created_at = created_at[i];
285
344
comments.push_back (comment);
286
345
}
346
+
347
+ return comments;
287
348
}
288
349
289
350
290
351
struct node {
291
-
292
352
using extra_columns = node_extra_columns;
293
353
294
354
struct extra_info {
@@ -306,13 +366,12 @@ struct node {
306
366
};
307
367
308
368
struct way {
309
-
310
369
using extra_columns = way_extra_columns;
311
370
312
371
struct extra_info {
313
372
nodes_t nodes;
314
373
inline void extract (const pqxx_tuple &row, const extra_columns& col) {
315
- extract_nodes (row, nodes , col);
374
+ nodes = extract_nodes (row, col);
316
375
}
317
376
};
318
377
@@ -324,13 +383,12 @@ struct way {
324
383
};
325
384
326
385
struct relation {
327
-
328
386
using extra_columns = relation_extra_columns;
329
387
330
388
struct extra_info {
331
389
members_t members;
332
390
inline void extract (const pqxx_tuple &row, const extra_columns& col) {
333
- extract_members (row, members , col);
391
+ members = extract_members (row, col);
334
392
}
335
393
};
336
394
@@ -347,18 +405,15 @@ void extract(
347
405
std::function<void (const element_info&)> notify,
348
406
std::map<osm_changeset_id_t, changeset> &cc) {
349
407
350
- element_info elem;
351
- typename T::extra_info extra;
352
- typename T::extra_columns extra_cols (rows);
353
- tags_t tags;
354
-
408
+ const typename T::extra_columns extra_cols (rows);
355
409
const elem_columns elem_cols (rows);
356
410
const tag_columns tag_cols (rows);
357
411
358
412
for (const auto &row : rows) {
359
- extract_elem (row, elem, cc, elem_cols);
413
+ typename T::extra_info extra;
414
+ auto elem = extract_elem (row, cc, elem_cols);
360
415
extra.extract (row, extra_cols);
361
- extract_tags (row, tags , tag_cols);
416
+ auto tags = extract_tags (row, tag_cols);
362
417
if (notify)
363
418
notify (elem); // let callback function know about a new element we're processing
364
419
T::write (formatter, elem, extra, tags);
@@ -392,21 +447,18 @@ void extract_relations(
392
447
393
448
void extract_changesets (
394
449
const pqxx::result &rows, output_formatter &formatter,
395
- std::map<osm_changeset_id_t , changeset> &cc, const std::chrono::system_clock::time_point &now,
450
+ std::map<osm_changeset_id_t , changeset> &cc,
451
+ const std::chrono::system_clock::time_point &now,
396
452
bool include_changeset_discussions) {
397
453
398
- changeset_info elem;
399
- tags_t tags;
400
- comments_t comments;
401
-
402
454
const changeset_columns changeset_cols (rows);
403
455
const comments_columns comments_cols (rows);
404
456
const tag_columns tag_cols (rows);
405
457
406
458
for (const auto &row : rows) {
407
- extract_changeset (row, elem , cc, changeset_cols);
408
- extract_tags (row, tags , tag_cols);
409
- extract_comments (row, comments , comments_cols);
459
+ auto elem = extract_changeset (row, cc, changeset_cols);
460
+ auto tags = extract_tags (row, tag_cols);
461
+ auto comments = extract_comments (row, comments_cols);
410
462
elem.comments_count = comments.size ();
411
463
formatter.write_changeset (
412
464
elem, tags, include_changeset_discussions, comments, now);
0 commit comments