@@ -40,7 +40,23 @@ class feature {
4040 feature (protozero::data_view const &, layer const &);
4141
4242 GeomType getType () const { return type; }
43- mapbox::feature::value getValue (std::string const &) const ;
43+ /* *
44+ * Retrieve the value associated with a given key from the feature.
45+ *
46+ * @param key The key used to look up the corresponding value.
47+ * @param warning A pointer to a string that may be used to record any warnings that
48+ * occur during the lookup process.
49+ * The caller is responsible for managing the memory of this string.
50+ * @return The value associated with the specified key, or a null value if the key is not found.
51+ *
52+ * Note: If the lookup process encounters a duplicate key in the feature, the function will
53+ * return the value in the `values` set to which the associated tag index points to, and
54+ * will append a message to the `warning` string (if provided) to alert the caller to the
55+ * presence of the duplicate key.
56+ * The caller should ensure that the `warning` string is properly initialized
57+ * and cleaned up after use.
58+ */
59+ mapbox::feature::value getValue (std::string const &, std::string* warning = nullptr ) const ;
4460 properties_type getProperties () const ;
4561 mapbox::feature::identifier const & getID () const ;
4662 std::uint32_t getExtent () const ;
@@ -72,7 +88,7 @@ class layer {
7288 std::string name;
7389 std::uint32_t version;
7490 std::uint32_t extent;
75- std::map <std::string, std::uint32_t > keysMap;
91+ std::multimap <std::string, std::uint32_t > keysMap;
7692 std::vector<std::reference_wrapper<const std::string>> keys;
7793 std::vector<protozero::data_view> values;
7894 std::vector<protozero::data_view> features;
@@ -153,23 +169,19 @@ inline feature::feature(protozero::data_view const& feature_view, layer const& l
153169 }
154170}
155171
156- inline mapbox::feature::value feature::getValue (const std::string& key) const {
157- auto keyIter = layer_.keysMap .find (key);
158- if (keyIter == layer_.keysMap .end ()) {
172+ inline mapbox::feature::value feature::getValue (const std::string& key, std::string* warning ) const {
173+ const auto key_range = layer_.keysMap .equal_range (key);
174+ const auto key_count = std::distance (key_range.first , key_range.second ) ;
175+ if (key_count < 1 ) {
159176 return mapbox::feature::null_value;
160177 }
161178
162179 const auto values_count = layer_.values .size ();
163- const auto keymap_count = layer_.keysMap .size ();
164180 auto start_itr = tags_iter.begin ();
165181 const auto end_itr = tags_iter.end ();
166182 while (start_itr != end_itr) {
167183 std::uint32_t tag_key = static_cast <std::uint32_t >(*start_itr++);
168184
169- if (keymap_count <= tag_key) {
170- throw std::runtime_error (" feature referenced out of range key" );
171- }
172-
173185 if (start_itr == end_itr) {
174186 throw std::runtime_error (" uneven number of feature tag ids" );
175187 }
@@ -179,7 +191,19 @@ inline mapbox::feature::value feature::getValue(const std::string& key) const {
179191 throw std::runtime_error (" feature referenced out of range value" );
180192 }
181193
182- if (tag_key == keyIter->second ) {
194+ bool key_found = false ;
195+ for (auto i = key_range.first ; i != key_range.second ; ++i) {
196+ if (i->second == tag_key) {
197+ key_found = true ;
198+ break ;
199+ }
200+ }
201+
202+ if (key_found) {
203+ // Continue process with case when same keys having multiple tag ids.
204+ if (key_count > 1 && warning) {
205+ *warning = std::string (" duplicate keys with different tag ids are found" );
206+ }
183207 return parseValue (layer_.values [tag_val]);
184208 }
185209 }
@@ -403,8 +427,8 @@ inline layer::layer(protozero::data_view const& layer_view) :
403427 {
404428 // We want to keep the keys in the order of the vector tile
405429 // https://github.com/mapbox/mapbox-gl-native/pull/5183
406- auto iter = keysMap.emplace (layer_pbf.get_string (), keysMap .size ());
407- keys.emplace_back (std::reference_wrapper<const std::string>(iter. first ->first ));
430+ auto iter = keysMap.emplace (layer_pbf.get_string (), keys .size ());
431+ keys.emplace_back (std::reference_wrapper<const std::string>(iter->first ));
408432 }
409433 break ;
410434 case LayerType::VALUES:
0 commit comments