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