1948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa/* 2948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * 3948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * Copyright 2006, The Android Open Source Project 4948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * 5948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * Licensed under the Apache License, Version 2.0 (the "License"); 6948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * you may not use this file except in compliance with the License. 7948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * You may obtain a copy of the License at 8948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * 9948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * http://www.apache.org/licenses/LICENSE-2.0 10948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * 11948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * Unless required by applicable law or agreed to in writing, software 12948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * distributed under the License is distributed on an "AS IS" BASIS, 13948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * See the License for the specific language governing permissions and 15948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * limitations under the License. 16948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa */ 17948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 18948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa// Old implementation for phone_number_compare(), which has used in cupcake, but once replaced with 19948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa// the new, more strict version, and reverted again. 20948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 21948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa#include <string.h> 22948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 23948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawanamespace android { 24948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 253fffdd3714c6d4de821269bcefb65d897151c2f2Wei Huangstatic int MIN_MATCH = 7; 26948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 27948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa/** True if c is ISO-LATIN characters 0-9 */ 28948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawastatic bool isISODigit (char c) 29948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa{ 30948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa return c >= '0' && c <= '9'; 31948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa} 32948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 33948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa/** True if c is ISO-LATIN characters 0-9, *, # , + */ 34948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawastatic bool isNonSeparator(char c) 35948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa{ 36948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa return (c >= '0' && c <= '9') || c == '*' || c == '#' || c == '+'; 37948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa} 38948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 39948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa/** 40948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * Phone numbers are stored in "lookup" form in the database 41948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * as reversed strings to allow for caller ID lookup 42948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * 43948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * This method takes a phone number and makes a valid SQL "LIKE" 44948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * string that will match the lookup form 45948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * 46948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa */ 47948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa/** all of a up to len must be an international prefix or 48948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * separators/non-dialing digits 49948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa */ 50948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawastatic bool matchIntlPrefix(const char* a, int len) 51948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa{ 52948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa /* '([^0-9*#+]\+[^0-9*#+] | [^0-9*#+]0(0|11)[^0-9*#+] )$' */ 53948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa /* 0 1 2 3 45 */ 54948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 55948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa int state = 0; 56948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa for (int i = 0 ; i < len ; i++) { 57948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa char c = a[i]; 58948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 59948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa switch (state) { 60948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa case 0: 61948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (c == '+') state = 1; 62948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa else if (c == '0') state = 2; 63948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa else if (isNonSeparator(c)) return false; 64948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa break; 65948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 66948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa case 2: 67948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (c == '0') state = 3; 68948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa else if (c == '1') state = 4; 69948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa else if (isNonSeparator(c)) return false; 70948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa break; 71948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 72948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa case 4: 73948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (c == '1') state = 5; 74948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa else if (isNonSeparator(c)) return false; 75948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa break; 76948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 77948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa default: 78948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (isNonSeparator(c)) return false; 79948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa break; 80948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 81948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } 82948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } 83948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 84948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa return state == 1 || state == 3 || state == 5; 85948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa} 86948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 87948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa/** all of 'a' up to len must match non-US trunk prefix ('0') */ 88948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawastatic bool matchTrunkPrefix(const char* a, int len) 89948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa{ 90948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa bool found; 91948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 92948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa found = false; 93948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 94948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa for (int i = 0 ; i < len ; i++) { 95948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa char c = a[i]; 96948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 97948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (c == '0' && !found) { 98948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa found = true; 99948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } else if (isNonSeparator(c)) { 100948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa return false; 101948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } 102948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } 103948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 104948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa return found; 105948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa} 106948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 107948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa/** all of 'a' up to len must be a (+|00|011)country code) 108948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * We're fast and loose with the country code. Any \d{1,3} matches */ 109948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawastatic bool matchIntlPrefixAndCC(const char* a, int len) 110948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa{ 111948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa /* [^0-9*#+]*(\+|0(0|11)\d\d?\d? [^0-9*#+] $ */ 112948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa /* 0 1 2 3 45 6 7 8 */ 113948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 114948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa int state = 0; 115948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa for (int i = 0 ; i < len ; i++ ) { 116948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa char c = a[i]; 117948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 118948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa switch (state) { 119948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa case 0: 120948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (c == '+') state = 1; 121948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa else if (c == '0') state = 2; 122948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa else if (isNonSeparator(c)) return false; 123948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa break; 124948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 125948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa case 2: 126948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (c == '0') state = 3; 127948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa else if (c == '1') state = 4; 128948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa else if (isNonSeparator(c)) return false; 129948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa break; 130948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 131948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa case 4: 132948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (c == '1') state = 5; 133948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa else if (isNonSeparator(c)) return false; 134948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa break; 135948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 136948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa case 1: 137948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa case 3: 138948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa case 5: 139948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (isISODigit(c)) state = 6; 140948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa else if (isNonSeparator(c)) return false; 141948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa break; 142948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 143948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa case 6: 144948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa case 7: 145948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (isISODigit(c)) state++; 146948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa else if (isNonSeparator(c)) return false; 147948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa break; 148948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 149948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa default: 150948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (isNonSeparator(c)) return false; 151948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } 152948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } 153948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 154948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa return state == 6 || state == 7 || state == 8; 155948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa} 156948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 157948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa/** or -1 if both are negative */ 158948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawastatic int minPositive(int a, int b) 159948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa{ 160948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (a >= 0 && b >= 0) { 161948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa return (a < b) ? a : b; 162948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } else if (a >= 0) { /* && b < 0 */ 163948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa return a; 164948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } else if (b >= 0) { /* && a < 0 */ 165948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa return b; 166948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } else { /* a < 0 && b < 0 */ 167948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa return -1; 168948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } 169948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa} 170948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 171948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa/** 172948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * Return the offset into a of the first appearance of b, or -1 if there 173948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * is no such character in a. 174948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa */ 175948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawastatic int indexOf(const char *a, char b) { 176d519668b62d5a402a2abc003c02e436f2424cdb8Mike Lockwood const char *ix = strchr(a, b); 177948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 178948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (ix == NULL) 179948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa return -1; 180948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa else 181948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa return ix - a; 182948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa} 183948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 184948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa/** 185948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * Compare phone numbers a and b, return true if they're identical 186948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * enough for caller ID purposes. 187948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * 188948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * - Compares from right to left 1893fffdd3714c6d4de821269bcefb65d897151c2f2Wei Huang * - requires MIN_MATCH (7) characters to match 190948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * - handles common trunk prefixes and international prefixes 191948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * (basically, everything except the Russian trunk prefix) 192948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * 193948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * Tolerates nulls 194948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa */ 195948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawabool phone_number_compare_loose(const char* a, const char* b) 196948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa{ 197948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa int ia, ib; 198948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa int matched; 199fd20ece0e27308d9b5e314b1cc8d5fa3a0d174eaWei Huang int numSeparatorCharsInA = 0; 200fd20ece0e27308d9b5e314b1cc8d5fa3a0d174eaWei Huang int numSeparatorCharsInB = 0; 201948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 202948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (a == NULL || b == NULL) { 203948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa return false; 204948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } 205948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 206948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa ia = strlen(a); 207948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa ib = strlen(b); 208948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (ia == 0 || ib == 0) { 209948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa return false; 210948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } 211948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 212948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa // Compare from right to left 213948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa ia--; 214948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa ib--; 215948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 216948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa matched = 0; 217948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 218948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa while (ia >= 0 && ib >=0) { 219948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa char ca, cb; 220948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa bool skipCmp = false; 221948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 222948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa ca = a[ia]; 223948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 224948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (!isNonSeparator(ca)) { 225948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa ia--; 226948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa skipCmp = true; 227fd20ece0e27308d9b5e314b1cc8d5fa3a0d174eaWei Huang numSeparatorCharsInA++; 228948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } 229948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 230948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa cb = b[ib]; 231948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 232948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (!isNonSeparator(cb)) { 233948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa ib--; 234948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa skipCmp = true; 235fd20ece0e27308d9b5e314b1cc8d5fa3a0d174eaWei Huang numSeparatorCharsInB++; 236948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } 237948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 238948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (!skipCmp) { 239948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (cb != ca) { 240948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa break; 241948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } 242948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa ia--; ib--; matched++; 243948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } 244948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } 245948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 246948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (matched < MIN_MATCH) { 247fd20ece0e27308d9b5e314b1cc8d5fa3a0d174eaWei Huang const int effectiveALen = strlen(a) - numSeparatorCharsInA; 248fd20ece0e27308d9b5e314b1cc8d5fa3a0d174eaWei Huang const int effectiveBLen = strlen(b) - numSeparatorCharsInB; 249948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 250fd20ece0e27308d9b5e314b1cc8d5fa3a0d174eaWei Huang // if the number of dialable chars in a and b match, but the matched chars < MIN_MATCH, 251fd20ece0e27308d9b5e314b1cc8d5fa3a0d174eaWei Huang // treat them as equal (i.e. 404-04 and 40404) 252fd20ece0e27308d9b5e314b1cc8d5fa3a0d174eaWei Huang if (effectiveALen == effectiveBLen && effectiveALen == matched) { 253948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa return true; 254948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } 255fd20ece0e27308d9b5e314b1cc8d5fa3a0d174eaWei Huang 256948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa return false; 257948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } 258948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 259948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa // At least one string has matched completely; 260948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (matched >= MIN_MATCH && (ia < 0 || ib < 0)) { 261948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa return true; 262948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } 263948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 264948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa /* 265948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * Now, what remains must be one of the following for a 266948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * match: 267948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * 268948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * - a '+' on one and a '00' or a '011' on the other 269948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * - a '0' on one and a (+,00)<country code> on the other 270948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * (for this, a '0' and a '00' prefix would have succeeded above) 271948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa */ 272948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 273948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (matchIntlPrefix(a, ia + 1) && matchIntlPrefix(b, ib +1)) { 274948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa return true; 275948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } 276948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 277948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (matchTrunkPrefix(a, ia + 1) && matchIntlPrefixAndCC(b, ib +1)) { 278948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa return true; 279948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } 280948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 281948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (matchTrunkPrefix(b, ib + 1) && matchIntlPrefixAndCC(a, ia +1)) { 282948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa return true; 283948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } 284948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 285948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa /* 286948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * Last resort: if the number of unmatched characters on both sides is less than or equal 287948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * to the length of the longest country code and only one number starts with a + accept 288948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * the match. This is because some countries like France and Russia have an extra prefix 289948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * digit that is used when dialing locally in country that does not show up when you dial 290948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * the number using the country code. In France this prefix digit is used to determine 291948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa * which land line carrier to route the call over. 292948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa */ 293948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa bool aPlusFirst = (*a == '+'); 294948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa bool bPlusFirst = (*b == '+'); 295948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa if (ia < 4 && ib < 4 && (aPlusFirst || bPlusFirst) && !(aPlusFirst && bPlusFirst)) { 296948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa return true; 297948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa } 298948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 299948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa return false; 300948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa} 301948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa 302948a119c94f8b69760437c7d1e784b498cd9b766Daisuke Miyakawa} // namespace android 303