summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/src/geo/utm.cppm44
-rw-r--r--server/src/log.cpp30
-rw-r--r--server/src/log.cppm10
-rw-r--r--server/src/srv.cpp8
-rw-r--r--server/src/trace.cpp77
-rw-r--r--server/src/trace.cppm6
6 files changed, 98 insertions, 77 deletions
diff --git a/server/src/geo/utm.cppm b/server/src/geo/utm.cppm
index c58ffb4..75bba6f 100644
--- a/server/src/geo/utm.cppm
+++ b/server/src/geo/utm.cppm
@@ -110,6 +110,7 @@ using zonable_wgs84_linestring =
110// and easting (so no Norway/Svalbard exceptions). 110// and easting (so no Norway/Svalbard exceptions).
111class zone 111class zone
112{ 112{
113public:
113 // Note: calculations heavily depend on the values of the variants. 114 // Note: calculations heavily depend on the values of the variants.
114 enum class hemisphere : std::uint8_t 115 enum class hemisphere : std::uint8_t
115 { 116 {
@@ -117,23 +118,6 @@ class zone
117 southern = 1, 118 southern = 1,
118 }; 119 };
119 120
120 // Negative if in the southern hemisphere
121 // Equal to (zone_no - 1) * 2 + hemisphere
122 // In range [0, 119]
123 std::uint8_t zone_;
124
125 static constexpr auto zone_no_valid(std::uint8_t zone_no) -> bool
126 {
127 return 0 < zone_no && zone_no <= 60;
128 }
129
130 static constexpr auto from(std::uint8_t zone_no, hemisphere h) -> std::uint8_t
131 {
132 if (!zone_no_valid(zone_no))
133 throw std::invalid_argument{"invalid UTM zone number"};
134 return (zone_no - 1) * 2 + static_cast<std::uint8_t>(h);
135 }
136
137public: 121public:
138 explicit constexpr zone(std::uint8_t zone_no, hemisphere h) 122 explicit constexpr zone(std::uint8_t zone_no, hemisphere h)
139 : zone_{from(zone_no, h)} 123 : zone_{from(zone_no, h)}
@@ -196,8 +180,34 @@ public:
196 { 180 {
197 return zone_ == rhs.zone_; 181 return zone_ == rhs.zone_;
198 } 182 }
183
184private:
185 static constexpr auto zone_no_valid(std::uint8_t zone_no) -> bool
186 {
187 return 0 < zone_no && zone_no <= 60;
188 }
189
190 static constexpr auto from(std::uint8_t zone_no, enum hemisphere h)
191 -> std::uint8_t
192 {
193 if (!zone_no_valid(zone_no))
194 throw std::invalid_argument{"invalid UTM zone number"};
195 return (zone_no - 1) * 2 + static_cast<std::uint8_t>(h);
196 }
197
198 // Negative if in the southern hemisphere
199 // Equal to (zone_no - 1) * 2 + hemisphere
200 // In range [0, 119]
201 std::uint8_t zone_;
199}; 202};
200static_assert(zone::min().as_index() == 0); 203static_assert(zone::min().as_index() == 0);
201static_assert(zone::max().as_index() == 119); 204static_assert(zone::max().as_index() == 119);
202 205
206auto to_string(zone z) -> std::string
207{
208 return std::format(
209 "{} {}", z.zone_no(),
210 z.hemisphere() == zone::hemisphere::northern ? "northern" : "southern");
211}
212
203} // namespace routemon::geo::utm 213} // namespace routemon::geo::utm
diff --git a/server/src/log.cpp b/server/src/log.cpp
index bb9fde2..5953c14 100644
--- a/server/src/log.cpp
+++ b/server/src/log.cpp
@@ -30,17 +30,7 @@ auto sink::level() const -> enum level { return lvl_; }
30 30
31auto sink::set_level(enum level lvl) -> void { lvl_ = lvl; } 31auto sink::set_level(enum level lvl) -> void { lvl_ = lvl; }
32 32
33auto sink::write(tmp_message msg) -> void 33auto sink::write() -> std::osyncstream { return std::osyncstream{os_}; }
34{
35 auto sos = std::osyncstream{os_};
36 sos << "[" << msg.lvl;
37 if (!msg.component.empty())
38 sos << " " << msg.component;
39 sos << "] " << msg.txt;
40 for (auto const& [k, v] : msg.attrs)
41 sos << " " << k << "=" << std::quoted(v);
42 sos << std::endl; // we want the flush!
43}
44 34
45auto make_sink(level lvl) -> std::shared_ptr<sink> 35auto make_sink(level lvl) -> std::shared_ptr<sink>
46{ 36{
@@ -51,13 +41,17 @@ auto logger::log_at(log::level lvl, std::string_view fmt, std::format_args args)
51 -> logger& 41 -> logger&
52{ 42{
53 if (sink_->level() <= lvl) 43 if (sink_->level() <= lvl)
54 sink_->write( 44 {
55 sink::tmp_message{ 45 auto sos = sink_->write();
56 .lvl = lvl, 46 sos << "[" << lvl;
57 .component = component_, 47 if (!component_.empty())
58 .txt = std::vformat(fmt, args), 48 sos << " " << component_;
59 .attrs = attrs_, 49 sos << "] ";
60 }); 50 std::vprint_unicode(sos, fmt, args);
51 for (auto const& [k, v] : attrs_)
52 sos << " " << k << "=" << std::quoted(v);
53 sos << std::endl; // we want the flush!
54 }
61 return *this; 55 return *this;
62} 56}
63 57
diff --git a/server/src/log.cppm b/server/src/log.cppm
index dc8c2e1..87382f6 100644
--- a/server/src/log.cppm
+++ b/server/src/log.cppm
@@ -21,18 +21,10 @@ export class sink
21 friend auto make_sink(level lvl) -> std::shared_ptr<sink>; 21 friend auto make_sink(level lvl) -> std::shared_ptr<sink>;
22 22
23public: 23public:
24 struct tmp_message
25 {
26 level lvl;
27 std::string_view component;
28 std::string_view txt;
29 std::map<std::string, std::string> const& attrs;
30 };
31
32 [[nodiscard]] auto level() const -> enum level; 24 [[nodiscard]] auto level() const -> enum level;
33 auto set_level(enum level lvl) -> void; 25 auto set_level(enum level lvl) -> void;
34 26
35 auto write(tmp_message msg) -> void; 27 auto write() -> std::osyncstream;
36}; 28};
37 29
38export auto make_sink(level lvl) -> std::shared_ptr<sink>; 30export auto make_sink(level lvl) -> std::shared_ptr<sink>;
diff --git a/server/src/srv.cpp b/server/src/srv.cpp
index a901f8e..dc9c814 100644
--- a/server/src/srv.cpp
+++ b/server/src/srv.cpp
@@ -343,10 +343,10 @@ auto handler::handle_process_gpx(l0_ctx ctx, http::readable_request r)
343 auto const before_read_gpx = chrono::steady_clock::now(); 343 auto const before_read_gpx = chrono::steady_clock::now();
344 auto parse_res = 344 auto parse_res =
345 r.p->get()[bhttp::field::content_encoding] == "x-deflate-raw" 345 r.p->get()[bhttp::field::content_encoding] == "x-deflate-raw"
346 ? std::move( 346 ? std::move((co_await http::
347 (co_await http::read_request<raw_deflate_body<readable_gpx_body>>( 347 read_request<raw_deflate_body<readable_gpx_body>>(
348 ctx, std::move(r))) 348 ctx, std::move(r)))
349 .body()) 349 .body())
350 : std::move((co_await http::read_request<readable_gpx_body>( 350 : std::move((co_await http::read_request<readable_gpx_body>(
351 ctx, std::move(r))) 351 ctx, std::move(r)))
352 .body()); 352 .body());
diff --git a/server/src/trace.cpp b/server/src/trace.cpp
index e7c00d0..f2935a9 100644
--- a/server/src/trace.cpp
+++ b/server/src/trace.cpp
@@ -10,6 +10,26 @@ import :trace;
10 10
11namespace routemon::trace { 11namespace routemon::trace {
12 12
13class psrng
14{
15 mutable std::default_random_engine e_ = {};
16 mutable std::uniform_int_distribution<std::uint64_t> distr_ = {};
17 mutable std::mutex mut_ = {};
18
19public:
20 auto next() const -> std::uint64_t
21 {
22 auto lock = std::lock_guard{mut_};
23 return distr_(e_);
24 }
25
26 static auto instance() -> psrng const&
27 {
28 static auto const inst = psrng{};
29 return inst;
30 }
31};
32
13uuid7::uuid7() 33uuid7::uuid7()
14{ 34{
15 namespace chrono = std::chrono; 35 namespace chrono = std::chrono;
@@ -23,46 +43,51 @@ uuid7::uuid7()
23 if (std::countl_zero(unix_time_ms) < 16) 43 if (std::countl_zero(unix_time_ms) < 16)
24 throw std::runtime_error{"system time too great"}; 44 throw std::runtime_error{"system time too great"};
25 45
26 auto rand = std::array<unsigned char, 10>{}; 46 auto const& rng = psrng::instance();
27 int s = RAND_bytes(rand.data(), static_cast<int>(rand.size())); 47 auto const rand1 = rng.next();
28 if (s != 1) 48 auto const rand2 = rng.next();
29 {
30 unsigned long e = ERR_get_error();
31 throw std::runtime_error{std::format(
32 "failed to generate UUID(v7): {} ({}, code {})",
33 ERR_reason_error_string(e), ERR_lib_error_string(e), e)};
34 }
35 49
36 auto version = std::uint64_t{0b0111}; 50 auto version = std::uint64_t{0b0111};
37 auto variant = std::uint64_t{0b10}; 51 auto variant = std::uint64_t{0b10};
38 52
39 hi_ |= unix_time_ms << 16; 53 hi_ = unix_time_ms << 16;
40 hi_ |= version << 12; 54 hi_ |= version << 12;
41 hi_ |= std::uint64_t{rand[0]} << 4; 55 hi_ |= rand1 & 0x0000'0000'0000'0fff;
42 hi_ |= std::uint64_t{rand[1]}; 56 lo_ = variant << 62;
43 lo_ |= variant << 62; 57 lo_ |= rand2 >> 2;
44 lo_ |= std::uint64_t{rand[2]} << 54;
45 lo_ |= std::uint64_t{rand[3]} << 48;
46 lo_ |= std::uint64_t{rand[4]} << 40;
47 lo_ |= std::uint64_t{rand[5]} << 32;
48 lo_ |= std::uint64_t{rand[6]} << 24;
49 lo_ |= std::uint64_t{rand[7]} << 16;
50 lo_ |= std::uint64_t{rand[8]} << 8;
51 lo_ |= std::uint64_t{rand[9]};
52} 58}
53 59
54auto uuid7::format(std::array<char, 37>& target) -> void 60auto uuid7::format(std::span<char, 37> target) -> void
55{ 61{
62 auto hexnibs =
63 []<std::size_t n>(std::uint64_t v, std::span<char, n> s) -> void
64 {
65 for (auto i = 0uz; i < n; i++)
66 {
67 static char const hextab[16] = {
68 '0', '1', '2', '3', '4', '5', '6', '7',
69 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
70 };
71 s[i] = hextab[(v >> 4 * (n - 1 - i)) & 0xf];
72 }
73 };
74
56 auto p____hi_hi = (hi_ & 0xffff'ffff'0000'0000) >> 32; 75 auto p____hi_hi = (hi_ & 0xffff'ffff'0000'0000) >> 32;
57 auto p_hi_lo_hi = (hi_ & 0x0000'0000'ffff'0000) >> 16; 76 auto p_hi_lo_hi = (hi_ & 0x0000'0000'ffff'0000) >> 16;
58 auto p_lo_lo_hi = (hi_ & 0x0000'0000'0000'ffff) >> 0; 77 auto p_lo_lo_hi = (hi_ & 0x0000'0000'0000'ffff) >> 0;
59 auto p____hi_lo = (lo_ & 0xffff'0000'0000'0000) >> 48; 78 auto p____hi_lo = (lo_ & 0xffff'0000'0000'0000) >> 48;
60 auto p____lo_lo = (lo_ & 0x0000'ffff'ffff'ffff) >> 0; 79 auto p____lo_lo = (lo_ & 0x0000'ffff'ffff'ffff) >> 0;
61 80
62 std::format_to( 81 hexnibs(p____hi_hi, target.subspan<0, 8>());
63 target.begin(), "{:0>8x}-{:0>4x}-{:0>4x}-{:0>4x}-{:0>12x}", p____hi_hi, 82 target[8] = '-';
64 p_hi_lo_hi, p_lo_lo_hi, p____hi_lo, p____lo_lo); 83 hexnibs(p_hi_lo_hi, target.subspan<9, 4>());
65 target.back() = '\0'; 84 target[13] = '-';
85 hexnibs(p_lo_lo_hi, target.subspan<14, 4>());
86 target[18] = '-';
87 hexnibs(p____hi_lo, target.subspan<19, 4>());
88 target[23] = '-';
89 hexnibs(p____lo_lo, target.subspan<24, 12>());
90 target[36] = '\0';
66} 91}
67 92
68id::id() { uuid7{}.format(chars_); } 93id::id() { uuid7{}.format(chars_); }
diff --git a/server/src/trace.cppm b/server/src/trace.cppm
index deb84a0..fa743e1 100644
--- a/server/src/trace.cppm
+++ b/server/src/trace.cppm
@@ -7,13 +7,13 @@ namespace routemon::trace {
7 7
8class uuid7 8class uuid7
9{ 9{
10 std::uint64_t hi_ = 0; 10 std::uint64_t hi_;
11 std::uint64_t lo_ = 0; 11 std::uint64_t lo_;
12 12
13public: 13public:
14 uuid7(); 14 uuid7();
15 15
16 auto format(std::array<char, 37>& target) -> void; 16 auto format(std::span<char, 37> target) -> void;
17}; 17};
18 18
19export class id 19export class id