Skip to content

Commit 5d0020c

Browse files
committed
Move hex decoding functions into new hex.hpp/cpp
1 parent aea98a5 commit 5d0020c

File tree

10 files changed

+109
-99
lines changed

10 files changed

+109
-99
lines changed

src/gen/gen-rivers.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "gen-rivers.hpp"
1111

1212
#include "geom-functions.hpp"
13+
#include "hex.hpp"
1314
#include "logging.hpp"
1415
#include "params.hpp"
1516
#include "pgsql.hpp"
@@ -264,7 +265,7 @@ SELECT "{id_column}", "{width_column}", "{name_column}", "{geom_column}"
264265
if (!name.empty()) {
265266
names.emplace(id, name);
266267
}
267-
auto const geom = ewkb_to_geom(decode_hex(result.get(i, 3)));
268+
auto const geom = ewkb_to_geom(util::decode_hex(result.get(i, 3)));
268269

269270
if (geom.is_linestring()) {
270271
auto const &ls = geom.get<geom::linestring_t>();

src/gen/gen-tile-builtup.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ void draw_from_db(double margin, canvas_list_t *canvas_list, pg_conn_t *conn,
6262
box.max_x(), box.max_y());
6363

6464
for (int n = 0; n < result.num_tuples(); ++n) {
65-
auto const geom = ewkb_to_geom(decode_hex(result.get(n, 0)));
65+
auto const geom = ewkb_to_geom(util::decode_hex(result.get(n, 0)));
6666
cc.canvas.draw(geom, tile);
6767
}
6868
}

src/gen/gen-tile-raster.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ void draw_from_db(double margin, unsigned int image_extent,
5050

5151
for (int n = 0; n < result.num_tuples(); ++n) {
5252
std::string param = result.get_value(n, 1);
53-
auto const geom = ewkb_to_geom(decode_hex(result.get(n, 0)));
53+
auto const geom = ewkb_to_geom(util::decode_hex(result.get(n, 0)));
5454

5555
auto const [it, success] = canvas_list->try_emplace(
5656
std::move(param), image_extent, image_buffer);

src/hex.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99

1010
#include "hex.hpp"
1111

12+
#include <array>
1213
#include <cassert>
14+
#include <stdexcept>
1315

1416
namespace util {
1517

@@ -34,4 +36,43 @@ std::string encode_hex(std::string const &in)
3436
return result;
3537
}
3638

39+
namespace {
40+
41+
constexpr std::array<char, 256> const HEX_TABLE = {
42+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
43+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
44+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
45+
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
46+
47+
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
48+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
49+
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
50+
};
51+
52+
} // anonymous namespace
53+
54+
unsigned char decode_hex_char(char c) noexcept
55+
{
56+
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index)
57+
return HEX_TABLE[static_cast<std::size_t>(static_cast<unsigned char>(c))];
58+
}
59+
60+
std::string decode_hex(std::string_view hex_string)
61+
{
62+
if (hex_string.size() % 2 != 0) {
63+
throw std::runtime_error{"Invalid wkb: Not a valid hex string"};
64+
}
65+
66+
std::string wkb;
67+
wkb.reserve(hex_string.size() / 2);
68+
69+
// NOLINTNEXTLINE(llvm-qualified-auto, readability-qualified-auto)
70+
for (auto hex = hex_string.begin(); hex != hex_string.end();) {
71+
unsigned int const c = decode_hex_char(*hex++);
72+
wkb += static_cast<char>((c << 4U) | decode_hex_char(*hex++));
73+
}
74+
75+
return wkb;
76+
}
77+
3778
} // namespace util

src/hex.hpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,19 @@ void encode_hex(std::string const &in, std::string *out);
2828
* \param in The input data.
2929
* \returns Hex encoded string.
3030
*/
31-
std::string encode_hex(std::string const &in);
31+
[[nodiscard]] std::string encode_hex(std::string const &in);
32+
33+
/**
34+
* Decode one hex character (0-9A-F or 0-9a-f) and return its value.
35+
* Returns 0 for characters that are not hex characters.
36+
*/
37+
[[nodiscard]] unsigned char decode_hex_char(char c) noexcept;
38+
39+
/**
40+
* Decode a string of hex characters. Throws an exception if the input is not
41+
* a valid hex encoding.
42+
*/
43+
[[nodiscard]] std::string decode_hex(std::string_view hex);
3244

3345
} // namespace util
3446

src/locator.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "geom-boost-adaptor.hpp"
1313
#include "geom-box.hpp"
1414
#include "geom-functions.hpp"
15+
#include "hex.hpp"
1516
#include "overloaded.hpp"
1617
#include "pgsql-capabilities.hpp"
1718
#include "pgsql.hpp"
@@ -60,7 +61,7 @@ void locator_t::add_regions(pg_conn_t const &db_connection,
6061

6162
for (int n = 0; n < result.num_tuples(); ++n) {
6263
std::string const name = result.get_value(n, 0);
63-
auto geometry = ewkb_to_geom(decode_hex(result.get(n, 1)));
64+
auto geometry = ewkb_to_geom(util::decode_hex(result.get(n, 1)));
6465

6566
if (geometry.srid() == 4326) {
6667
add_region(name, geometry);

src/wkb.cpp

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -575,42 +575,3 @@ geom::geometry_t ewkb_to_geom(std::string_view wkb)
575575

576576
return geom;
577577
}
578-
579-
namespace {
580-
581-
constexpr std::array<char, 256> const HEX_TABLE = {
582-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
583-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
584-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
585-
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
586-
587-
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
588-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
589-
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
590-
};
591-
592-
} // anonymous namespace
593-
594-
unsigned char decode_hex_char(char c) noexcept
595-
{
596-
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index)
597-
return HEX_TABLE[static_cast<std::size_t>(static_cast<unsigned char>(c))];
598-
}
599-
600-
std::string decode_hex(std::string_view hex_string)
601-
{
602-
if (hex_string.size() % 2 != 0) {
603-
throw std::runtime_error{"Invalid wkb: Not a valid hex string"};
604-
}
605-
606-
std::string wkb;
607-
wkb.reserve(hex_string.size() / 2);
608-
609-
// NOLINTNEXTLINE(llvm-qualified-auto, readability-qualified-auto)
610-
for (auto hex = hex_string.begin(); hex != hex_string.end();) {
611-
unsigned int const c = decode_hex_char(*hex++);
612-
wkb += static_cast<char>((c << 4U) | decode_hex_char(*hex++));
613-
}
614-
615-
return wkb;
616-
}

src/wkb.hpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,4 @@
4040
*/
4141
[[nodiscard]] geom::geometry_t ewkb_to_geom(std::string_view wkb);
4242

43-
/**
44-
* Decode one hex character (0-9A-F or 0-9a-f) and return its value.
45-
* Returns 0 for characters that are not hex characters.
46-
*/
47-
[[nodiscard]] unsigned char decode_hex_char(char c) noexcept;
48-
49-
/**
50-
* Decode a string of hex characters. Throws an exception if the input is not
51-
* a valid hex encoding.
52-
*/
53-
[[nodiscard]] std::string decode_hex(std::string_view hex);
54-
5543
#endif // OSM2PGSQL_WKB_HPP

tests/test-hex.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,52 @@ TEST_CASE("hex encoding an empty string doesn't change output string", "[NoDB]")
3535
util::encode_hex("", &result);
3636
REQUIRE(result == "foo");
3737
}
38+
39+
TEST_CASE("wkb hex decode of valid and invalid hex characters")
40+
{
41+
REQUIRE(util::decode_hex_char('0') == 0);
42+
REQUIRE(util::decode_hex_char('9') == 9);
43+
REQUIRE(util::decode_hex_char('a') == 0x0a);
44+
REQUIRE(util::decode_hex_char('f') == 0x0f);
45+
REQUIRE(util::decode_hex_char('A') == 0x0a);
46+
REQUIRE(util::decode_hex_char('F') == 0x0f);
47+
REQUIRE(util::decode_hex_char('#') == 0);
48+
REQUIRE(util::decode_hex_char('@') == 0);
49+
REQUIRE(util::decode_hex_char('g') == 0);
50+
REQUIRE(util::decode_hex_char('G') == 0);
51+
REQUIRE(util::decode_hex_char(0x7f) == 0);
52+
}
53+
54+
TEST_CASE("wkb hex decode of valid hex string")
55+
{
56+
std::string const hex{"0001020F1099FF"};
57+
std::string const data = {0x00,
58+
0x01,
59+
0x02,
60+
0x0f,
61+
0x10,
62+
static_cast<char>(0x99),
63+
static_cast<char>(0xff)};
64+
65+
auto const result = util::decode_hex(hex);
66+
REQUIRE(result.size() == hex.size() / 2);
67+
REQUIRE(result == data);
68+
}
69+
70+
TEST_CASE("wkb hex decode of empty string is okay")
71+
{
72+
std::string const hex{};
73+
REQUIRE(util::decode_hex(hex).empty());
74+
}
75+
76+
TEST_CASE("wkb hex decode of string with odd number of characters fails")
77+
{
78+
REQUIRE_THROWS(util::decode_hex("a"));
79+
REQUIRE_THROWS(util::decode_hex("abc"));
80+
REQUIRE_THROWS(util::decode_hex("00000"));
81+
}
82+
83+
TEST_CASE("hex encode and decode") {
84+
std::string const str{"something somewhere"};
85+
REQUIRE(util::decode_hex(util::encode_hex(str)) == str);
86+
}

tests/test-wkb.cpp

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -189,46 +189,3 @@ TEST_CASE("wkb: geometrycollection", "[NoDB]")
189189

190190
TEST_CASE("wkb: invalid", "[NoDB]") { REQUIRE_THROWS(ewkb_to_geom("INVALID")); }
191191

192-
TEST_CASE("wkb hex decode of valid and invalid hex characters")
193-
{
194-
REQUIRE(decode_hex_char('0') == 0);
195-
REQUIRE(decode_hex_char('9') == 9);
196-
REQUIRE(decode_hex_char('a') == 0x0a);
197-
REQUIRE(decode_hex_char('f') == 0x0f);
198-
REQUIRE(decode_hex_char('A') == 0x0a);
199-
REQUIRE(decode_hex_char('F') == 0x0f);
200-
REQUIRE(decode_hex_char('#') == 0);
201-
REQUIRE(decode_hex_char('@') == 0);
202-
REQUIRE(decode_hex_char('g') == 0);
203-
REQUIRE(decode_hex_char('G') == 0);
204-
REQUIRE(decode_hex_char(0x7f) == 0);
205-
}
206-
207-
TEST_CASE("wkb hex decode of valid hex string")
208-
{
209-
std::string const hex{"0001020F1099FF"};
210-
std::string const data = {0x00,
211-
0x01,
212-
0x02,
213-
0x0f,
214-
0x10,
215-
static_cast<char>(0x99),
216-
static_cast<char>(0xff)};
217-
218-
auto const result = decode_hex(hex);
219-
REQUIRE(result.size() == hex.size() / 2);
220-
REQUIRE(result == data);
221-
}
222-
223-
TEST_CASE("wkb hex decode of empty string is okay")
224-
{
225-
std::string const hex{};
226-
REQUIRE(decode_hex(hex).empty());
227-
}
228-
229-
TEST_CASE("wkb hex decode of string with odd number of characters fails")
230-
{
231-
REQUIRE_THROWS(decode_hex("a"));
232-
REQUIRE_THROWS(decode_hex("abc"));
233-
REQUIRE_THROWS(decode_hex("00000"));
234-
}

0 commit comments

Comments
 (0)