CPP: use new geocoding data in AreaCodeMap. Patch contributed by pmezard.
authorjia.shao.peng <jia.shao.peng@ee073f10-1060-11df-b6a4-87a95322a99c>
Tue, 7 Aug 2012 15:14:43 +0000 (15:14 +0000)
committerjia.shao.peng <jia.shao.peng@ee073f10-1060-11df-b6a4-87a95322a99c>
Tue, 7 Aug 2012 15:14:43 +0000 (15:14 +0000)
git-svn-id: http://libphonenumber.googlecode.com/svn/trunk@514 ee073f10-1060-11df-b6a4-87a95322a99c

cpp/src/phonenumbers/geocoding/area_code_map.cc
cpp/src/phonenumbers/geocoding/area_code_map.h
cpp/src/phonenumbers/geocoding/area_code_map_storage_strategy.h [deleted file]
cpp/src/phonenumbers/geocoding/default_map_storage.cc
cpp/src/phonenumbers/geocoding/default_map_storage.h
cpp/test/phonenumbers/geocoding/area_code_map_test.cc

index 7e869be..1d8e115 100644 (file)
 #include "phonenumbers/geocoding/area_code_map.h"
 
 #include <cstddef>
-#include <iterator>
-#include <set>
 
-#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<int, string>& 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<int>& lengths = storage_->GetPossibleLengths();
+  const int* const lengths = storage_->GetPossibleLengths();
+  const int lengths_size = storage_->GetPossibleLengthsSize();
   int current_index = entries - 1;
-  for (set<int>::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<int>(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) {
index 24df22d..ea6b348 100644 (file)
@@ -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<int, string>& 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<const AreaCodeMapStorageStrategy> storage_;
+  scoped_ptr<const DefaultMapStorage> 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 (file)
index e25c1f0..0000000
+++ /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 <map>
-#include <set>
-#include <string>
-
-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<int, string>& 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<int>& GetPossibleLengths() const = 0;
-};
-
-}  // namespace phonenumbers
-}  // namespace i18n
-
-#endif  // I18N_PHONENUMBERS_AREA_CODE_MAP_STRATEGY_H_
index 450ee5b..2ea3daa 100644 (file)
 
 #include "phonenumbers/geocoding/default_map_storage.h"
 
-#include <math.h>
-#include <utility>
-
+#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<int>(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<int>(descriptions_.size()));
+  DCHECK_LT(index, prefixes_size_);
   return descriptions_[index];
 }
 
-void DefaultMapStorage::ReadFromMap(const map<int, string>& area_codes) {
-  prefixes_.resize(area_codes.size());
-  descriptions_.resize(area_codes.size());
-  possible_lengths_.clear();
-  int index = 0;
-  for (map<int, string>::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<int>(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<int>& DefaultMapStorage::GetPossibleLengths() const {
+const int* DefaultMapStorage::GetPossibleLengths() const {
   return possible_lengths_;
 }
 
+int DefaultMapStorage::GetPossibleLengthsSize() const {
+  return possible_lengths_size_;
+}
+
 }  // namespace phonenumbers
 }  // namespace i18n
index b4b9631..a2a276f 100644 (file)
 #ifndef I18N_PHONENUMBERS_DEFAULT_MAP_STORAGE_H_
 #define I18N_PHONENUMBERS_DEFAULT_MAP_STORAGE_H_
 
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-
 #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<int, string>& area_codes);
-  virtual int GetNumOfEntries() const;
-  virtual const set<int>& 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<int> prefixes_;
+  const int32* prefixes_;
+  int prefixes_size_;
   // Sequence of prefix descriptions, in the same order than prefixes_.
-  vector<string> descriptions_;
+  const char** descriptions_;
   // Sequence of unique possible lengths in ascending order.
-  set<int> possible_lengths_;
+  const int32* possible_lengths_;
+  int possible_lengths_size_;
 
   DISALLOW_COPY_AND_ASSIGN(DefaultMapStorage);
 };
index 112f509..786c638 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <gtest/gtest.h>  // 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<int, string>& m, scoped_ptr<AreaCodeMap>* code_map) {
+void MakeCodeMap(const PrefixDescriptions* descriptions,
+                 scoped_ptr<AreaCodeMap>* code_map) {
   scoped_ptr<AreaCodeMap> 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<AreaCodeMap>* code_map) {
-  map<int, string> 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<AreaCodeMap>* code_map) {
-  map<int, string> 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