Patrick Mézard avatar Patrick Mézard committed da84b59 Merge

Merge with r462

Comments (0)

Files changed (12)

cpp/CMakeLists.txt

   "src/base/string_piece.cc"
   "src/phonenumbers/asyoutypeformatter.cc"
   "src/phonenumbers/default_logger.cc"
+  "src/phonenumbers/geocoding/area_code_map.cc"
+  "src/phonenumbers/geocoding/default_map_storage.cc"
   "src/phonenumbers/logger.cc"
   "src/phonenumbers/metadata.h"          # Generated by build tools.
   "src/phonenumbers/phonemetadata.pb.cc" # Generated by Protocol Buffers.
 
 set (TEST_SOURCES
   "test/phonenumbers/asyoutypeformatter_test.cc"
+  "test/phonenumbers/geocoding/area_code_map_test.cc"
   "test/phonenumbers/logger_test.cc"
   "test/phonenumbers/phonenumberutil_test.cc"
   "test/phonenumbers/regexp_adapter_test.cc"

cpp/src/phonenumbers/geocoding/area_code_map.cc

+// 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
+
+#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"
+#include "phonenumbers/stringutil.h"
+
+namespace i18n {
+namespace phonenumbers {
+
+AreaCodeMap::AreaCodeMap()
+  : phone_util_(*PhoneNumberUtil::GetInstance()) {
+}
+
+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);
+  storage_.reset(storage);
+}
+
+const string* AreaCodeMap::Lookup(const PhoneNumber& number) const {
+  const int entries = storage_->GetNumOfEntries();
+  if (!entries) {
+    return NULL;
+  }
+
+  string national_number;
+  phone_util_.GetNationalSignificantNumber(number, &national_number);
+  int64 phone_prefix;
+  safe_strto64(SimpleItoa(number.country_code()) + national_number,
+               &phone_prefix);
+
+  const set<int>& lengths = storage_->GetPossibleLengths();
+  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;
+    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);
+    }
+    current_index = BinarySearch(0, current_index, phone_prefix);
+    if (current_index < 0) {
+      return NULL;
+    }
+    const int current_prefix = storage_->GetPrefix(current_index);
+    if (phone_prefix == current_prefix) {
+      return &storage_->GetDescription(current_index);
+    }
+  }
+  return NULL;
+}
+
+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);
+    if (current_value == value) {
+      return current;
+    } else if (current_value > value) {
+      --current;
+      end = current;
+    } else {
+      start = current + 1;
+    }
+  }
+  return current;
+}
+
+}  // namespace phonenumbers
+}  // namespace i18n

cpp/src/phonenumbers/geocoding/area_code_map.h

+// 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
+
+#ifndef I18N_PHONENUMBERS_AREA_CODE_MAP_H_
+#define I18N_PHONENUMBERS_AREA_CODE_MAP_H_
+
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+
+namespace i18n {
+namespace phonenumbers {
+
+using std::map;
+using std::string;
+
+class AreaCodeMapStorageStrategy;
+class PhoneNumber;
+class PhoneNumberUtil;
+
+// A utility that maps phone number prefixes to a string describing the
+// geographical area the prefix covers.
+class AreaCodeMap {
+ public:
+  AreaCodeMap();
+  ~AreaCodeMap();
+
+  // Returns the description of the geographical area the number corresponds
+  // to. This method distinguishes the case of an invalid prefix and a prefix
+  // for which the name is not available in the current language. If the
+  // 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;
+
+  // 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);
+
+ 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.
+  // This means if value is the smallest, -1 will be returned.
+  int BinarySearch(int start, int end, int64 value) const;
+
+  const PhoneNumberUtil& phone_util_;
+  scoped_ptr<const AreaCodeMapStorageStrategy> storage_;
+
+  DISALLOW_COPY_AND_ASSIGN(AreaCodeMap);
+};
+
+}  // namespace phonenumbers
+}  // namespace i18n
+
+#endif /* I18N_PHONENUMBERS_AREA_CODE_MAP_H_ */

cpp/src/phonenumbers/geocoding/area_code_map_storage_strategy.h

+// 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_

cpp/src/phonenumbers/geocoding/default_map_storage.cc

+// 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
+
+#include "phonenumbers/geocoding/default_map_storage.h"
+
+#include <math.h>
+#include <utility>
+
+#include "base/logging.h"
+
+namespace i18n {
+namespace phonenumbers {
+
+using std::map;
+using std::set;
+using std::string;
+
+DefaultMapStorage::DefaultMapStorage() {
+}
+
+DefaultMapStorage::~DefaultMapStorage() {
+}
+
+int DefaultMapStorage::GetPrefix(int index) const {
+  DCHECK_GE(index, 0);
+  DCHECK_LT(index, static_cast<int>(prefixes_.size()));
+  return prefixes_[index];
+}
+
+const string& DefaultMapStorage::GetDescription(int index) const {
+  DCHECK_GE(index, 0);
+  DCHECK_LT(index, static_cast<int>(descriptions_.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);
+  }
+}
+
+int DefaultMapStorage::GetNumOfEntries() const {
+  return prefixes_.size();
+}
+
+const set<int>& DefaultMapStorage::GetPossibleLengths() const {
+  return possible_lengths_;
+}
+
+}  // namespace phonenumbers
+}  // namespace i18n

cpp/src/phonenumbers/geocoding/default_map_storage.h

+// 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
+//
+// Default class for storing area codes.
+
+#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;
+
+// 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 {
+ 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;
+
+ private:
+  // Sorted sequence of phone number prefixes.
+  vector<int> prefixes_;
+  // Sequence of prefix descriptions, in the same order than prefixes_.
+  vector<string> descriptions_;
+  // Sequence of unique possible lengths in ascending order.
+  set<int> possible_lengths_;
+
+  DISALLOW_COPY_AND_ASSIGN(DefaultMapStorage);
+};
+
+}  // namespace phonenumbers
+}  // namespace i18n
+
+#endif /* I18N_PHONENUMBERS_DEFAULT_MAP_STORAGE_H_ */
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.