1 #pragma once
2
3 #include <mapbox/geometry.hpp>
4
5 #include <mapbox/variant.hpp>
6
7 #include <cstdint>
8 #include <string>
9 #include <vector>
10 #include <unordered_map>
11
12 namespace mapbox {
13 namespace feature {
14
15 struct value;
16
17 struct null_value_t
18 {
19 };
20
operator ==(const null_value_t &,const null_value_t &)21 constexpr bool operator==(const null_value_t&, const null_value_t&) { return true; }
operator !=(const null_value_t &,const null_value_t &)22 constexpr bool operator!=(const null_value_t&, const null_value_t&) { return false; }
operator <(const null_value_t &,const null_value_t &)23 constexpr bool operator<(const null_value_t&, const null_value_t&) { return false; }
24
25 constexpr null_value_t null_value = null_value_t();
26
27 // Multiple numeric types (uint64_t, int64_t, double) are present in order to support
28 // the widest possible range of JSON numbers, which do not have a maximum range.
29 // Implementations that produce `value`s should use that order for type preference,
30 // using uint64_t for positive integers, int64_t for negative integers, and double
31 // for non-integers and integers outside the range of 64 bits.
32 using value_base = mapbox::util::variant<null_value_t, bool, uint64_t, int64_t, double, std::string,
33 mapbox::util::recursive_wrapper<std::vector<value>>,
34 mapbox::util::recursive_wrapper<std::unordered_map<std::string, value>>>;
35
36 struct value : value_base
37 {
38 using value_base::value_base;
39 };
40
41 using property_map = std::unordered_map<std::string, value>;
42
43 // The same considerations and requirement for numeric types apply as for `value_base`.
44 using identifier = mapbox::util::variant<null_value_t, uint64_t, int64_t, double, std::string>;
45
46 template <class T>
47 struct feature
48 {
49 using coordinate_type = T;
50 using geometry_type = mapbox::geometry::geometry<T>; // Fully qualified to avoid GCC -fpermissive error.
51
52 geometry_type geometry;
53 property_map properties;
54 identifier id;
55
featuremapbox::feature::feature56 feature()
57 : geometry(),
58 properties(),
59 id() {}
featuremapbox::feature::feature60 feature(geometry_type const& geom_)
61 : geometry(geom_),
62 properties(),
63 id() {}
featuremapbox::feature::feature64 feature(geometry_type&& geom_)
65 : geometry(std::move(geom_)),
66 properties(),
67 id() {}
featuremapbox::feature::feature68 feature(geometry_type const& geom_, property_map const& prop_)
69 : geometry(geom_), properties(prop_), id() {}
featuremapbox::feature::feature70 feature(geometry_type&& geom_, property_map&& prop_)
71 : geometry(std::move(geom_)),
72 properties(std::move(prop_)),
73 id() {}
featuremapbox::feature::feature74 feature(geometry_type const& geom_, property_map const& prop_, identifier const& id_)
75 : geometry(geom_),
76 properties(prop_),
77 id(id_) {}
featuremapbox::feature::feature78 feature(geometry_type&& geom_, property_map&& prop_, identifier&& id_)
79 : geometry(std::move(geom_)),
80 properties(std::move(prop_)),
81 id(std::move(id_)) {}
82 };
83
84 template <class T>
operator ==(feature<T> const & lhs,feature<T> const & rhs)85 constexpr bool operator==(feature<T> const& lhs, feature<T> const& rhs)
86 {
87 return lhs.id == rhs.id && lhs.geometry == rhs.geometry && lhs.properties == rhs.properties;
88 }
89
90 template <class T>
operator !=(feature<T> const & lhs,feature<T> const & rhs)91 constexpr bool operator!=(feature<T> const& lhs, feature<T> const& rhs)
92 {
93 return !(lhs == rhs);
94 }
95
96 template <class T, template <typename...> class Cont = std::vector>
97 struct feature_collection : Cont<feature<T>>
98 {
99 using coordinate_type = T;
100 using feature_type = feature<T>;
101 using container_type = Cont<feature_type>;
102 using size_type = typename container_type::size_type;
103
104 template <class... Args>
feature_collectionmapbox::feature::feature_collection105 feature_collection(Args&&... args) : container_type(std::forward<Args>(args)...)
106 {
107 }
feature_collectionmapbox::feature::feature_collection108 feature_collection(std::initializer_list<feature_type> args)
109 : container_type(std::move(args)) {}
110 };
111
112 } // namespace feature
113 } // namespace mapbox
114