Skip to content

Commit

Permalink
Remove mapbox/variant.hpp (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
louwers authored Oct 17, 2024
1 parent 88f0d88 commit 3dad9c7
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 146 deletions.
12 changes: 1 addition & 11 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,14 @@ include(FetchContent)
FetchContent_Declare(
geometry-hpp
GIT_REPOSITORY https://github.com/maplibre/geometry.hpp
GIT_TAG 1297004bd70ed281d0dc4ecac4fbc41b22e50030
GIT_TAG origin/main
EXCLUDE_FROM_ALL
)

FetchContent_MakeAvailable(geometry-hpp)

include_directories(SYSTEM ${geometry-hpp_SOURCE_DIR}/include)

FetchContent_Declare(
MapboxVariant
GIT_REPOSITORY https://github.com/mapbox/variant.git
GIT_TAG origin/master
)
FetchContent_MakeAvailable(MapboxVariant)

include_directories(SYSTEM ${mapboxvariant_SOURCE_DIR}/include)

FetchContent_Declare(
rapidjson
GIT_REPOSITORY https://github.com/Tencent/rapidjson.git
Expand All @@ -44,7 +35,6 @@ FetchContent_Declare(
FetchContent_MakeAvailable(rapidjson)
include_directories(SYSTEM ${rapidjson_SOURCE_DIR}/include)


add_executable(
test
test/test.cpp
Expand Down
5 changes: 3 additions & 2 deletions include/maplibre/geojson.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#pragma once

#include <mapbox/variant.hpp>
#include <maplibre/feature.hpp>
#include <maplibre/geometry.hpp>

#include <variant>

namespace maplibre {
namespace geojson {

Expand All @@ -24,7 +25,7 @@ using identifier = maplibre::feature::identifier;
using feature = maplibre::feature::feature<double>;
using feature_collection = maplibre::feature::feature_collection<double>;

using geojson = mapbox::util::variant<geometry, feature, feature_collection>;
using geojson = std::variant<geometry, feature, feature_collection>;

// Parse inputs of known types. Instantiations are provided for geojson, geometry, feature, and
// feature_collection.
Expand Down
23 changes: 12 additions & 11 deletions include/maplibre/geojson_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ struct to_value {
rapidjson_value result;
result.SetArray();
for (const auto &item : array) {
result.PushBack(item.visit(item, *this), allocator);
result.PushBack(std::visit(*this, item), allocator);
}
return result;
}
Expand All @@ -430,7 +430,7 @@ struct to_value {
for (const auto &property : map) {
result.AddMember(
rapidjson::GenericStringRef<char>{ property.first.data(), rapidjson::SizeType(property.first.size()) },
value::visit(property.second, *this), allocator);
std::visit(*this, property.second), allocator);
}
return result;
}
Expand All @@ -442,16 +442,17 @@ struct to_value {

template <>
rapidjson_value convert<geometry>(const geometry &element, rapidjson_allocator &allocator) {
if (element.is<empty>())
if (std::holds_alternative<empty>(element))
return rapidjson_value(rapidjson::kNullType);

rapidjson_value result(rapidjson::kObjectType);

result.AddMember("type", rapidjson::GenericStringRef<char>{ geometry::visit(element, to_type()) }, allocator);
result.AddMember("type", rapidjson::GenericStringRef<char>{ std::visit(to_type(), element) }, allocator);

result.AddMember(
rapidjson::GenericStringRef<char>{ element.is<geometry_collection>() ? "geometries" : "coordinates" },
geometry::visit(element, to_coordinates_or_geometries{ allocator }), allocator);
result.AddMember(rapidjson::GenericStringRef<char>{ std::holds_alternative<geometry_collection>(element)
? "geometries"
: "coordinates" },
std::visit(to_coordinates_or_geometries{ allocator }, element), allocator);

return result;
}
Expand All @@ -461,8 +462,8 @@ rapidjson_value convert<feature>(const feature &element, rapidjson_allocator &al
rapidjson_value result(rapidjson::kObjectType);
result.AddMember("type", "Feature", allocator);

if (!element.id.is<null_value_t>()) {
result.AddMember("id", identifier::visit(element.id, to_value{ allocator }), allocator);
if (!std::holds_alternative<null_value_t>(element.id)) {
result.AddMember("id", std::visit(to_value{ allocator }, element.id), allocator);
}

result.AddMember("geometry", convert(element.geometry, allocator), allocator);
Expand Down Expand Up @@ -491,7 +492,7 @@ rapidjson_value convert(const geojson &element, rapidjson_allocator &allocator)
}

rapidjson_value convert(const geojson &element, rapidjson_allocator &allocator) {
return geojson::visit(element, [&](const auto &alternative) { return convert(alternative, allocator); });
return std::visit([&](const auto &alternative) { return convert(alternative, allocator); }, element);
}

template <class T>
Expand All @@ -515,7 +516,7 @@ std::string stringify(const geojson &element) {
}

std::string stringify(const geojson &element) {
return geojson::visit(element, [](const auto &alternative) { return stringify(alternative); });
return std::visit([](const auto &alternative) { return stringify(alternative); }, element);
}

} // namespace geojson
Expand Down
134 changes: 79 additions & 55 deletions include/maplibre/geojson_value_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,27 @@
#include <maplibre/geojson.hpp>
#include <maplibre/geojson/value.hpp>

#include <cassert>
#include <variant>

namespace maplibre {
namespace geojson {

using error = std::runtime_error;

namespace {

template <class... Ts>
struct overloaded : Ts... {
using Ts::operator()...;
};

double getDouble(const value &numVal) {
return numVal.match([](double n) { return n; }, [](uint64_t n) { return n; }, [](int64_t n) { return n; },
[](const auto &) -> double { throw error("coordinate's value must be of a Number type"); });
return std::visit(
overloaded{ [](double n) -> double { return n; }, [](uint64_t n) -> double { return n; },
[](int64_t n) -> double { return n; },
[](const auto &) -> double { throw error("coordinate's value must be of a Number type"); } },
numVal);
}

} // namespace
Expand All @@ -22,8 +33,8 @@ T convert(const value &);

template <>
point convert<point>(const value &val) {
assert(val.is<std::shared_ptr<std::vector<value>>>());
if (!val.is<std::shared_ptr<std::vector<value>>>()) {
assert(std::holds_alternative<std::shared_ptr<std::vector<value>>>(val));
if (!std::holds_alternative<std::shared_ptr<std::vector<value>>>(val)) {
throw error("coordinates must be of an Array type");
}

Expand All @@ -37,8 +48,8 @@ point convert<point>(const value &val) {

template <typename Container>
Container convert(const value &val) {
assert(val.is<std::shared_ptr<std::vector<value>>>());
if (!val.is<std::shared_ptr<std::vector<value>>>()) {
assert(std::holds_alternative<std::shared_ptr<std::vector<value>>>(val));
if (!std::holds_alternative<std::shared_ptr<std::vector<value>>>(val)) {
throw error("coordinates must be of an Array type");
}

Expand All @@ -64,7 +75,7 @@ geometry convert<geometry>(const value &val) {
}

const auto &typeValue = typeIt->second;
if (!typeValue.is<std::string>()) {
if (!std::holds_alternative<std::string>(typeValue)) {
throw error("Geometry 'type' property must be of a String type");
}

Expand Down Expand Up @@ -123,7 +134,7 @@ feature convert<feature>(const value &val) {
}

const auto &typeValue = typeIt->second;
if (!typeValue.is<std::string>()) {
if (!std::holds_alternative<std::string>(typeValue)) {
throw error("Feature 'type' property must be of a String type");
}

Expand All @@ -139,17 +150,19 @@ feature convert<feature>(const value &val) {
feature result{ convert<geometry>(geometryIt->second) };
auto idIt = valueObject->find("id");
if (idIt != valueObject->end()) {
result.id = idIt->second.match(
[](const std::string &string) -> identifier { return { string }; },
[](int64_t number) -> identifier { return { number }; },
[](uint64_t number) -> identifier { return { number }; },
[](double number) -> identifier { return { number }; },
[](const auto &) -> identifier { throw error("Feature id must be a string or number"); });
result.id = std::visit(
overloaded{ [](const std::string &string) -> identifier { return { string }; },
[](int64_t number) -> identifier { return { number }; },
[](uint64_t number) -> identifier { return { number }; },
[](double number) -> identifier { return { number }; },
[](const auto &) -> identifier { throw error("Feature id must be a string or number"); } },
idIt->second);
}

auto propertiesIt = valueObject->find("properties");
if (propertiesIt != valueObject->end() && !propertiesIt->second.is<maplibre::geojson::null_value_t>()) {
if (!propertiesIt->second.is<value::object_ptr_type>()) {
if (propertiesIt != valueObject->end() &&
!std::holds_alternative<maplibre::geojson::null_value_t>(propertiesIt->second)) {
if (!std::holds_alternative<value::object_ptr_type>(propertiesIt->second)) {
throw error("properties must be an object");
}
result.properties = *propertiesIt->second.getObject();
Expand All @@ -171,7 +184,7 @@ geojson convert<geojson>(const value &val) {
}

const auto &typeValue = typeIt->second;
if (!typeValue.is<std::string>()) {
if (!std::holds_alternative<std::string>(typeValue)) {
throw error("GeoJSON 'type' property must be of a String type");
}

Expand Down Expand Up @@ -205,14 +218,15 @@ geojson convert<geojson>(const value &val) {
template feature_collection convert<feature_collection>(const value &);

geojson convert(const value &val) {
return val.match(
[](const null_value_t &) -> geojson { return geometry{}; },
[](const std::string &jsonString) { return jsonString == "null" ? geometry{} : parse(jsonString); },
[](const value::object_type &jsonObject) {
return convert<geojson>(static_cast<const maplibre::geojson::value &>(jsonObject));
},
[](const value::object_ptr_type obj) { return convert<geojson>(*obj); },
[](const auto &) -> geojson { throw error("Invalid GeoJSON value was provided."); });
return std::visit(
overloaded{ [](const null_value_t &) -> geojson { return geometry{}; },
[](const std::string &jsonString) { return jsonString == "null" ? geometry{} : parse(jsonString); },
[](const value::object_type &jsonObject) {
return convert<geojson>(static_cast<const maplibre::geojson::value &>(jsonObject));
},
[](const value::object_ptr_type obj) { return convert<geojson>(*obj); },
[](const auto &) -> geojson { throw error("Invalid GeoJSON value was provided."); } },
val);
}

value convert(const point &p) {
Expand All @@ -231,30 +245,36 @@ value convert(const Cont &points) {

template <>
value convert(const geometry &geom) {
return geom.match(
[](const empty &) { return value{}; },
[](const point &p) { return value::object_type{ { "type", "Point" }, { "coordinates", convert(p) } }; },
[](const multi_point &mp) {
return value::object_type{ { "type", "MultiPoint" }, { "coordinates", convert(mp) } };
},
[](const line_string &ls) {
return value::object_type{ { "type", "LineString" }, { "coordinates", convert(ls) } };
},
[](const multi_line_string &mls) {
return value::object_type{ { "type", "MultiLineString" }, { "coordinates", convert(mls) } };
},
[](const polygon &pol) { return value::object_type{ { "type", "Polygon" }, { "coordinates", convert(pol) } }; },
[](const multi_polygon &mpol) {
return value::object_type{ { "type", "MultiPolygon" }, { "coordinates", convert(mpol) } };
},
[](const geometry_collection &gc) {
value::array_type geometries;
geometries.reserve(gc.size());
for (const auto &gcGeom : gc) {
geometries.push_back(convert(gcGeom));
}
return value::object_type{ { "type", "GeometryCollection" }, { "geometries", std::move(geometries) } };
});
return std::visit(
overloaded{ [](const empty &) { return value{}; },
[](const point &p) -> value {
return value::object_type{ { "type", "Point" }, { "coordinates", convert(p) } };
},
[](const multi_point &mp) -> value {
return value::object_type{ { "type", "MultiPoint" }, { "coordinates", convert(mp) } };
},
[](const line_string &ls) -> value {
return value::object_type{ { "type", "LineString" }, { "coordinates", convert(ls) } };
},
[](const multi_line_string &mls) -> value {
return value::object_type{ { "type", "MultiLineString" }, { "coordinates", convert(mls) } };
},
[](const polygon &pol) -> value {
return value::object_type{ { "type", "Polygon" }, { "coordinates", convert(pol) } };
},
[](const multi_polygon &mpol) -> value {
return value::object_type{ { "type", "MultiPolygon" }, { "coordinates", convert(mpol) } };
},
[](const geometry_collection &gc) -> value {
value::array_type geometries;
geometries.reserve(gc.size());
for (const auto &gcGeom : gc) {
geometries.push_back(convert(gcGeom));
}
return value::object_type{ { "type", "GeometryCollection" },
{ "geometries", std::move(geometries) } };
} },
geom);
}

template <>
Expand All @@ -263,10 +283,12 @@ value convert(const feature &f) {
{ "geometry", convert(f.geometry) },
{ "properties", f.properties } };

if (!f.id.is<maplibre::geojson::null_value_t>()) {
value id = f.id.match([](uint64_t n) -> value { return n; }, [](int64_t n) -> value { return n; },
[](double n) -> value { return n; }, [](std::string s) -> value { return s; },
[](const auto &) -> value { throw error("Unknown type for a Feature 'id'"); });
if (!std::holds_alternative<maplibre::geojson::null_value_t>(f.id)) {
value id =
std::visit(overloaded{ [](uint64_t n) -> value { return n; }, [](int64_t n) -> value { return n; },
[](double n) -> value { return n; }, [](std::string s) -> value { return s; },
[](const auto &) -> value { throw error("Unknown type for a Feature 'id'"); } },
f.id);
result.emplace(std::make_pair("id", std::move(id)));
}

Expand All @@ -291,8 +313,10 @@ value convert(const geojson &json) {
}

value convert(const geojson &json) {
return json.match([](const geometry &g) { return convert(g); }, [](const feature &f) { return convert(f); },
[](const feature_collection &c) { return convert(c); });
return std::visit(overloaded{ [](const geometry &g) -> value { return convert(g); },
[](const feature &f) -> value { return convert(f); },
[](const feature_collection &c) -> value { return convert(c); } },
json);
}

} // namespace geojson
Expand Down
Loading

0 comments on commit 3dad9c7

Please sign in to comment.