xref: /aosp_15_r20/external/sqlite/android/PhoneNumberUtils.cpp (revision a3141fd39888aecc864dfb08485df64ff6c387f9)
1*a3141fd3SAndroid Build Coastguard Worker /*
2*a3141fd3SAndroid Build Coastguard Worker  * Copyright 2009, The Android Open Source Project
3*a3141fd3SAndroid Build Coastguard Worker  *
4*a3141fd3SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*a3141fd3SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*a3141fd3SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*a3141fd3SAndroid Build Coastguard Worker  *
8*a3141fd3SAndroid Build Coastguard Worker  *     http://www.apache.org/licenses/LICENSE-2.0
9*a3141fd3SAndroid Build Coastguard Worker  *
10*a3141fd3SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*a3141fd3SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*a3141fd3SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*a3141fd3SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*a3141fd3SAndroid Build Coastguard Worker  * limitations under the License.
15*a3141fd3SAndroid Build Coastguard Worker  */
16*a3141fd3SAndroid Build Coastguard Worker 
17*a3141fd3SAndroid Build Coastguard Worker #include <ctype.h>
18*a3141fd3SAndroid Build Coastguard Worker #include <string.h>
19*a3141fd3SAndroid Build Coastguard Worker 
20*a3141fd3SAndroid Build Coastguard Worker namespace android {
21*a3141fd3SAndroid Build Coastguard Worker 
22*a3141fd3SAndroid Build Coastguard Worker /* Generated by the following Python script. Values of country calling codes
23*a3141fd3SAndroid Build Coastguard Worker    are from http://en.wikipedia.org/wiki/List_of_country_calling_codes
24*a3141fd3SAndroid Build Coastguard Worker 
25*a3141fd3SAndroid Build Coastguard Worker #!/usr/bin/python
26*a3141fd3SAndroid Build Coastguard Worker import sys
27*a3141fd3SAndroid Build Coastguard Worker ccc_set_2digits = set([0, 1, 7,
28*a3141fd3SAndroid Build Coastguard Worker                        20, 27, 28, 30, 31, 32, 33, 34, 36, 39, 40, 43, 44, 45,
29*a3141fd3SAndroid Build Coastguard Worker                        46, 47, 48, 49, 51, 52, 53, 54, 55, 56, 57, 58, 60, 61,
30*a3141fd3SAndroid Build Coastguard Worker                        62, 63, 64, 65, 66, 81, 82, 83, 84, 86, 89, 90, 91, 92,
31*a3141fd3SAndroid Build Coastguard Worker                        93, 94, 95, 98])
32*a3141fd3SAndroid Build Coastguard Worker 
33*a3141fd3SAndroid Build Coastguard Worker ONE_LINE_NUM = 10
34*a3141fd3SAndroid Build Coastguard Worker 
35*a3141fd3SAndroid Build Coastguard Worker for i in xrange(100):
36*a3141fd3SAndroid Build Coastguard Worker   if i % ONE_LINE_NUM == 0:
37*a3141fd3SAndroid Build Coastguard Worker     sys.stdout.write('    ')
38*a3141fd3SAndroid Build Coastguard Worker   if i in ccc_set_2digits:
39*a3141fd3SAndroid Build Coastguard Worker     included = 'true'
40*a3141fd3SAndroid Build Coastguard Worker   else:
41*a3141fd3SAndroid Build Coastguard Worker     included = 'false'
42*a3141fd3SAndroid Build Coastguard Worker   sys.stdout.write(included + ',')
43*a3141fd3SAndroid Build Coastguard Worker   if ((i + 1) % ONE_LINE_NUM) == 0:
44*a3141fd3SAndroid Build Coastguard Worker     sys.stdout.write('\n')
45*a3141fd3SAndroid Build Coastguard Worker   else:
46*a3141fd3SAndroid Build Coastguard Worker     sys.stdout.write(' ')
47*a3141fd3SAndroid Build Coastguard Worker */
48*a3141fd3SAndroid Build Coastguard Worker static bool two_length_country_code_map[100] = {
49*a3141fd3SAndroid Build Coastguard Worker     true, true, false, false, false, false, false, true, false, false,
50*a3141fd3SAndroid Build Coastguard Worker     false, false, false, false, false, false, false, false, false, false,
51*a3141fd3SAndroid Build Coastguard Worker     true, false, false, false, false, false, false, true, true, false,
52*a3141fd3SAndroid Build Coastguard Worker     true, true, true, true, true, false, true, false, false, true,
53*a3141fd3SAndroid Build Coastguard Worker     true, false, false, true, true, true, true, true, true, true,
54*a3141fd3SAndroid Build Coastguard Worker     false, true, true, true, true, true, true, true, true, false,
55*a3141fd3SAndroid Build Coastguard Worker     true, true, true, true, true, true, true, false, false, false,
56*a3141fd3SAndroid Build Coastguard Worker     false, false, false, false, false, false, false, false, false, false,
57*a3141fd3SAndroid Build Coastguard Worker     false, true, true, true, true, false, true, false, false, true,
58*a3141fd3SAndroid Build Coastguard Worker     true, true, true, true, true, true, false, false, true, false,
59*a3141fd3SAndroid Build Coastguard Worker };
60*a3141fd3SAndroid Build Coastguard Worker 
61*a3141fd3SAndroid Build Coastguard Worker #define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
62*a3141fd3SAndroid Build Coastguard Worker 
63*a3141fd3SAndroid Build Coastguard Worker /**
64*a3141fd3SAndroid Build Coastguard Worker  * Returns true if "ccc_candidate" expresses (part of ) some country calling
65*a3141fd3SAndroid Build Coastguard Worker  * code.
66*a3141fd3SAndroid Build Coastguard Worker  * Returns false otherwise.
67*a3141fd3SAndroid Build Coastguard Worker  */
isCountryCallingCode(int ccc_candidate)68*a3141fd3SAndroid Build Coastguard Worker static bool isCountryCallingCode(int ccc_candidate) {
69*a3141fd3SAndroid Build Coastguard Worker     return ccc_candidate > 0 &&
70*a3141fd3SAndroid Build Coastguard Worker             ccc_candidate < (int)ARRAY_SIZE(two_length_country_code_map) &&
71*a3141fd3SAndroid Build Coastguard Worker             two_length_country_code_map[ccc_candidate];
72*a3141fd3SAndroid Build Coastguard Worker }
73*a3141fd3SAndroid Build Coastguard Worker 
74*a3141fd3SAndroid Build Coastguard Worker /**
75*a3141fd3SAndroid Build Coastguard Worker  * Returns interger corresponding to the input if input "ch" is
76*a3141fd3SAndroid Build Coastguard Worker  * ISO-LATIN characters 0-9.
77*a3141fd3SAndroid Build Coastguard Worker  * Returns -1 otherwise
78*a3141fd3SAndroid Build Coastguard Worker  */
tryGetISODigit(char ch)79*a3141fd3SAndroid Build Coastguard Worker static int tryGetISODigit (char ch)
80*a3141fd3SAndroid Build Coastguard Worker {
81*a3141fd3SAndroid Build Coastguard Worker     if ('0' <= ch && ch <= '9') {
82*a3141fd3SAndroid Build Coastguard Worker         return ch - '0';
83*a3141fd3SAndroid Build Coastguard Worker     } else {
84*a3141fd3SAndroid Build Coastguard Worker         return -1;
85*a3141fd3SAndroid Build Coastguard Worker     }
86*a3141fd3SAndroid Build Coastguard Worker }
87*a3141fd3SAndroid Build Coastguard Worker 
88*a3141fd3SAndroid Build Coastguard Worker /**
89*a3141fd3SAndroid Build Coastguard Worker  * True if ch is ISO-LATIN characters 0-9, *, # , +
90*a3141fd3SAndroid Build Coastguard Worker  * Note this method current does not account for the WILD char 'N'
91*a3141fd3SAndroid Build Coastguard Worker  */
isDialable(char ch)92*a3141fd3SAndroid Build Coastguard Worker static bool isDialable(char ch)
93*a3141fd3SAndroid Build Coastguard Worker {
94*a3141fd3SAndroid Build Coastguard Worker     return ('0' <= ch && ch <= '9') || ch == '*' || ch == '#' || ch == '+';
95*a3141fd3SAndroid Build Coastguard Worker }
96*a3141fd3SAndroid Build Coastguard Worker 
97*a3141fd3SAndroid Build Coastguard Worker /** Returns true if ch is not dialable or alpha char */
isSeparator(char ch)98*a3141fd3SAndroid Build Coastguard Worker static bool isSeparator(char ch)
99*a3141fd3SAndroid Build Coastguard Worker {
100*a3141fd3SAndroid Build Coastguard Worker     return !isDialable(ch) && (isalpha(ch) == 0);
101*a3141fd3SAndroid Build Coastguard Worker }
102*a3141fd3SAndroid Build Coastguard Worker 
103*a3141fd3SAndroid Build Coastguard Worker /**
104*a3141fd3SAndroid Build Coastguard Worker  * Try to store the pointer to "new_ptr" which does not have trunk prefix.
105*a3141fd3SAndroid Build Coastguard Worker  *
106*a3141fd3SAndroid Build Coastguard Worker  * Currently this function simply ignore the first digit assuming it is
107*a3141fd3SAndroid Build Coastguard Worker  * trunk prefix. Actually trunk prefix is different in each country.
108*a3141fd3SAndroid Build Coastguard Worker  *
109*a3141fd3SAndroid Build Coastguard Worker  * e.g.
110*a3141fd3SAndroid Build Coastguard Worker  * "+79161234567" equals "89161234567" (Russian trunk digit is 8)
111*a3141fd3SAndroid Build Coastguard Worker  * "+33123456789" equals "0123456789" (French trunk digit is 0)
112*a3141fd3SAndroid Build Coastguard Worker  *
113*a3141fd3SAndroid Build Coastguard Worker  */
tryGetTrunkPrefixOmittedStr(const char * str,size_t len,const char ** new_ptr,size_t * new_len)114*a3141fd3SAndroid Build Coastguard Worker static bool tryGetTrunkPrefixOmittedStr(const char *str, size_t len,
115*a3141fd3SAndroid Build Coastguard Worker                                         const char **new_ptr, size_t *new_len)
116*a3141fd3SAndroid Build Coastguard Worker {
117*a3141fd3SAndroid Build Coastguard Worker     for (size_t i = 0 ; i < len ; i++) {
118*a3141fd3SAndroid Build Coastguard Worker         char ch = str[i];
119*a3141fd3SAndroid Build Coastguard Worker         if (tryGetISODigit(ch) >= 0) {
120*a3141fd3SAndroid Build Coastguard Worker             if (new_ptr != NULL) {
121*a3141fd3SAndroid Build Coastguard Worker                 *new_ptr = str + i + 1;
122*a3141fd3SAndroid Build Coastguard Worker             }
123*a3141fd3SAndroid Build Coastguard Worker             if (new_len != NULL) {
124*a3141fd3SAndroid Build Coastguard Worker                 *new_len = len - (i + 1);
125*a3141fd3SAndroid Build Coastguard Worker             }
126*a3141fd3SAndroid Build Coastguard Worker             return true;
127*a3141fd3SAndroid Build Coastguard Worker         } else if (isDialable(ch)) {
128*a3141fd3SAndroid Build Coastguard Worker             return false;
129*a3141fd3SAndroid Build Coastguard Worker         }
130*a3141fd3SAndroid Build Coastguard Worker     }
131*a3141fd3SAndroid Build Coastguard Worker 
132*a3141fd3SAndroid Build Coastguard Worker     return false;
133*a3141fd3SAndroid Build Coastguard Worker }
134*a3141fd3SAndroid Build Coastguard Worker 
135*a3141fd3SAndroid Build Coastguard Worker /*
136*a3141fd3SAndroid Build Coastguard Worker  * Note that this function does not strictly care the country calling code with
137*a3141fd3SAndroid Build Coastguard Worker  * 3 length (like Morocco: +212), assuming it is enough to use the first two
138*a3141fd3SAndroid Build Coastguard Worker  * digit to compare two phone numbers.
139*a3141fd3SAndroid Build Coastguard Worker  */
tryGetCountryCallingCode(const char * str,size_t len,const char ** new_ptr,size_t * new_len,bool accept_thailand_case)140*a3141fd3SAndroid Build Coastguard Worker static int tryGetCountryCallingCode(const char *str, size_t len,
141*a3141fd3SAndroid Build Coastguard Worker                                     const char **new_ptr, size_t *new_len,
142*a3141fd3SAndroid Build Coastguard Worker                                     bool accept_thailand_case)
143*a3141fd3SAndroid Build Coastguard Worker {
144*a3141fd3SAndroid Build Coastguard Worker     // Rough regexp:
145*a3141fd3SAndroid Build Coastguard Worker     //  ^[^0-9*#+]*((\+|0(0|11)\d\d?|166) [^0-9*#+] $
146*a3141fd3SAndroid Build Coastguard Worker     //         0        1 2 3 45  6 7  89
147*a3141fd3SAndroid Build Coastguard Worker     //
148*a3141fd3SAndroid Build Coastguard Worker     // In all the states, this function ignores separator characters.
149*a3141fd3SAndroid Build Coastguard Worker     // "166" is the special case for the call from Thailand to the US. Ugu!
150*a3141fd3SAndroid Build Coastguard Worker 
151*a3141fd3SAndroid Build Coastguard Worker     int state = 0;
152*a3141fd3SAndroid Build Coastguard Worker     int ccc = 0;
153*a3141fd3SAndroid Build Coastguard Worker     for (size_t i = 0 ; i < len ; i++ ) {
154*a3141fd3SAndroid Build Coastguard Worker         char ch = str[i];
155*a3141fd3SAndroid Build Coastguard Worker         switch (state) {
156*a3141fd3SAndroid Build Coastguard Worker             case 0:
157*a3141fd3SAndroid Build Coastguard Worker                 if      (ch == '+') state = 1;
158*a3141fd3SAndroid Build Coastguard Worker                 else if (ch == '0') state = 2;
159*a3141fd3SAndroid Build Coastguard Worker                 else if (ch == '1') {
160*a3141fd3SAndroid Build Coastguard Worker                     if (accept_thailand_case) {
161*a3141fd3SAndroid Build Coastguard Worker                         state = 8;
162*a3141fd3SAndroid Build Coastguard Worker                     } else {
163*a3141fd3SAndroid Build Coastguard Worker                         return -1;
164*a3141fd3SAndroid Build Coastguard Worker                     }
165*a3141fd3SAndroid Build Coastguard Worker                 } else if (isDialable(ch)) return -1;
166*a3141fd3SAndroid Build Coastguard Worker             break;
167*a3141fd3SAndroid Build Coastguard Worker 
168*a3141fd3SAndroid Build Coastguard Worker             case 2:
169*a3141fd3SAndroid Build Coastguard Worker                 if      (ch == '0') state = 3;
170*a3141fd3SAndroid Build Coastguard Worker                 else if (ch == '1') state = 4;
171*a3141fd3SAndroid Build Coastguard Worker                 else if (isDialable(ch)) return -1;
172*a3141fd3SAndroid Build Coastguard Worker             break;
173*a3141fd3SAndroid Build Coastguard Worker 
174*a3141fd3SAndroid Build Coastguard Worker             case 4:
175*a3141fd3SAndroid Build Coastguard Worker                 if      (ch == '1') state = 5;
176*a3141fd3SAndroid Build Coastguard Worker                 else if (isDialable(ch)) return -1;
177*a3141fd3SAndroid Build Coastguard Worker             break;
178*a3141fd3SAndroid Build Coastguard Worker 
179*a3141fd3SAndroid Build Coastguard Worker             case 1:
180*a3141fd3SAndroid Build Coastguard Worker             case 3:
181*a3141fd3SAndroid Build Coastguard Worker             case 5:
182*a3141fd3SAndroid Build Coastguard Worker             case 6:
183*a3141fd3SAndroid Build Coastguard Worker             case 7:
184*a3141fd3SAndroid Build Coastguard Worker                 {
185*a3141fd3SAndroid Build Coastguard Worker                     int ret = tryGetISODigit(ch);
186*a3141fd3SAndroid Build Coastguard Worker                     if (ret > 0) {
187*a3141fd3SAndroid Build Coastguard Worker                         ccc = ccc * 10 + ret;
188*a3141fd3SAndroid Build Coastguard Worker                         if (ccc >= 100 || isCountryCallingCode(ccc)) {
189*a3141fd3SAndroid Build Coastguard Worker                             if (new_ptr != NULL) {
190*a3141fd3SAndroid Build Coastguard Worker                                 *new_ptr = str + i + 1;
191*a3141fd3SAndroid Build Coastguard Worker                             }
192*a3141fd3SAndroid Build Coastguard Worker                             if (new_len != NULL) {
193*a3141fd3SAndroid Build Coastguard Worker                                 *new_len = len - (i + 1);
194*a3141fd3SAndroid Build Coastguard Worker                             }
195*a3141fd3SAndroid Build Coastguard Worker                             return ccc;
196*a3141fd3SAndroid Build Coastguard Worker                         }
197*a3141fd3SAndroid Build Coastguard Worker                         if (state == 1 || state == 3 || state == 5) {
198*a3141fd3SAndroid Build Coastguard Worker                             state = 6;
199*a3141fd3SAndroid Build Coastguard Worker                         } else {
200*a3141fd3SAndroid Build Coastguard Worker                             state++;
201*a3141fd3SAndroid Build Coastguard Worker                         }
202*a3141fd3SAndroid Build Coastguard Worker                     } else if (isDialable(ch)) {
203*a3141fd3SAndroid Build Coastguard Worker                         return -1;
204*a3141fd3SAndroid Build Coastguard Worker                     }
205*a3141fd3SAndroid Build Coastguard Worker                 }
206*a3141fd3SAndroid Build Coastguard Worker                 break;
207*a3141fd3SAndroid Build Coastguard Worker             case 8:
208*a3141fd3SAndroid Build Coastguard Worker                 if (ch == '6') state = 9;
209*a3141fd3SAndroid Build Coastguard Worker                 else if (isDialable(ch)) return -1;
210*a3141fd3SAndroid Build Coastguard Worker                 break;
211*a3141fd3SAndroid Build Coastguard Worker             case 9:
212*a3141fd3SAndroid Build Coastguard Worker                 if (ch == '6') {
213*a3141fd3SAndroid Build Coastguard Worker                     if (new_ptr != NULL) {
214*a3141fd3SAndroid Build Coastguard Worker                         *new_ptr = str + i + 1;
215*a3141fd3SAndroid Build Coastguard Worker                     }
216*a3141fd3SAndroid Build Coastguard Worker                     if (new_len != NULL) {
217*a3141fd3SAndroid Build Coastguard Worker                         *new_len = len - (i + 1);
218*a3141fd3SAndroid Build Coastguard Worker                     }
219*a3141fd3SAndroid Build Coastguard Worker                     return 66;
220*a3141fd3SAndroid Build Coastguard Worker                 } else {
221*a3141fd3SAndroid Build Coastguard Worker                     return -1;
222*a3141fd3SAndroid Build Coastguard Worker                 }
223*a3141fd3SAndroid Build Coastguard Worker                 break;
224*a3141fd3SAndroid Build Coastguard Worker             default:
225*a3141fd3SAndroid Build Coastguard Worker                 return -1;
226*a3141fd3SAndroid Build Coastguard Worker         }
227*a3141fd3SAndroid Build Coastguard Worker     }
228*a3141fd3SAndroid Build Coastguard Worker 
229*a3141fd3SAndroid Build Coastguard Worker     return -1;
230*a3141fd3SAndroid Build Coastguard Worker }
231*a3141fd3SAndroid Build Coastguard Worker 
232*a3141fd3SAndroid Build Coastguard Worker /**
233*a3141fd3SAndroid Build Coastguard Worker  * Return true if the prefix of "ch" is "ignorable". Here, "ignorable" means
234*a3141fd3SAndroid Build Coastguard Worker  * that "ch" has only one digit and separator characters. The one digit is
235*a3141fd3SAndroid Build Coastguard Worker  * assumed to be the trunk prefix.
236*a3141fd3SAndroid Build Coastguard Worker  */
checkPrefixIsIgnorable(const char * ch,int i)237*a3141fd3SAndroid Build Coastguard Worker static bool checkPrefixIsIgnorable(const char* ch, int i) {
238*a3141fd3SAndroid Build Coastguard Worker     bool trunk_prefix_was_read = false;
239*a3141fd3SAndroid Build Coastguard Worker     while (i >= 0) {
240*a3141fd3SAndroid Build Coastguard Worker         if (tryGetISODigit(ch[i]) >= 0) {
241*a3141fd3SAndroid Build Coastguard Worker             if (trunk_prefix_was_read) {
242*a3141fd3SAndroid Build Coastguard Worker                 // More than one digit appeared, meaning that "a" and "b"
243*a3141fd3SAndroid Build Coastguard Worker                 // is different.
244*a3141fd3SAndroid Build Coastguard Worker                 return false;
245*a3141fd3SAndroid Build Coastguard Worker             } else {
246*a3141fd3SAndroid Build Coastguard Worker                 // Ignore just one digit, assuming it is trunk prefix.
247*a3141fd3SAndroid Build Coastguard Worker                 trunk_prefix_was_read = true;
248*a3141fd3SAndroid Build Coastguard Worker             }
249*a3141fd3SAndroid Build Coastguard Worker         } else if (isDialable(ch[i])) {
250*a3141fd3SAndroid Build Coastguard Worker             // Trunk prefix is a digit, not "*", "#"...
251*a3141fd3SAndroid Build Coastguard Worker             return false;
252*a3141fd3SAndroid Build Coastguard Worker         }
253*a3141fd3SAndroid Build Coastguard Worker         i--;
254*a3141fd3SAndroid Build Coastguard Worker     }
255*a3141fd3SAndroid Build Coastguard Worker 
256*a3141fd3SAndroid Build Coastguard Worker     return true;
257*a3141fd3SAndroid Build Coastguard Worker }
258*a3141fd3SAndroid Build Coastguard Worker 
259*a3141fd3SAndroid Build Coastguard Worker /**
260*a3141fd3SAndroid Build Coastguard Worker  * Compare phone numbers a and b, return true if they're identical
261*a3141fd3SAndroid Build Coastguard Worker  * enough for caller ID purposes.
262*a3141fd3SAndroid Build Coastguard Worker  *
263*a3141fd3SAndroid Build Coastguard Worker  * Assume NULL as 0-length string.
264*a3141fd3SAndroid Build Coastguard Worker  *
265*a3141fd3SAndroid Build Coastguard Worker  * Detailed information:
266*a3141fd3SAndroid Build Coastguard Worker  * Currently (as of 2009-06-12), we cannot depend on the locale given from the
267*a3141fd3SAndroid Build Coastguard Worker  * OS. For example, current Android does not accept "en_JP", meaning
268*a3141fd3SAndroid Build Coastguard Worker  * "the display language is English but the phone should be in Japan", but
269*a3141fd3SAndroid Build Coastguard Worker  * en_US, es_US, etc. So we cannot identify which digit is valid trunk prefix
270*a3141fd3SAndroid Build Coastguard Worker  * in the country where the phone is used. More specifically, "880-1234-1234"
271*a3141fd3SAndroid Build Coastguard Worker  * is not valid phone number in Japan since the trunk prefix in Japan is not 8
272*a3141fd3SAndroid Build Coastguard Worker  * but 0 (correct number should be "080-1234-1234"), while Russian trunk prefix
273*a3141fd3SAndroid Build Coastguard Worker  * is 8. Also, we cannot know whether the country where users live has trunk
274*a3141fd3SAndroid Build Coastguard Worker  * prefix itself. So, we cannot determine whether "+81-80-1234-1234" is NOT
275*a3141fd3SAndroid Build Coastguard Worker  * same as "880-1234-1234" (while "+81-80-1234-1234" is same as "080-1234-1234"
276*a3141fd3SAndroid Build Coastguard Worker  * and we can determine "880-1234-1234" is different from "080-1234-1234").
277*a3141fd3SAndroid Build Coastguard Worker  *
278*a3141fd3SAndroid Build Coastguard Worker  * In the future, we should handle trunk prefix more correctly, but as of now,
279*a3141fd3SAndroid Build Coastguard Worker  * we just ignore it...
280*a3141fd3SAndroid Build Coastguard Worker  */
phone_number_compare_inter(const char * const org_a,const char * const org_b,bool accept_thailand_case)281*a3141fd3SAndroid Build Coastguard Worker static bool phone_number_compare_inter(const char* const org_a, const char* const org_b,
282*a3141fd3SAndroid Build Coastguard Worker                                        bool accept_thailand_case)
283*a3141fd3SAndroid Build Coastguard Worker {
284*a3141fd3SAndroid Build Coastguard Worker     const char* a = org_a;
285*a3141fd3SAndroid Build Coastguard Worker     const char* b = org_b;
286*a3141fd3SAndroid Build Coastguard Worker     size_t len_a = 0;
287*a3141fd3SAndroid Build Coastguard Worker     size_t len_b = 0;
288*a3141fd3SAndroid Build Coastguard Worker     if (a == NULL) {
289*a3141fd3SAndroid Build Coastguard Worker         a = "";
290*a3141fd3SAndroid Build Coastguard Worker     } else {
291*a3141fd3SAndroid Build Coastguard Worker         len_a = strlen(a);
292*a3141fd3SAndroid Build Coastguard Worker     }
293*a3141fd3SAndroid Build Coastguard Worker     if (b == NULL) {
294*a3141fd3SAndroid Build Coastguard Worker         b = "";
295*a3141fd3SAndroid Build Coastguard Worker     } else {
296*a3141fd3SAndroid Build Coastguard Worker         len_b = strlen(b);
297*a3141fd3SAndroid Build Coastguard Worker     }
298*a3141fd3SAndroid Build Coastguard Worker 
299*a3141fd3SAndroid Build Coastguard Worker     const char* tmp_a = NULL;
300*a3141fd3SAndroid Build Coastguard Worker     const char* tmp_b = NULL;
301*a3141fd3SAndroid Build Coastguard Worker     size_t tmp_len_a = len_a;
302*a3141fd3SAndroid Build Coastguard Worker     size_t tmp_len_b = len_b;
303*a3141fd3SAndroid Build Coastguard Worker 
304*a3141fd3SAndroid Build Coastguard Worker     int ccc_a = tryGetCountryCallingCode(a, len_a, &tmp_a, &tmp_len_a, accept_thailand_case);
305*a3141fd3SAndroid Build Coastguard Worker     int ccc_b = tryGetCountryCallingCode(b, len_b, &tmp_b, &tmp_len_b, accept_thailand_case);
306*a3141fd3SAndroid Build Coastguard Worker     bool both_have_ccc = false;
307*a3141fd3SAndroid Build Coastguard Worker     bool may_ignore_prefix = true;
308*a3141fd3SAndroid Build Coastguard Worker     bool trunk_prefix_is_omitted_a = false;
309*a3141fd3SAndroid Build Coastguard Worker     bool trunk_prefix_is_omitted_b = false;
310*a3141fd3SAndroid Build Coastguard Worker     if (ccc_a >= 0 && ccc_b >= 0) {
311*a3141fd3SAndroid Build Coastguard Worker         if (ccc_a != ccc_b) {
312*a3141fd3SAndroid Build Coastguard Worker             // Different Country Calling Code. Must be different phone number.
313*a3141fd3SAndroid Build Coastguard Worker             return false;
314*a3141fd3SAndroid Build Coastguard Worker         }
315*a3141fd3SAndroid Build Coastguard Worker         // When both have ccc, do not ignore trunk prefix. Without this,
316*a3141fd3SAndroid Build Coastguard Worker         // "+81123123" becomes same as "+810123123" (+81 == Japan)
317*a3141fd3SAndroid Build Coastguard Worker         may_ignore_prefix = false;
318*a3141fd3SAndroid Build Coastguard Worker         both_have_ccc = true;
319*a3141fd3SAndroid Build Coastguard Worker     } else if (ccc_a < 0 && ccc_b < 0) {
320*a3141fd3SAndroid Build Coastguard Worker         // When both do not have ccc, do not ignore trunk prefix. Without this,
321*a3141fd3SAndroid Build Coastguard Worker         // "123123" becomes same as "0123123"
322*a3141fd3SAndroid Build Coastguard Worker         may_ignore_prefix = false;
323*a3141fd3SAndroid Build Coastguard Worker     } else {
324*a3141fd3SAndroid Build Coastguard Worker         if (ccc_a < 0) {
325*a3141fd3SAndroid Build Coastguard Worker             tryGetTrunkPrefixOmittedStr(a, len_a, &tmp_a, &tmp_len_a);
326*a3141fd3SAndroid Build Coastguard Worker             trunk_prefix_is_omitted_a = true;
327*a3141fd3SAndroid Build Coastguard Worker         }
328*a3141fd3SAndroid Build Coastguard Worker         if (ccc_b < 0) {
329*a3141fd3SAndroid Build Coastguard Worker             tryGetTrunkPrefixOmittedStr(b, len_b, &tmp_b, &tmp_len_b);
330*a3141fd3SAndroid Build Coastguard Worker             trunk_prefix_is_omitted_b = true;
331*a3141fd3SAndroid Build Coastguard Worker         }
332*a3141fd3SAndroid Build Coastguard Worker     }
333*a3141fd3SAndroid Build Coastguard Worker 
334*a3141fd3SAndroid Build Coastguard Worker     if (tmp_a != NULL) {
335*a3141fd3SAndroid Build Coastguard Worker         a = tmp_a;
336*a3141fd3SAndroid Build Coastguard Worker         len_a = tmp_len_a;
337*a3141fd3SAndroid Build Coastguard Worker     }
338*a3141fd3SAndroid Build Coastguard Worker     if (tmp_b != NULL) {
339*a3141fd3SAndroid Build Coastguard Worker         b = tmp_b;
340*a3141fd3SAndroid Build Coastguard Worker         len_b = tmp_len_b;
341*a3141fd3SAndroid Build Coastguard Worker     }
342*a3141fd3SAndroid Build Coastguard Worker 
343*a3141fd3SAndroid Build Coastguard Worker     int i_a = len_a - 1;
344*a3141fd3SAndroid Build Coastguard Worker     int i_b = len_b - 1;
345*a3141fd3SAndroid Build Coastguard Worker     while (i_a >= 0 && i_b >= 0) {
346*a3141fd3SAndroid Build Coastguard Worker         bool skip_compare = false;
347*a3141fd3SAndroid Build Coastguard Worker         char ch_a = a[i_a];
348*a3141fd3SAndroid Build Coastguard Worker         char ch_b = b[i_b];
349*a3141fd3SAndroid Build Coastguard Worker         if (isSeparator(ch_a)) {
350*a3141fd3SAndroid Build Coastguard Worker             i_a--;
351*a3141fd3SAndroid Build Coastguard Worker             skip_compare = true;
352*a3141fd3SAndroid Build Coastguard Worker         }
353*a3141fd3SAndroid Build Coastguard Worker         if (isSeparator(ch_b)) {
354*a3141fd3SAndroid Build Coastguard Worker             i_b--;
355*a3141fd3SAndroid Build Coastguard Worker             skip_compare = true;
356*a3141fd3SAndroid Build Coastguard Worker         }
357*a3141fd3SAndroid Build Coastguard Worker 
358*a3141fd3SAndroid Build Coastguard Worker         if (!skip_compare) {
359*a3141fd3SAndroid Build Coastguard Worker             if (ch_a != ch_b) {
360*a3141fd3SAndroid Build Coastguard Worker                 return false;
361*a3141fd3SAndroid Build Coastguard Worker             }
362*a3141fd3SAndroid Build Coastguard Worker             i_a--;
363*a3141fd3SAndroid Build Coastguard Worker             i_b--;
364*a3141fd3SAndroid Build Coastguard Worker         }
365*a3141fd3SAndroid Build Coastguard Worker     }
366*a3141fd3SAndroid Build Coastguard Worker 
367*a3141fd3SAndroid Build Coastguard Worker     if (may_ignore_prefix) {
368*a3141fd3SAndroid Build Coastguard Worker         bool trunk_prefix_ignorable_a = checkPrefixIsIgnorable(a, i_a);
369*a3141fd3SAndroid Build Coastguard Worker         if ((trunk_prefix_is_omitted_a && i_a >= 0) || !trunk_prefix_ignorable_a) {
370*a3141fd3SAndroid Build Coastguard Worker             if (accept_thailand_case) {
371*a3141fd3SAndroid Build Coastguard Worker                 // Maybe the code handling the special case for Thailand makes the
372*a3141fd3SAndroid Build Coastguard Worker                 // result garbled, so disable the code and try again.
373*a3141fd3SAndroid Build Coastguard Worker                 // e.g. "16610001234" must equal to "6610001234", but with
374*a3141fd3SAndroid Build Coastguard Worker                 //      Thailand-case handling code, they become equal to each other.
375*a3141fd3SAndroid Build Coastguard Worker                 //
376*a3141fd3SAndroid Build Coastguard Worker                 // Note: we select simplicity rather than adding some complicated
377*a3141fd3SAndroid Build Coastguard Worker                 //       logic here for performance(like "checking whether remaining
378*a3141fd3SAndroid Build Coastguard Worker                 //       numbers are just 66 or not"), assuming inputs are small
379*a3141fd3SAndroid Build Coastguard Worker                 //       enough.
380*a3141fd3SAndroid Build Coastguard Worker                 return phone_number_compare_inter(org_a, org_b, false);
381*a3141fd3SAndroid Build Coastguard Worker             } else {
382*a3141fd3SAndroid Build Coastguard Worker                 return false;
383*a3141fd3SAndroid Build Coastguard Worker             }
384*a3141fd3SAndroid Build Coastguard Worker         } else if (trunk_prefix_ignorable_a && trunk_prefix_is_omitted_b) {
385*a3141fd3SAndroid Build Coastguard Worker             bool cmp_prefixes = i_a == 0 && isDialable(a[i_a]);
386*a3141fd3SAndroid Build Coastguard Worker             if (cmp_prefixes && org_b[i_a] != a[i_a]) {
387*a3141fd3SAndroid Build Coastguard Worker                 // Unmatched trunk prefix
388*a3141fd3SAndroid Build Coastguard Worker                 return false;
389*a3141fd3SAndroid Build Coastguard Worker             }
390*a3141fd3SAndroid Build Coastguard Worker         }
391*a3141fd3SAndroid Build Coastguard Worker 
392*a3141fd3SAndroid Build Coastguard Worker         bool trunk_prefix_ignorable_b = checkPrefixIsIgnorable(b, i_b);
393*a3141fd3SAndroid Build Coastguard Worker         if ((trunk_prefix_is_omitted_b && i_b >= 0) || !trunk_prefix_ignorable_b) {
394*a3141fd3SAndroid Build Coastguard Worker             if (accept_thailand_case) {
395*a3141fd3SAndroid Build Coastguard Worker                 return phone_number_compare_inter(org_a, org_b, false);
396*a3141fd3SAndroid Build Coastguard Worker             } else {
397*a3141fd3SAndroid Build Coastguard Worker                 return false;
398*a3141fd3SAndroid Build Coastguard Worker             }
399*a3141fd3SAndroid Build Coastguard Worker         } else if (trunk_prefix_ignorable_b && trunk_prefix_is_omitted_a) {
400*a3141fd3SAndroid Build Coastguard Worker             bool cmp_prefixes = i_b == 0 && isDialable(b[i_b]);
401*a3141fd3SAndroid Build Coastguard Worker             if (cmp_prefixes && org_a[i_b] != b[i_b]) {
402*a3141fd3SAndroid Build Coastguard Worker                 // Unmatched trunk prefix
403*a3141fd3SAndroid Build Coastguard Worker                 return false;
404*a3141fd3SAndroid Build Coastguard Worker             }
405*a3141fd3SAndroid Build Coastguard Worker         }
406*a3141fd3SAndroid Build Coastguard Worker     } else {
407*a3141fd3SAndroid Build Coastguard Worker         // In the US, 1-650-555-1234 must be equal to 650-555-1234,
408*a3141fd3SAndroid Build Coastguard Worker         // while 090-1234-1234 must not be equal to 90-1234-1234 in Japan.
409*a3141fd3SAndroid Build Coastguard Worker         // This request exists just in US (with 1 trunk (NDD) prefix).
410*a3141fd3SAndroid Build Coastguard Worker         // In addition, "011 11 7005554141" must not equal to "+17005554141",
411*a3141fd3SAndroid Build Coastguard Worker         // while "011 1 7005554141" must equal to "+17005554141"
412*a3141fd3SAndroid Build Coastguard Worker         //
413*a3141fd3SAndroid Build Coastguard Worker         // In this comparison, we ignore the prefix '1' just once, when
414*a3141fd3SAndroid Build Coastguard Worker         // - at least either does not have CCC, or
415*a3141fd3SAndroid Build Coastguard Worker         // - the remaining non-separator number is 1
416*a3141fd3SAndroid Build Coastguard Worker         bool may_be_namp = !both_have_ccc;
417*a3141fd3SAndroid Build Coastguard Worker         while (i_a >= 0) {
418*a3141fd3SAndroid Build Coastguard Worker             const char ch_a = a[i_a];
419*a3141fd3SAndroid Build Coastguard Worker             if (isDialable(ch_a)) {
420*a3141fd3SAndroid Build Coastguard Worker                 if (may_be_namp && tryGetISODigit(ch_a) == 1) {
421*a3141fd3SAndroid Build Coastguard Worker                     may_be_namp = false;
422*a3141fd3SAndroid Build Coastguard Worker                 } else {
423*a3141fd3SAndroid Build Coastguard Worker                     return false;
424*a3141fd3SAndroid Build Coastguard Worker                 }
425*a3141fd3SAndroid Build Coastguard Worker             }
426*a3141fd3SAndroid Build Coastguard Worker             i_a--;
427*a3141fd3SAndroid Build Coastguard Worker         }
428*a3141fd3SAndroid Build Coastguard Worker         while (i_b >= 0) {
429*a3141fd3SAndroid Build Coastguard Worker             const char ch_b = b[i_b];
430*a3141fd3SAndroid Build Coastguard Worker             if (isDialable(ch_b)) {
431*a3141fd3SAndroid Build Coastguard Worker                 if (may_be_namp && tryGetISODigit(ch_b) == 1) {
432*a3141fd3SAndroid Build Coastguard Worker                     may_be_namp = false;
433*a3141fd3SAndroid Build Coastguard Worker                 } else {
434*a3141fd3SAndroid Build Coastguard Worker                     return false;
435*a3141fd3SAndroid Build Coastguard Worker                 }
436*a3141fd3SAndroid Build Coastguard Worker             }
437*a3141fd3SAndroid Build Coastguard Worker             i_b--;
438*a3141fd3SAndroid Build Coastguard Worker         }
439*a3141fd3SAndroid Build Coastguard Worker     }
440*a3141fd3SAndroid Build Coastguard Worker 
441*a3141fd3SAndroid Build Coastguard Worker     return true;
442*a3141fd3SAndroid Build Coastguard Worker }
443*a3141fd3SAndroid Build Coastguard Worker 
phone_number_compare_strict(const char * a,const char * b)444*a3141fd3SAndroid Build Coastguard Worker bool phone_number_compare_strict(const char* a, const char* b)
445*a3141fd3SAndroid Build Coastguard Worker {
446*a3141fd3SAndroid Build Coastguard Worker     return phone_number_compare_inter(a, b, true);
447*a3141fd3SAndroid Build Coastguard Worker }
448*a3141fd3SAndroid Build Coastguard Worker 
449*a3141fd3SAndroid Build Coastguard Worker /**
450*a3141fd3SAndroid Build Coastguard Worker  * Imitates the Java method PhoneNumberUtils.getStrippedReversed.
451*a3141fd3SAndroid Build Coastguard Worker  * Used for API compatibility with Android 1.6 and earlier.
452*a3141fd3SAndroid Build Coastguard Worker  */
phone_number_stripped_reversed_inter(const char * in,char * out,const int len,int * outlen)453*a3141fd3SAndroid Build Coastguard Worker bool phone_number_stripped_reversed_inter(const char* in, char* out, const int len, int *outlen) {
454*a3141fd3SAndroid Build Coastguard Worker     int in_len = strlen(in);
455*a3141fd3SAndroid Build Coastguard Worker     int out_len = 0;
456*a3141fd3SAndroid Build Coastguard Worker     bool have_seen_plus = false;
457*a3141fd3SAndroid Build Coastguard Worker     for (int i = in_len; --i >= 0;) {
458*a3141fd3SAndroid Build Coastguard Worker         char c = in[i];
459*a3141fd3SAndroid Build Coastguard Worker         if ((c >= '0' && c <= '9') || c == '*' || c == '#' || c == 'N') {
460*a3141fd3SAndroid Build Coastguard Worker             if (out_len < len) {
461*a3141fd3SAndroid Build Coastguard Worker                 out[out_len++] = c;
462*a3141fd3SAndroid Build Coastguard Worker             }
463*a3141fd3SAndroid Build Coastguard Worker         } else {
464*a3141fd3SAndroid Build Coastguard Worker             switch (c) {
465*a3141fd3SAndroid Build Coastguard Worker               case '+':
466*a3141fd3SAndroid Build Coastguard Worker                   if (!have_seen_plus) {
467*a3141fd3SAndroid Build Coastguard Worker                       if (out_len < len) {
468*a3141fd3SAndroid Build Coastguard Worker                           out[out_len++] = c;
469*a3141fd3SAndroid Build Coastguard Worker                       }
470*a3141fd3SAndroid Build Coastguard Worker                       have_seen_plus = true;
471*a3141fd3SAndroid Build Coastguard Worker                   }
472*a3141fd3SAndroid Build Coastguard Worker                   break;
473*a3141fd3SAndroid Build Coastguard Worker               case ',':
474*a3141fd3SAndroid Build Coastguard Worker               case ';':
475*a3141fd3SAndroid Build Coastguard Worker                   out_len = 0;
476*a3141fd3SAndroid Build Coastguard Worker                   break;
477*a3141fd3SAndroid Build Coastguard Worker           }
478*a3141fd3SAndroid Build Coastguard Worker         }
479*a3141fd3SAndroid Build Coastguard Worker     }
480*a3141fd3SAndroid Build Coastguard Worker 
481*a3141fd3SAndroid Build Coastguard Worker     *outlen = out_len;
482*a3141fd3SAndroid Build Coastguard Worker     return true;
483*a3141fd3SAndroid Build Coastguard Worker }
484*a3141fd3SAndroid Build Coastguard Worker 
485*a3141fd3SAndroid Build Coastguard Worker }  // namespace android
486