aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libcontacts_same_number.c92
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;