Home | History | Annotate | Download | only in geocoding
      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
     95