CPP: use new geocoding data in AreaCodeMap. Patch contributed by pmezard.
[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
21 #include "phonenumbers/geocoding/default_map_storage.h"
22 #include "phonenumbers/phonenumber.pb.h"
23 #include "phonenumbers/phonenumberutil.h"
24 #include "phonenumbers/stringutil.h"
25
26 namespace i18n {
27 namespace phonenumbers {
28
29 AreaCodeMap::AreaCodeMap()
30   : phone_util_(*PhoneNumberUtil::GetInstance()) {
31 }
32
33 AreaCodeMap::~AreaCodeMap() {
34 }
35
36 void AreaCodeMap::ReadAreaCodeMap(const PrefixDescriptions* descriptions) {
37   DefaultMapStorage* storage = new DefaultMapStorage();
38   storage->ReadFromMap(descriptions);
39   storage_.reset(storage);
40 }
41
42 const char* AreaCodeMap::Lookup(const PhoneNumber& number) const {
43   const int entries = storage_->GetNumOfEntries();
44   if (!entries) {
45     return NULL;
46   }
47
48   string national_number;
49   phone_util_.GetNationalSignificantNumber(number, &national_number);
50   int64 phone_prefix;
51   safe_strto64(SimpleItoa(number.country_code()) + national_number,
52                &phone_prefix);
53
54   const int* const lengths = storage_->GetPossibleLengths();
55   const int lengths_size = storage_->GetPossibleLengthsSize();
56   int current_index = entries - 1;
57   for (int lengths_index = lengths_size - 1; lengths_index >= 0;
58        --lengths_index) {
59     const int possible_length = lengths[lengths_index];
60     string phone_prefix_str = SimpleItoa(phone_prefix);
61     if (static_cast<int>(phone_prefix_str.length()) > possible_length) {
62       safe_strto64(phone_prefix_str.substr(0, possible_length), &phone_prefix);
63     }
64     current_index = BinarySearch(0, current_index, phone_prefix);
65     if (current_index < 0) {
66       return NULL;
67     }
68     const int32 current_prefix = storage_->GetPrefix(current_index);
69     if (phone_prefix == current_prefix) {
70       return storage_->GetDescription(current_index);
71     }
72   }
73   return NULL;
74 }
75
76 int AreaCodeMap::BinarySearch(int start, int end, int64 value) const {
77   int current = 0;
78   while (start <= end) {
79     current = (start + end) / 2;
80     int32 current_value = storage_->GetPrefix(current);
81     if (current_value == value) {
82       return current;
83     } else if (current_value > value) {
84       --current;
85       end = current;
86     } else {
87       start = current + 1;
88     }
89   }
90   return current;
91 }
92
93 }  // namespace phonenumbers
94 }  // namespace i18n