-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdecode.cc
87 lines (72 loc) · 2.82 KB
/
decode.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include <cassert>
#include <cstdio>
#include <fstream>
#include <ios>
#include <iostream>
#include <memory>
#include <protozero/pbf_message.hpp>
#include <protozero/pbf_reader.hpp>
#include <protozero/varint.hpp>
#include "bundle_limit.h"
#include "csv.h"
#include "mapping.h"
#include "tags.h"
using AutoclosingFile = std::unique_ptr<::FILE, decltype(&::fclose)>;
void writetoFile(const std::string &bytes, ::FILE *FileToWrite) {
const auto count = ::fwrite(bytes.data(), sizeof(char), bytes.size(), FileToWrite);
if (count != bytes.size())
std::quick_exit(EXIT_FAILURE);
}
int main(int argc, const char *argv[]) {
if (argc != 3) {
std::cout << "Usage: provide a pbf file to decode and a file to write to\n e.g.: " << argv[0] << " ./file.pbf decoded.csv" << std::endl;
std::exit(0);
}
auto out_file = argv[2];
AutoclosingFile decodedFile(::fopen(out_file, "wb"), &::fclose);
if (!decodedFile)
std::quick_exit(EXIT_FAILURE);
auto infile = mapping::fromReadOnlyFile(argv[1]);
const auto *const end = reinterpret_cast<const char *>(infile.get_address()) + infile.get_size();
const auto *pos = reinterpret_cast<const char *>(infile.get_address());
// create vector and allocate the bundle limit size
std::vector<csv::Line> decodedLines(bundle_limit::limit);
while (pos != end) {
uint64_t chunksize = protozero::decode_varint(&pos, end);
protozero::pbf_reader bundle(pos, chunksize);
// iterate over message, reading out packed values in the order they were
// written: from nodes, to nodes and speeds
std::size_t fromNodesLength = 0;
bundle.next(tags::Group::fromNodes);
auto pi = bundle.get_packed_uint64();
for (const auto &fromVal : pi) {
decodedLines[fromNodesLength].from = fromVal;
fromNodesLength++;
}
std::size_t toNodesLength = 0;
bundle.next(tags::Group::toNodes);
pi = bundle.get_packed_uint64();
for (const auto &toVal : pi) {
decodedLines[toNodesLength].to = toVal;
toNodesLength++;
}
std::size_t speedsLength = 0;
bundle.next(tags::Group::speeds);
auto speedsField = bundle.get_packed_uint32();
for (const auto &speedVal : speedsField) {
decodedLines[speedsLength].speed = speedVal;
speedsLength++;
}
assert(fromNodesLength == toNodesLength);
assert(toNodesLength == speedsLength);
// in case this is the flushed message at the end of a file, shrink the vector
// to num of values decoded to get rid of null preallocated values in the vector
decodedLines.resize(speedsLength);
for (const auto &line : decodedLines) {
writetoFile(std::to_string(line.from) + ",", decodedFile.get());
writetoFile(std::to_string(line.to) + ",", decodedFile.get());
writetoFile(std::to_string(line.speed) + "\n", decodedFile.get());
}
pos += chunksize;
}
}