From: jia.shao.peng Date: Tue, 7 Aug 2012 15:14:43 +0000 (+0000) Subject: CPP: use new geocoding data in AreaCodeMap. Patch contributed by pmezard. X-Git-Tag: upstream/5.3.2~39 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ce0c85d5c76322a9eeede88953388e1a7d38e90a;p=platform%2Fupstream%2Flibphonenumber.git CPP: use new geocoding data in AreaCodeMap. Patch contributed by pmezard. git-svn-id: http://libphonenumber.googlecode.com/svn/trunk@514 ee073f10-1060-11df-b6a4-87a95322a99c --- diff --git a/cpp/src/phonenumbers/geocoding/area_code_map.cc b/cpp/src/phonenumbers/geocoding/area_code_map.cc index 7e869be..1d8e115 100644 --- a/cpp/src/phonenumbers/geocoding/area_code_map.cc +++ b/cpp/src/phonenumbers/geocoding/area_code_map.cc @@ -17,10 +17,7 @@ #include "phonenumbers/geocoding/area_code_map.h" #include -#include -#include -#include "phonenumbers/geocoding/area_code_map_storage_strategy.h" #include "phonenumbers/geocoding/default_map_storage.h" #include "phonenumbers/phonenumber.pb.h" #include "phonenumbers/phonenumberutil.h" @@ -36,17 +33,13 @@ AreaCodeMap::AreaCodeMap() AreaCodeMap::~AreaCodeMap() { } -AreaCodeMapStorageStrategy* AreaCodeMap::CreateDefaultMapStorage() const { - return new DefaultMapStorage(); -} - -void AreaCodeMap::ReadAreaCodeMap(const map& area_codes) { - AreaCodeMapStorageStrategy* storage = CreateDefaultMapStorage(); - storage->ReadFromMap(area_codes); +void AreaCodeMap::ReadAreaCodeMap(const PrefixDescriptions* descriptions) { + DefaultMapStorage* storage = new DefaultMapStorage(); + storage->ReadFromMap(descriptions); storage_.reset(storage); } -const string* AreaCodeMap::Lookup(const PhoneNumber& number) const { +const char* AreaCodeMap::Lookup(const PhoneNumber& number) const { const int entries = storage_->GetNumOfEntries(); if (!entries) { return NULL; @@ -58,11 +51,12 @@ const string* AreaCodeMap::Lookup(const PhoneNumber& number) const { safe_strto64(SimpleItoa(number.country_code()) + national_number, &phone_prefix); - const set& lengths = storage_->GetPossibleLengths(); + const int* const lengths = storage_->GetPossibleLengths(); + const int lengths_size = storage_->GetPossibleLengthsSize(); int current_index = entries - 1; - for (set::const_reverse_iterator lengths_it = lengths.rbegin(); - lengths_it != lengths.rend(); ++lengths_it) { - const int possible_length = *lengths_it; + for (int lengths_index = lengths_size - 1; lengths_index >= 0; + --lengths_index) { + const int possible_length = lengths[lengths_index]; string phone_prefix_str = SimpleItoa(phone_prefix); if (static_cast(phone_prefix_str.length()) > possible_length) { safe_strto64(phone_prefix_str.substr(0, possible_length), &phone_prefix); @@ -71,9 +65,9 @@ const string* AreaCodeMap::Lookup(const PhoneNumber& number) const { if (current_index < 0) { return NULL; } - const int current_prefix = storage_->GetPrefix(current_index); + const int32 current_prefix = storage_->GetPrefix(current_index); if (phone_prefix == current_prefix) { - return &storage_->GetDescription(current_index); + return storage_->GetDescription(current_index); } } return NULL; @@ -83,7 +77,7 @@ int AreaCodeMap::BinarySearch(int start, int end, int64 value) const { int current = 0; while (start <= end) { current = (start + end) / 2; - int current_value = storage_->GetPrefix(current); + int32 current_value = storage_->GetPrefix(current); if (current_value == value) { return current; } else if (current_value > value) { diff --git a/cpp/src/phonenumbers/geocoding/area_code_map.h b/cpp/src/phonenumbers/geocoding/area_code_map.h index 24df22d..ea6b348 100644 --- a/cpp/src/phonenumbers/geocoding/area_code_map.h +++ b/cpp/src/phonenumbers/geocoding/area_code_map.h @@ -29,9 +29,10 @@ namespace phonenumbers { using std::map; using std::string; -class AreaCodeMapStorageStrategy; +class DefaultMapStorage; class PhoneNumber; class PhoneNumberUtil; +struct PrefixDescriptions; // A utility that maps phone number prefixes to a string describing the // geographical area the prefix covers. @@ -46,18 +47,16 @@ class AreaCodeMap { // description is not available in the current language an empty string is // returned. If no description was found for the provided number, null is // returned. - const string* Lookup(const PhoneNumber& number) const; + const char* Lookup(const PhoneNumber& number) const; // Creates an AreaCodeMap initialized with area_codes. Note that the // underlying implementation of this method is expensive thus should // not be called by time-critical applications. // // area_codes maps phone number prefixes to geographical area description. - void ReadAreaCodeMap(const map& area_codes); + void ReadAreaCodeMap(const PrefixDescriptions* descriptions); private: - AreaCodeMapStorageStrategy* CreateDefaultMapStorage() const; - // Does a binary search for value in the provided array from start to end // (inclusive). Returns the position if {@code value} is found; otherwise, // returns the position which has the largest value that is less than value. @@ -65,7 +64,7 @@ class AreaCodeMap { int BinarySearch(int start, int end, int64 value) const; const PhoneNumberUtil& phone_util_; - scoped_ptr storage_; + scoped_ptr storage_; DISALLOW_COPY_AND_ASSIGN(AreaCodeMap); }; diff --git a/cpp/src/phonenumbers/geocoding/area_code_map_storage_strategy.h b/cpp/src/phonenumbers/geocoding/area_code_map_storage_strategy.h deleted file mode 100644 index e25c1f0..0000000 --- a/cpp/src/phonenumbers/geocoding/area_code_map_storage_strategy.h +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (C) 2012 The Libphonenumber Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Author: Patrick Mezard -// -// Interface for phone numbers area prefixes storage classes. - -#ifndef I18N_PHONENUMBERS_AREA_CODE_MAP_STRATEGY_H_ -#define I18N_PHONENUMBERS_AREA_CODE_MAP_STRATEGY_H_ - -#include -#include -#include - -namespace i18n { -namespace phonenumbers { - -using std::map; -using std::set; -using std::string; - -// Abstracts the way area code data is stored into memory. It is used by -// AreaCodeMap to support the most space-efficient storage strategy according -// to the provided data. -class AreaCodeMapStorageStrategy { - public: - virtual ~AreaCodeMapStorageStrategy() {} - - // Returns the phone number prefix located at the provided index. - virtual int GetPrefix(int index) const = 0; - - // Gets the description corresponding to the phone number prefix located - // at the provided index. If the description is not available in the current - // language an empty string is returned. - virtual const string& GetDescription(int index) const = 0; - - // Sets the internal state of the underlying storage implementation from the - // provided area_codes that maps phone number prefixes to description strings. - virtual void ReadFromMap(const map& area_codes) = 0; - - // Returns the number of entries contained in the area code map. - virtual int GetNumOfEntries() const = 0; - - // Returns the set containing the possible lengths of prefixes. - virtual const set& GetPossibleLengths() const = 0; -}; - -} // namespace phonenumbers -} // namespace i18n - -#endif // I18N_PHONENUMBERS_AREA_CODE_MAP_STRATEGY_H_ diff --git a/cpp/src/phonenumbers/geocoding/default_map_storage.cc b/cpp/src/phonenumbers/geocoding/default_map_storage.cc index 450ee5b..2ea3daa 100644 --- a/cpp/src/phonenumbers/geocoding/default_map_storage.cc +++ b/cpp/src/phonenumbers/geocoding/default_map_storage.cc @@ -16,56 +16,50 @@ #include "phonenumbers/geocoding/default_map_storage.h" -#include -#include - +#include "base/basictypes.h" #include "base/logging.h" +#include "phonenumbers/geocoding/geocoding_data.h" namespace i18n { namespace phonenumbers { -using std::map; -using std::set; -using std::string; - DefaultMapStorage::DefaultMapStorage() { } DefaultMapStorage::~DefaultMapStorage() { } -int DefaultMapStorage::GetPrefix(int index) const { +int32 DefaultMapStorage::GetPrefix(int index) const { DCHECK_GE(index, 0); - DCHECK_LT(index, static_cast(prefixes_.size())); + DCHECK_LT(index, prefixes_size_); return prefixes_[index]; } -const string& DefaultMapStorage::GetDescription(int index) const { +const char* DefaultMapStorage::GetDescription(int index) const { DCHECK_GE(index, 0); - DCHECK_LT(index, static_cast(descriptions_.size())); + DCHECK_LT(index, prefixes_size_); return descriptions_[index]; } -void DefaultMapStorage::ReadFromMap(const map& area_codes) { - prefixes_.resize(area_codes.size()); - descriptions_.resize(area_codes.size()); - possible_lengths_.clear(); - int index = 0; - for (map::const_iterator it = area_codes.begin(); - it != area_codes.end(); ++it, ++index) { - prefixes_[index] = it->first; - descriptions_[index] = it->second; - possible_lengths_.insert(static_cast(log10(it->first)) + 1); - } +void DefaultMapStorage::ReadFromMap(const PrefixDescriptions* descriptions) { + prefixes_ = descriptions->prefixes; + prefixes_size_ = descriptions->prefixes_size; + descriptions_ = descriptions->descriptions; + possible_lengths_ = descriptions->possible_lengths; + possible_lengths_size_ = descriptions->possible_lengths_size; } int DefaultMapStorage::GetNumOfEntries() const { - return prefixes_.size(); + return prefixes_size_; } -const set& DefaultMapStorage::GetPossibleLengths() const { +const int* DefaultMapStorage::GetPossibleLengths() const { return possible_lengths_; } +int DefaultMapStorage::GetPossibleLengthsSize() const { + return possible_lengths_size_; +} + } // namespace phonenumbers } // namespace i18n diff --git a/cpp/src/phonenumbers/geocoding/default_map_storage.h b/cpp/src/phonenumbers/geocoding/default_map_storage.h index b4b9631..a2a276f 100644 --- a/cpp/src/phonenumbers/geocoding/default_map_storage.h +++ b/cpp/src/phonenumbers/geocoding/default_map_storage.h @@ -19,44 +19,53 @@ #ifndef I18N_PHONENUMBERS_DEFAULT_MAP_STORAGE_H_ #define I18N_PHONENUMBERS_DEFAULT_MAP_STORAGE_H_ -#include -#include -#include -#include - #include "base/basictypes.h" -#include "phonenumbers/geocoding/area_code_map_storage_strategy.h" namespace i18n { namespace phonenumbers { -using std::map; -using std::set; -using std::string; -using std::vector; +struct PrefixDescriptions; // Default area code map storage strategy that is used for data not // containing description duplications. It is mainly intended to avoid // the overhead of the string table management when it is actually // unnecessary (i.e no string duplication). -class DefaultMapStorage : public AreaCodeMapStorageStrategy { +class DefaultMapStorage { public: DefaultMapStorage(); virtual ~DefaultMapStorage(); - virtual int GetPrefix(int index) const; - virtual const string& GetDescription(int index) const; - virtual void ReadFromMap(const map& area_codes); - virtual int GetNumOfEntries() const; - virtual const set& GetPossibleLengths() const; + // Returns the phone number prefix located at the provided index. + int32 GetPrefix(int index) const; + + // Gets the description corresponding to the phone number prefix located + // at the provided index. If the description is not available in the current + // language an empty string is returned. + const char* GetDescription(int index) const; + + // Sets the internal state of the underlying storage implementation from the + // provided area_codes that maps phone number prefixes to description strings. + void ReadFromMap(const PrefixDescriptions* descriptions); + + // Returns the number of entries contained in the area code map. + int GetNumOfEntries() const; + + // Returns an array containing the possible lengths of prefixes sorted in + // ascending order. + const int* GetPossibleLengths() const; + + // Returns the number of elements in GetPossibleLengths() array. + int GetPossibleLengthsSize() const; private: // Sorted sequence of phone number prefixes. - vector prefixes_; + const int32* prefixes_; + int prefixes_size_; // Sequence of prefix descriptions, in the same order than prefixes_. - vector descriptions_; + const char** descriptions_; // Sequence of unique possible lengths in ascending order. - set possible_lengths_; + const int32* possible_lengths_; + int possible_lengths_size_; DISALLOW_COPY_AND_ASSIGN(DefaultMapStorage); }; diff --git a/cpp/test/phonenumbers/geocoding/area_code_map_test.cc b/cpp/test/phonenumbers/geocoding/area_code_map_test.cc index 112f509..786c638 100644 --- a/cpp/test/phonenumbers/geocoding/area_code_map_test.cc +++ b/cpp/test/phonenumbers/geocoding/area_code_map_test.cc @@ -23,6 +23,7 @@ #include // NOLINT(build/include_order) +#include "phonenumbers/geocoding/geocoding_data.h" #include "phonenumbers/phonenumber.pb.h" namespace i18n { @@ -34,37 +35,89 @@ using std::vector; namespace { -void MakeCodeMap(const map& m, scoped_ptr* code_map) { +void MakeCodeMap(const PrefixDescriptions* descriptions, + scoped_ptr* code_map) { scoped_ptr cm(new AreaCodeMap()); - cm->ReadAreaCodeMap(m); + cm->ReadAreaCodeMap(descriptions); code_map->swap(cm); } +const int32 prefix_1_us_prefixes[] = { + 1212, + 1480, + 1650, + 1907, + 1201664, + 1480893, + 1501372, + 1626308, + 1650345, + 1867993, + 1972480, +}; + +const char* prefix_1_us_descriptions[] = { + "New York", + "Arizona", + "California", + "Alaska", + "Westwood, NJ", + "Phoenix, AZ", + "Little Rock, AR", + "Alhambra, CA", + "San Mateo, CA", + "Dawson, YT", + "Richardson, TX", +}; + +const int32 prefix_1_us_lengths[] = { + 4, 7, +}; + +const PrefixDescriptions prefix_1_us = { + prefix_1_us_prefixes, + sizeof(prefix_1_us_prefixes) / sizeof(*prefix_1_us_prefixes), + prefix_1_us_descriptions, + prefix_1_us_lengths, + sizeof(prefix_1_us_lengths) / sizeof(*prefix_1_us_lengths), +}; + +const int32 prefix_39_it_prefixes[] = { + 3902, + 3906, + 39010, + 390131, + 390321, + 390975, +}; + +const char* prefix_39_it_descriptions[] = { + "Milan", + "Rome", + "Genoa", + "Alessandria", + "Novara", + "Potenza", +}; + +const int32 prefix_39_it_lengths[] = { + 4, 5, 6, +}; + +const PrefixDescriptions prefix_39_it = { + prefix_39_it_prefixes, + sizeof(prefix_39_it_prefixes) / sizeof(*prefix_39_it_prefixes), + prefix_39_it_descriptions, + prefix_39_it_lengths, + sizeof(prefix_39_it_lengths) / sizeof(*prefix_1_us_lengths), +}; + void MakeCodeMapUS(scoped_ptr* code_map) { - map m; - m[1212] = "New York"; - m[1480] = "Arizona"; - m[1650] = "California"; - m[1907] = "Alaska"; - m[1201664] = "Westwood, NJ"; - m[1480893] = "Phoenix, AZ"; - m[1501372] = "Little Rock, AR"; - m[1626308] = "Alhambra, CA"; - m[1650345] = "San Mateo, CA"; - m[1867993] = "Dawson, YT"; - m[1972480] = "Richardson, TX"; - MakeCodeMap(m, code_map); + MakeCodeMap(&prefix_1_us, code_map); } void MakeCodeMapIT(scoped_ptr* code_map) { - map m; - m[3902] = "Milan"; - m[3906] = "Rome"; - m[39010] = "Genoa"; - m[390131] = "Alessandria"; - m[390321] = "Novara"; - m[390975] = "Potenza"; - MakeCodeMap(m, code_map); + MakeCodeMap(&prefix_39_it, code_map); } PhoneNumber MakePhoneNumber(int32 country_code, uint64 national_number) { @@ -88,58 +141,60 @@ class AreaCodeMapTest : public testing::Test { }; TEST_F(AreaCodeMapTest, TestLookupInvalidNumberUS) { - EXPECT_EQ("New York", *map_US_->Lookup(MakePhoneNumber(1, 2121234567L))); + EXPECT_STREQ("New York", map_US_->Lookup(MakePhoneNumber(1, 2121234567L))); } TEST_F(AreaCodeMapTest, TestLookupNumberNJ) { - EXPECT_EQ("Westwood, NJ", *map_US_->Lookup(MakePhoneNumber(1, 2016641234L))); + EXPECT_STREQ("Westwood, NJ", + map_US_->Lookup(MakePhoneNumber(1, 2016641234L))); } TEST_F(AreaCodeMapTest, TestLookupNumberNY) { - EXPECT_EQ("New York", *map_US_->Lookup(MakePhoneNumber(1, 2126641234L))); + EXPECT_STREQ("New York", map_US_->Lookup(MakePhoneNumber(1, 2126641234L))); } TEST_F(AreaCodeMapTest, TestLookupNumberCA1) { - EXPECT_EQ("San Mateo, CA", *map_US_->Lookup(MakePhoneNumber(1, 6503451234L))); + EXPECT_STREQ("San Mateo, CA", + map_US_->Lookup(MakePhoneNumber(1, 6503451234L))); } TEST_F(AreaCodeMapTest, TestLookupNumberCA2) { - EXPECT_EQ("California", *map_US_->Lookup(MakePhoneNumber(1, 6502531234L))); + EXPECT_STREQ("California", map_US_->Lookup(MakePhoneNumber(1, 6502531234L))); } TEST_F(AreaCodeMapTest, TestLookupNumberTX) { - EXPECT_EQ("Richardson, TX", - *map_US_->Lookup(MakePhoneNumber(1, 9724801234L))); + EXPECT_STREQ("Richardson, TX", + map_US_->Lookup(MakePhoneNumber(1, 9724801234L))); } TEST_F(AreaCodeMapTest, TestLookupNumberNotFoundTX) { - EXPECT_EQ(NULL, map_US_->Lookup(MakePhoneNumber(1, 9724811234L))); + EXPECT_STREQ(NULL, map_US_->Lookup(MakePhoneNumber(1, 9724811234L))); } TEST_F(AreaCodeMapTest, TestLookupNumberCH) { - EXPECT_EQ(NULL, map_US_->Lookup(MakePhoneNumber(41, 446681300L))); + EXPECT_STREQ(NULL, map_US_->Lookup(MakePhoneNumber(41, 446681300L))); } TEST_F(AreaCodeMapTest, TestLookupNumberIT) { PhoneNumber number = MakePhoneNumber(39, 212345678L); number.set_italian_leading_zero(true); - EXPECT_EQ("Milan", *map_IT_->Lookup(number)); + EXPECT_STREQ("Milan", map_IT_->Lookup(number)); number.set_national_number(612345678L); - EXPECT_EQ("Rome", *map_IT_->Lookup(number)); + EXPECT_STREQ("Rome", map_IT_->Lookup(number)); number.set_national_number(3211234L); - EXPECT_EQ("Novara", *map_IT_->Lookup(number)); + EXPECT_STREQ("Novara", map_IT_->Lookup(number)); // A mobile number number.set_national_number(321123456L); number.set_italian_leading_zero(false); - EXPECT_EQ(NULL, map_IT_->Lookup(number)); + EXPECT_STREQ(NULL, map_IT_->Lookup(number)); // An invalid number (too short) number.set_national_number(321123L); number.set_italian_leading_zero(true); - EXPECT_EQ("Novara", *map_IT_->Lookup(number)); + EXPECT_STREQ("Novara", map_IT_->Lookup(number)); } } // namespace phonenumbers