diff --git a/android/jni/com/mapswithme/maps/Framework.cpp b/android/jni/com/mapswithme/maps/Framework.cpp index 859f3229ee..957e150873 100644 --- a/android/jni/com/mapswithme/maps/Framework.cpp +++ b/android/jni/com/mapswithme/maps/Framework.cpp @@ -805,12 +805,10 @@ namespace android static jmethodID const addId = env->GetMethodID(clazz, "addMetadata", "(ILjava/lang/String;)V"); ASSERT ( addId, () ); - vector const metaTypes = metadata.GetPresentTypes(); - for (size_t i = 0; i < metaTypes.size(); i++) + for (feature::Metadata::EType t : metadata.GetPresentTypes()) { - feature::Metadata::EType metaType = static_cast(metaTypes[i]); - jstring metaString = jni::ToJavaString(env, metadata.Get(metaType)); - env->CallVoidMethod(mapObject, addId, metaType, metaString); + jstring metaString = jni::ToJavaString(env, metadata.Get(t)); + env->CallVoidMethod(mapObject, addId, t, metaString); // TODO use unique_ptrs for autoallocation of local refs env->DeleteLocalRef(metaString); } @@ -847,8 +845,7 @@ pair NativeMetadataToJavaMetadata(JNIEnv * env, feature for (size_t i = 0; i < metaTypes.size(); i++) { arr[i] = metaTypes[i]; - feature::Metadata::EType metaType = static_cast(metaTypes[i]); - jstring metaString = jni::ToJavaString(env, metadata.Get(metaType)); + jstring metaString = jni::ToJavaString(env, metadata.Get(metaTypes[i])); env->SetObjectArrayElement(j_metaValues, i, metaString); env->DeleteLocalRef(metaString); } diff --git a/indexer/categories_holder.cpp b/indexer/categories_holder.cpp index e573e2a0ea..e7d21d9e98 100644 --- a/indexer/categories_holder.cpp +++ b/indexer/categories_holder.cpp @@ -233,7 +233,7 @@ int8_t CategoriesHolder::MapLocaleToInteger(string const & locale) string lower = locale; strings::AsciiToLower(lower); - for (auto s : {"hant", "tw", "hk", "mo"}) + for (char const * s : {"hant", "tw", "hk", "mo"}) if (lower.find(s) != string::npos) return 12; // Traditional Chinese diff --git a/indexer/feature_meta.hpp b/indexer/feature_meta.hpp index bd0dfe578d..ae3d5ef9f7 100644 --- a/indexer/feature_meta.hpp +++ b/indexer/feature_meta.hpp @@ -8,14 +8,16 @@ #include "std/limits.hpp" #include "std/algorithm.hpp" #include "std/vector.hpp" +#include "std/static_assert.hpp" + namespace feature { class Metadata { - map m_metadata; - public: + /// @note! Do not change values here. + /// Add new types to the end of list, before FMD_COUNT. enum EType { FMD_CUISINE = 1, @@ -32,9 +34,12 @@ namespace feature FMD_TURN_LANES_FORWARD = 12, FMD_TURN_LANES_BACKWARD = 13, FMD_EMAIL = 14, - FMD_POSTCODE = 15 + FMD_POSTCODE = 15, + FMD_COUNT }; + STATIC_ASSERT(FMD_COUNT <= 255); + bool Add(EType type, string const & s) { string & val = m_metadata[type]; @@ -54,8 +59,10 @@ namespace feature vector GetPresentTypes() const { vector types; - for (auto item : m_metadata) - types.push_back(static_cast(item.first)); + types.reserve(m_metadata.size()); + + for (auto const & item : m_metadata) + types.push_back(item.first); return types; } @@ -70,11 +77,12 @@ namespace feature template void SerializeToMWM(ArchiveT & ar) const { - for (auto const & e: m_metadata) + for (auto const & e : m_metadata) { - uint8_t last_key_mark = (&e == &(*m_metadata.crbegin())) << 7; /// set high bit (0x80) if it last element - uint8_t elem[2] = {static_cast(e.first | last_key_mark), - static_cast(min(e.second.size(), (size_t)numeric_limits::max()))}; + // set high bit if it's the last element + uint8_t const mark = (&e == &(*m_metadata.crbegin()) ? 0x80 : 0); + uint8_t elem[2] = {static_cast(e.first | mark), + static_cast(min(e.second.size(), (size_t)kMaxStringLength))}; ar.Write(elem, sizeof(elem)); ar.Write(e.second.data(), elem[1]); } @@ -83,12 +91,12 @@ namespace feature template void DeserializeFromMWM(ArchiveT & ar) { uint8_t header[2] = {0}; - char buffer[uint8_t(-1)] = {0}; + char buffer[kMaxStringLength] = {0}; do { ar.Read(header, sizeof(header)); ar.Read(buffer, header[1]); - m_metadata[static_cast(header[0] & 0x7F)].assign(buffer, header[1]); + m_metadata[ToType(header[0] & 0x7F)].assign(buffer, header[1]); } while (!(header[0] & 0x80)); } @@ -96,26 +104,35 @@ namespace feature { uint8_t const sz = m_metadata.size(); WriteToSink(ar, sz); - if (sz) + for (auto const & it : m_metadata) { - for (auto const & it : m_metadata) - { - WriteToSink(ar, static_cast(it.first)); - utils::WriteString(ar, it.second); - } + WriteToSink(ar, static_cast(it.first)); + utils::WriteString(ar, it.second); } } template void Deserialize(ArchiveT & ar) { uint8_t const sz = ReadPrimitiveFromSource(ar); + ASSERT_LESS_OR_EQUAL(sz, FMD_COUNT, ()); + for (size_t i = 0; i < sz; ++i) { - uint8_t const key = ReadPrimitiveFromSource(ar); + EType const key = ToType(ReadPrimitiveFromSource(ar)); string value; utils::ReadString(ar, value); m_metadata.insert(make_pair(key, value)); } } + + private: + static EType ToType(uint8_t key) + { + ASSERT(key > 0 && key < FMD_COUNT, (key)); + return static_cast(key); + } + + enum { kMaxStringLength = 255 }; + map m_metadata; }; }