From d960e0e43fad75aad8776fc3cf9333e7df126510 Mon Sep 17 00:00:00 2001 From: vng Date: Thu, 26 Jan 2012 12:33:38 +0300 Subject: [PATCH] CountryInfoGetter::GetRegionInfo - extended country information (name, flag, ...) --- search/intermediate_result.cpp | 10 ++-- storage/country.cpp | 53 ++++++++++++++------- storage/country.hpp | 5 +- storage/country_decl.hpp | 33 +++++++++++++ storage/country_info.cpp | 36 +++++++------- storage/country_info.hpp | 10 ++-- storage/country_polygon.hpp | 17 +------ storage/storage.pro | 1 + storage/storage_tests/country_info_test.cpp | 34 +++++++++---- 9 files changed, 129 insertions(+), 70 deletions(-) create mode 100644 storage/country_decl.hpp diff --git a/search/intermediate_result.cpp b/search/intermediate_result.cpp index eda33a2698..55faa731f2 100644 --- a/search/intermediate_result.cpp +++ b/search/intermediate_result.cpp @@ -261,12 +261,14 @@ string IntermediateResult::DebugPrint() const string IntermediateResult::RegionInfo::GetRegion(storage::CountryInfoGetter const * pInfo) const { + storage::CountryInfo info; + if (!m_file.empty()) - return pInfo->GetRegionName(m_file); + pInfo->GetRegionInfo(m_file, info); else if (m_valid) - return pInfo->GetRegionName(m_point); - else - return string(); + pInfo->GetRegionInfo(m_point, info); + + return info.m_name; } } // namespace search::impl diff --git a/storage/country.cpp b/storage/country.cpp index db33df642a..5e74061b30 100644 --- a/storage/country.cpp +++ b/storage/country.cpp @@ -142,24 +142,45 @@ namespace } }; - class DoStoreFile2Name + class DoStoreFile2Info { - map & m_file2name; - public: - DoStoreFile2Name(map & file2name) : m_file2name(file2name) {} + map & m_file2info; + string m_lastFlag; - void operator() (string name, string const & file, string const &, + public: + DoStoreFile2Info(map & file2info) : m_file2info(file2info) {} + + void operator() (string name, string file, string const & flag, uint32_t size, int64_t, int) { - // if 'file' is empty - it's equal to name - if (size && !file.empty()) - { - size_t const i = file.find_first_of('_'); - if (i != string::npos) - name = file.substr(0, i) + '_' + name; + if (!flag.empty()) + m_lastFlag = flag; - if (name != file) - m_file2name[file] = name; + if (size) + { + CountryInfo info; + + // if 'file' is empty - it's equal to 'name' + if (!file.empty()) + { + // make compound name: country_region + size_t const i = file.find_first_of('_'); + if (i != string::npos) + name = file.substr(0, i) + '_' + name; + + // fill 'name' only when it differs with 'file' + if (name != file) + info.m_name.swap(name); + } + else + file.swap(name); + + // Do not use 'name' here! It was swapped! + + ASSERT ( !m_lastFlag.empty(), () ); + info.m_flag = m_lastFlag; + + m_file2info[file] = info; } } }; @@ -185,10 +206,10 @@ int64_t LoadCountries(string const & jsonBuffer, CountriesContainerT & countries return LoadCountriesImpl(jsonBuffer, doStore); } -void LoadCountryFile2Name(string const & jsonBuffer, map & id2name) +void LoadCountryFile2CountryInfo(string const & jsonBuffer, map & id2info) { - ASSERT ( id2name.empty(), () ); - DoStoreFile2Name doStore(id2name); + ASSERT ( id2info.empty(), () ); + DoStoreFile2Info doStore(id2info); LoadCountriesImpl(jsonBuffer, doStore); } diff --git a/storage/country.hpp b/storage/country.hpp index dde2f67c1a..a133c3a6b6 100644 --- a/storage/country.hpp +++ b/storage/country.hpp @@ -1,6 +1,7 @@ #pragma once #include "simple_tree.hpp" +#include "country_decl.hpp" #include "../defines.hpp" @@ -40,7 +41,7 @@ namespace storage class Country { friend class update::SizeUpdater; - /// Name in the coutry node tree + /// Name in the country node tree string m_name; /// Flag to display string m_flag; @@ -70,7 +71,7 @@ namespace storage /// @return version of country file or -1 if error was encountered int64_t LoadCountries(string const & jsonBuffer, CountriesContainerT & countries); - void LoadCountryFile2Name(string const & jsonBuffer, map & id2name); + void LoadCountryFile2CountryInfo(string const & jsonBuffer, map & id2info); void LoadCountryCode2File(string const & jsonBuffer, multimap & code2file); bool SaveCountries(int64_t version, CountriesContainerT const & countries, string & jsonBuffer); diff --git a/storage/country_decl.hpp b/storage/country_decl.hpp new file mode 100644 index 0000000000..1ddb4b6a64 --- /dev/null +++ b/storage/country_decl.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "../geometry/rect2d.hpp" + +#include "../std/string.hpp" + + +namespace storage +{ + struct CountryDef + { + string m_name; + m2::RectD m_rect; + + CountryDef() {} + CountryDef(string const & name, m2::RectD const & r) + : m_name(name), m_rect(r) + { + } + }; + + struct CountryInfo + { + /// Name (in native language) of country or region. + /// (if empty - equals to file name of country - no additional memory) + string m_name; + + /// Flag of country or region. + string m_flag; + + bool IsNotEmpty() const { return !m_flag.empty(); } + }; +} diff --git a/storage/country_info.cpp b/storage/country_info.cpp index ea5fd4f577..bb5e2c2722 100644 --- a/storage/country_info.cpp +++ b/storage/country_info.cpp @@ -1,4 +1,5 @@ #include "country_info.hpp" +#include "country_polygon.hpp" #include "country.hpp" #include "../indexer/geometry_serialization.hpp" @@ -20,7 +21,7 @@ namespace storage string buffer; countryR.ReadAsString(buffer); - LoadCountryFile2Name(buffer, m_id2name); + LoadCountryFile2CountryInfo(buffer, m_id2info); } template @@ -85,38 +86,33 @@ namespace storage return string(); } - string CountryInfoGetter::GetRegionName(m2::PointD const & pt) const + void CountryInfoGetter::GetRegionInfo(m2::PointD const & pt, CountryInfo & info) const { GetByPoint doGet(*this, pt); ForEachCountry(pt, doGet); if (doGet.m_res != -1) - return GetRegionName(m_countries[doGet.m_res].m_name); - - return string(); + GetRegionInfo(m_countries[doGet.m_res].m_name, info); } - string CountryInfoGetter::GetRegionName(string const & id) const + void CountryInfoGetter::GetRegionInfo(string const & id, CountryInfo & info) const { - string name; + map::const_iterator i = m_id2info.find(id); + ASSERT ( i != m_id2info.end(), () ); - map::const_iterator i = m_id2name.find(id); - if (i != m_id2name.end()) - name = i->second; - else - name = id; + info = i->second; + + if (info.m_name.empty()) + info.m_name = id; - /// @todo Correct replace '_' with ", " in name. if (id.find_first_of('_') != string::npos) { - // I don't know how to do it best for UTF8, but this variant will work - // correctly for now (utf8-names of compound countries are equal to ascii-names). + size_t const i = info.m_name.find_first_of('_'); + ASSERT ( i != string::npos, () ); - size_t const i = name.find_first_of('_'); - ASSERT_NOT_EQUAL ( i, string::npos, () ); - name = name.substr(0, i) + ", " + name.substr(i+1); + // replace '_' with ", " + info.m_name[i] = ','; + info.m_name.insert(i+1, " "); } - - return name; } } diff --git a/storage/country_info.hpp b/storage/country_info.hpp index 6923040b8e..1209fe85bf 100644 --- a/storage/country_info.hpp +++ b/storage/country_info.hpp @@ -1,5 +1,6 @@ #pragma once -#include "country_polygon.hpp" + +#include "country_decl.hpp" #include "../geometry/region2d.hpp" @@ -15,7 +16,7 @@ namespace storage FilesContainerR m_reader; vector m_countries; - map m_id2name; + map m_id2info; mutable my::Cache > m_cache; @@ -41,7 +42,8 @@ namespace storage CountryInfoGetter(ModelReaderPtr polyR, ModelReaderPtr countryR); string GetRegionFile(m2::PointD const & pt) const; - string GetRegionName(m2::PointD const & pt) const; - string GetRegionName(string const & id) const; + + void GetRegionInfo(m2::PointD const & pt, CountryInfo & info) const; + void GetRegionInfo(string const & id, CountryInfo & info) const; }; } diff --git a/storage/country_polygon.hpp b/storage/country_polygon.hpp index f8d56cb23a..ec4492cabd 100644 --- a/storage/country_polygon.hpp +++ b/storage/country_polygon.hpp @@ -1,28 +1,15 @@ #pragma once -#include "../defines.hpp" +#include "country_decl.hpp" #include "../indexer/point_to_int64.hpp" #include "../indexer/coding_params.hpp" -#include "../geometry/rect2d.hpp" - #include "../coding/read_write_utils.hpp" + namespace storage { - struct CountryDef - { - string m_name; - m2::RectD m_rect; - - CountryDef() {} - CountryDef(string const & name, m2::RectD const & r) - : m_name(name), m_rect(r) - { - } - }; - template void Read(TSource & src, CountryDef & p) { rw::Read(src, p.m_name); diff --git a/storage/storage.pro b/storage/storage.pro index 3d86ad1246..33faa0509c 100644 --- a/storage/storage.pro +++ b/storage/storage.pro @@ -18,6 +18,7 @@ HEADERS += \ storage.hpp \ country_polygon.hpp \ country_info.hpp \ + country_decl.hpp \ SOURCES += \ country.cpp \ diff --git a/storage/storage_tests/country_info_test.cpp b/storage/storage_tests/country_info_test.cpp index 10507fe116..5b9a91e07a 100644 --- a/storage/storage_tests/country_info_test.cpp +++ b/storage/storage_tests/country_info_test.cpp @@ -8,6 +8,8 @@ #include "../../platform/platform.hpp" +using namespace storage; + UNIT_TEST(CountryInfo_GetByPoint_Smoke) { Platform & pl = GetPlatform(); @@ -16,9 +18,23 @@ UNIT_TEST(CountryInfo_GetByPoint_Smoke) pl.GetReader(COUNTRIES_FILE)); // Minsk - TEST_EQUAL(getter.GetRegionName( - m2::PointD(MercatorBounds::LonToX(27.5618818), - MercatorBounds::LatToY(53.9022651))), "Belarus", ()); + CountryInfo info; + getter.GetRegionInfo(m2::PointD(MercatorBounds::LonToX(27.5618818), + MercatorBounds::LatToY(53.9022651)), + info); + + TEST_EQUAL(info.m_name, "Belarus", ()); + TEST_EQUAL(info.m_flag, "by", ()); +} + +namespace +{ + bool IsEmptyName(map const & id2info, string const & id) + { + map::const_iterator i = id2info.find(id); + TEST(i != id2info.end(), ()); + return i->second.m_name.empty(); + } } UNIT_TEST(CountryInfo_ValidName_Smoke) @@ -26,12 +42,12 @@ UNIT_TEST(CountryInfo_ValidName_Smoke) string buffer; ReaderPtr(GetPlatform().GetReader(COUNTRIES_FILE)).ReadAsString(buffer); - map id2name; - storage::LoadCountryFile2Name(buffer, id2name); + map id2info; + storage::LoadCountryFile2CountryInfo(buffer, id2info); - TEST(id2name.count("Germany_Baden-Wurttemberg") == 1, ()); - TEST(id2name.count("France_Paris & Ile-de-France") == 1, ()); + TEST(!IsEmptyName(id2info, "Germany_Baden-Wurttemberg"), ()); + TEST(!IsEmptyName(id2info, "France_Paris & Ile-de-France"), ()); - TEST(id2name.count("Russia_Far Eastern") == 0, ()); - TEST(id2name.count("UK_Northern Ireland") == 0, ()); + TEST(IsEmptyName(id2info, "Russia_Far Eastern"), ()); + TEST(IsEmptyName(id2info, "UK_Northern Ireland"), ()); }