#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"
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;
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);
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;
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) {
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.
// 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.
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);
};
+++ /dev/null
-// 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_
#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
#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);
};
#include <gtest/gtest.h> // NOLINT(build/include_order)
+#include "phonenumbers/geocoding/geocoding_data.h"
#include "phonenumbers/phonenumber.pb.h"
namespace i18n {
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) {
};
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