7e869be991bf15038d66d967ec055f358d1f56c8
[platform/upstream/libphonenumber.git] / cpp / src / phonenumbers / geocoding / area_code_map.cc
1 // Copyright (C) 2012 The Libphonenumber Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // Author: Patrick Mezard
16
17 #include "phonenumbers/geocoding/area_code_map.h"
18
19 #include <cstddef>
20 #include <iterator>
21 #include <set>
22
23 #include "phonenumbers/geocoding/area_code_map_storage_strategy.h"
24 #include "phonenumbers/geocoding/default_map_storage.h"
25 #include "phonenumbers/phonenumber.pb.h"
26 #include "phonenumbers/phonenumberutil.h"
27 #include "phonenumbers/stringutil.h"
28
29 namespace i18n {
30 namespace phonenumbers {
31
32 AreaCodeMap::AreaCodeMap()
33   : phone_util_(*PhoneNumberUtil::GetInstance()) {
34 }
35
36 AreaCodeMap::~AreaCodeMap() {
37 }
38
39 AreaCodeMapStorageStrategy* AreaCodeMap::CreateDefaultMapStorage() const {
40   return new DefaultMapStorage();
41 }
42
43 void AreaCodeMap::ReadAreaCodeMap(const map<int, string>& area_codes) {
44   AreaCodeMapStorageStrategy* storage = CreateDefaultMapStorage();
45   storage->ReadFromMap(area_codes);
46   storage_.reset(storage);
47 }
48
49 const string* AreaCodeMap::Lookup(const PhoneNumber& number) const {
50   const int entries = storage_->GetNumOfEntries();
51   if (!entries) {
52     return NULL;
53   }
54
55   string national_number;
56   phone_util_.GetNationalSignificantNumber(number, &national_number);
57   int64 phone_prefix;
58   safe_strto64(SimpleItoa(number.country_code()) + national_number,
59                &phone_prefix);
60
61   const set<int>& lengths = storage_->GetPossibleLengths();
62   int current_index = entries - 1;
63   for (set<int>::const_reverse_iterator lengths_it = lengths.rbegin();
64        lengths_it != lengths.rend(); ++lengths_it) {
65     const int possible_length = *lengths_it;
66     string phone_prefix_str = SimpleItoa(phone_prefix);
67     if (static_cast<int>(phone_prefix_str.length()) > possible_length) {
68       safe_strto64(phone_prefix_str.substr(0, possible_length), &phone_prefix);
69     }
70     current_index = BinarySearch(0, current_index, phone_prefix);
71     if (current_index < 0) {
72       return NULL;
73     }
74     const int current_prefix = storage_->GetPrefix(current_index);
75     if (phone_prefix == current_prefix) {
76       return &storage_->GetDescription(current_index);
77     }
78   }
79   return NULL;
80 }
81
82 int AreaCodeMap::BinarySearch(int start, int end, int64 value) const {
83   int current = 0;
84   while (start <= end) {
85     current = (start + end) / 2;
86     int current_value = storage_->GetPrefix(current);
87     if (current_value == value) {
88       return current;
89     } else if (current_value > value) {
90       --current;
91       end = current;
92     } else {
93       start = current + 1;
94     }
95   }
96   return current;
97 }
98
99 }  // namespace phonenumbers
100 }  // namespace i18n