diff options
Diffstat (limited to 'libcontacts_same_number.c')
-rw-r--r-- | libcontacts_same_number.c | 92 |
1 files changed, 63 insertions, 29 deletions
diff --git a/libcontacts_same_number.c b/libcontacts_same_number.c index 633fc7e..cfdcc7c 100644 --- a/libcontacts_same_number.c +++ b/libcontacts_same_number.c @@ -19,12 +19,14 @@ static const char *digits[255] = { }; static char * -canonicalise(const char *number, const char *country) +canonicalise(const char *number, const char *country, char **post_cccp) { size_t nlen = 0, clen = 0, skip; const char *digit, *p; char *ret, *r; + *post_cccp = NULL; + for (p = number, skip = 0; *p; p++) { digit = digits[*p & 255]; if (digit) { @@ -49,32 +51,35 @@ canonicalise(const char *number, const char *country) } } - ret = malloc(nlen + clen + 3); + r = ret = malloc(nlen + clen + 3); if (!ret) return NULL; - for (r = ret, p = number, skip = 0; *p; p++) { - digit = digits[*p & 255]; - if (digit) { - if (*digit == '(') { - skip += 1; - } else if (*digit == ')') { - skip -= !!skip; - } else if (!skip) { - *r++ = digit[0]; - if (digit[1]) - *r++ = digit[1]; + if (clen) { + for (p = country, skip = 0; *p; p++) { + digit = digits[*p & 255]; + if (digit) { + if (*digit == '(') { + skip += 1; + } else if (*digit == ')') { + skip -= !!skip; + } else if (!skip) { + *r++ = digit[0]; + if (digit[1]) + *r++ = digit[1]; + } } } + if (clen < 2 || ret[0] != '0' || ret[1] != '0') { + memmove(&ret[2], ret, clen); + ret[0] = ret[1] = '0'; + clen += 2; + r += 2; + } + *post_cccp = r; } - *r = '\0'; - if (ret[0] != '0' || ret[1] == '0' || !*country) - return ret; - - memmove(&ret[clen], &ret[1], nlen); - - for (r = ret, p = country, skip = 0; *p; p++) { + for (p = number, skip = 0; *p; p++) { digit = digits[*p & 255]; if (digit) { if (*digit == '(') { @@ -88,35 +93,64 @@ canonicalise(const char *number, const char *country) } } } + *r = '\0'; + + if (r[clen] != '0') { + *post_cccp = NULL; + memmove(ret, &ret[clen], nlen + 1); + } else { + memmove(&ret[clen], &ret[clen + 1], nlen--); + if (nlen >= 2 && ret[clen + 1] == '0') { + if (nlen < clen || memcmp(&ret[0], &ret[clen], clen)) + *post_cccp = NULL; + memmove(ret, &ret[clen], nlen + 1); + } + } - if (ret[0] == '0' && ret[1] == '0') - return ret; + if (ret[0] == '0' && ret[1] != '0') + *post_cccp = &ret[1]; - memmove(&ret[2], ret, nlen + clen); - ret[0] = ret[1] = '0'; return ret; } int libcontacts_same_number(const char *a, const char *a_country, const char *b, const char *b_country) { - char *a_full, *b_full; - int ret; + char *a_full, *b_full, *a_post_ccc, *b_post_ccc; + int ret, a_has_ccc, b_has_ccc; if (!a || !*a || !b || !*b) { errno = EINVAL; return -1; } - a_full = canonicalise(a, a_country ? a_country : ""); + if (!a_country) + a_country = ""; + if (!b_country) + b_country = ""; + + a_full = canonicalise(a, a_country, &a_post_ccc); if (!a_full) return -1; - b_full = canonicalise(b, b_country ? b_country : ""); + b_full = canonicalise(b, b_country, &b_post_ccc); if (!b_full) { free(a_full); return -1; } - ret = !strcmp(a_full, b_full); + + a_has_ccc = (a_full[0] == '0' && a_full[1] == '0'); + b_has_ccc = (b_full[0] == '0' && b_full[1] == '0'); + + a = a_full; + b = b_full; + if (a_has_ccc != b_has_ccc) { + if (a_post_ccc && b_post_ccc) { + a = a_post_ccc; + b = b_post_ccc; + } + } + + ret = !strcmp(a, b); free(a_full); free(b_full); return ret; |