mirror of
https://github.com/protomaps/PMTiles.git
synced 2026-02-04 10:51:07 +00:00
C++: throw exceptions in overflow cases
This commit is contained in:
@@ -311,14 +311,14 @@ void rotate(int64_t n, int64_t &x, int64_t &y, int64_t rx, int64_t ry) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
zxy t_on_level(uint8_t z, uint64_t pos) {
|
zxy t_on_level(uint8_t z, uint64_t pos) {
|
||||||
int64_t n = 1 << z;
|
int64_t n = 1LL << z;
|
||||||
int64_t rx, ry, s, t = pos;
|
int64_t rx, ry, s, t = pos;
|
||||||
int64_t tx = 0;
|
int64_t tx = 0;
|
||||||
int64_t ty = 0;
|
int64_t ty = 0;
|
||||||
|
|
||||||
for (s = 1; s < n; s *= 2) {
|
for (s = 1; s < n; s *= 2) {
|
||||||
rx = 1 & (t / 2);
|
rx = 1LL & (t / 2);
|
||||||
ry = 1 & (t ^ rx);
|
ry = 1LL & (t ^ rx);
|
||||||
rotate(s, tx, ty, rx, ry);
|
rotate(s, tx, ty, rx, ry);
|
||||||
tx += s * rx;
|
tx += s * rx;
|
||||||
ty += s * ry;
|
ty += s * ry;
|
||||||
@@ -385,28 +385,33 @@ entryv3 find_tile(const std::vector<entryv3> &entries, uint64_t tile_id) {
|
|||||||
|
|
||||||
inline zxy tileid_to_zxy(uint64_t tileid) {
|
inline zxy tileid_to_zxy(uint64_t tileid) {
|
||||||
uint64_t acc = 0;
|
uint64_t acc = 0;
|
||||||
uint8_t t_z = 0;
|
for (uint8_t t_z = 0; t_z < 32; t_z++) {
|
||||||
while (true) {
|
|
||||||
uint64_t num_tiles = (1LL << t_z) * (1LL << t_z);
|
uint64_t num_tiles = (1LL << t_z) * (1LL << t_z);
|
||||||
if (acc + num_tiles > tileid) {
|
if (acc + num_tiles > tileid) {
|
||||||
return t_on_level(t_z, tileid - acc);
|
return t_on_level(t_z, tileid - acc);
|
||||||
}
|
}
|
||||||
acc += num_tiles;
|
acc += num_tiles;
|
||||||
t_z++;
|
|
||||||
}
|
}
|
||||||
|
throw std::overflow_error("tile zoom exceeds 64-bit limit");
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint64_t zxy_to_tileid(uint8_t z, uint32_t x, uint32_t y) {
|
inline uint64_t zxy_to_tileid(uint8_t z, uint32_t x, uint32_t y) {
|
||||||
|
if (z > 31) {
|
||||||
|
throw std::overflow_error("tile zoom exceeds 64-bit limit");
|
||||||
|
}
|
||||||
|
if (x > (1 << z) - 1 || y > (1 << z) - 1) {
|
||||||
|
throw std::overflow_error("tile x/y outside zoom level bounds");
|
||||||
|
}
|
||||||
uint64_t acc = 0;
|
uint64_t acc = 0;
|
||||||
for (uint8_t t_z = 0; t_z < z; t_z++) acc += (1LL << t_z) * (1LL << t_z);
|
for (uint8_t t_z = 0; t_z < z; t_z++) acc += (1LL << t_z) * (1LL << t_z);
|
||||||
int64_t n = 1 << z;
|
int64_t n = 1LL << z;
|
||||||
int64_t rx, ry, s, d = 0;
|
int64_t rx, ry, s, d = 0;
|
||||||
int64_t tx = x;
|
int64_t tx = x;
|
||||||
int64_t ty = y;
|
int64_t ty = y;
|
||||||
for (s = n / 2; s > 0; s /= 2) {
|
for (s = n / 2; s > 0; s /= 2) {
|
||||||
rx = (tx & s) > 0;
|
rx = (tx & s) > 0;
|
||||||
ry = (ty & s) > 0;
|
ry = (ty & s) > 0;
|
||||||
d += s * s * ((3 * rx) ^ ry);
|
d += s * s * ((3LL * rx) ^ ry);
|
||||||
rotate(s, tx, ty, rx, ry);
|
rotate(s, tx, ty, rx, ry);
|
||||||
}
|
}
|
||||||
return acc + d;
|
return acc + d;
|
||||||
|
|||||||
37
cpp/test.cpp
37
cpp/test.cpp
@@ -46,7 +46,7 @@ MU_TEST(test_zxy_to_tileid) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(test_roundtrip) {
|
MU_TEST(test_roundtrip) {
|
||||||
for (int z = 0; z < 25; z++) {
|
for (int z = 0; z < 32; z++) {
|
||||||
uint64_t dim = (1 << z) - 1;
|
uint64_t dim = (1 << z) - 1;
|
||||||
auto tl = tileid_to_zxy(zxy_to_tileid(z, 0, 0));
|
auto tl = tileid_to_zxy(zxy_to_tileid(z, 0, 0));
|
||||||
mu_check(tl.z == z);
|
mu_check(tl.z == z);
|
||||||
@@ -65,6 +65,41 @@ MU_TEST(test_roundtrip) {
|
|||||||
mu_check(br.x == dim);
|
mu_check(br.x == dim);
|
||||||
mu_check(br.y == dim);
|
mu_check(br.y == dim);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool caught = false;
|
||||||
|
try {
|
||||||
|
tileid_to_zxy(18446744073709551615ULL);
|
||||||
|
} catch (const std::runtime_error &e) {
|
||||||
|
caught = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
mu_check(caught);
|
||||||
|
|
||||||
|
caught = false;
|
||||||
|
try {
|
||||||
|
zxy_to_tileid(32, 0, 0);
|
||||||
|
} catch (const std::runtime_error &e) {
|
||||||
|
caught = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
mu_check(caught);
|
||||||
|
|
||||||
|
caught = false;
|
||||||
|
try {
|
||||||
|
zxy_to_tileid(0, 1, 1);
|
||||||
|
} catch (const std::runtime_error &e) {
|
||||||
|
caught = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
mu_check(caught);
|
||||||
|
|
||||||
|
caught = false;
|
||||||
|
try {
|
||||||
|
zxy_to_tileid(31, 2147483647ULL + 1, 2147483647ULL + 1);
|
||||||
|
} catch (const std::runtime_error &e) {
|
||||||
|
caught = true;
|
||||||
|
}
|
||||||
|
mu_check(caught);
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(test_serialize_directory) {
|
MU_TEST(test_serialize_directory) {
|
||||||
|
|||||||
Reference in New Issue
Block a user