aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2019-03-05 22:41:31 +0100
committerNeels Hofmeyr <neels@hofmeyr.de>2019-04-10 18:06:08 +0200
commit56b8a9327f2829a11115c1f9aae2084e86352484 (patch)
tree5bc4045182fc1938496f2bf0c5dfcdcb936bf96f
parentd08e9866a5c3da6edda574bbe6d277047d10fded (diff)
-rw-r--r--include/osmocom/gsm/gsm0808_utils.h1
-rw-r--r--src/gsm/gsm0808_utils.c118
-rw-r--r--tests/gsm0808/gsm0808_test.c7
3 files changed, 96 insertions, 30 deletions
diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h
index e246967..de99b8e 100644
--- a/include/osmocom/gsm/gsm0808_utils.h
+++ b/include/osmocom/gsm/gsm0808_utils.h
@@ -125,6 +125,7 @@ int gsm0808_dec_cell_id_list(struct gsm0808_cell_id_list *cil,
const uint8_t *elem, uint8_t len)
OSMO_DEPRECATED("use gsm0808_dec_cell_id_list2 instead");
int gsm0808_cell_id_list_add(struct gsm0808_cell_id_list2 *dst, const struct gsm0808_cell_id_list2 *src);
+int gsm0808_cell_id_list_del(struct gsm0808_cell_id_list2 *dst, const struct gsm0808_cell_id_list2 *src);
void gsm0808_cell_id_to_list(struct gsm0808_cell_id_list2 *dst, const struct gsm0808_cell_id *src);
uint8_t gsm0808_enc_cell_id(struct msgb *msg, const struct gsm0808_cell_id *ci);
int gsm0808_dec_cell_id(struct gsm0808_cell_id *ci, const uint8_t *elem, uint8_t len);
diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c
index 52e4674..e4a9e7a 100644
--- a/src/gsm/gsm0808_utils.c
+++ b/src/gsm/gsm0808_utils.c
@@ -1069,41 +1069,53 @@ int gsm0808_dec_cell_id_list(struct gsm0808_cell_id_list *cil,
return (int)(elem - old_elem);
}
+static int osmo_gsm0808_cell_id_u_cmp(enum CELL_IDENT id_discr_a,
+ const union gsm0808_cell_id_u *a,
+ enum CELL_IDENT id_discr_b,
+ const union gsm0808_cell_id_u *b)
+{
+ if (id_discr_a < id_discr_b)
+ return -1;
+ if (id_discr_a > id_discr_b)
+ return 1;
+
+#define RETURN_CMP(name) \
+ if (a->name < b->name) \
+ return -1; \
+ if (a->name > b->name) \
+ return 1
+
+ switch (id_discr_a) {
+ case CELL_IDENT_WHOLE_GLOBAL:
+ return osmo_cgi_cmp(&a->global, &b->global);
+ case CELL_IDENT_LAC_AND_CI:
+ RETURN_CMP(lac_and_ci.lac);
+ RETURN_CMP(lac_and_ci.ci);
+ return 0;
+ case CELL_IDENT_CI:
+ RETURN_CMP(ci);
+ return 0;
+ case CELL_IDENT_LAI_AND_LAC:
+ return osmo_lai_cmp(&a->lai_and_lac, &b->lai_and_lac);
+ case CELL_IDENT_LAC:
+ RETURN_CMP(lac);
+ return 0;
+ case CELL_IDENT_BSS:
+ case CELL_IDENT_NO_CELL:
+ return 0;
+ default:
+ return -1;
+ }
+#undef RETURN_CMP
+}
+
static bool same_cell_id_list_entries(const struct gsm0808_cell_id_list2 *a, int ai,
const struct gsm0808_cell_id_list2 *b, int bi)
{
- struct gsm0808_cell_id_list2 tmp = {
- .id_discr = a->id_discr,
- .id_list_len = 1,
- };
- uint8_t buf_a[32 + sizeof(struct msgb)];
- uint8_t buf_b[32 + sizeof(struct msgb)];
- struct msgb *msg_a = (void*)buf_a;
- struct msgb *msg_b = (void*)buf_b;
-
- msg_a->data_len = 32;
- msg_b->data_len = 32;
- msgb_reset(msg_a);
- msgb_reset(msg_b);
-
- if (a->id_discr != b->id_discr)
- return false;
if (ai >= a->id_list_len
|| bi >= b->id_list_len)
return false;
-
- tmp.id_list[0] = a->id_list[ai];
- gsm0808_enc_cell_id_list2(msg_a, &tmp);
-
- tmp.id_list[0] = b->id_list[bi];
- gsm0808_enc_cell_id_list2(msg_b, &tmp);
-
- if (msg_a->len != msg_b->len)
- return false;
- if (memcmp(msg_a->data, msg_b->data, msg_a->len))
- return false;
-
- return true;
+ return osmo_gsm0808_cell_id_u_cmp(a->id_discr, &a->id_list[ai], b->id_discr, &b->id_list[bi]) == 0;
}
/*! Append entries from one Cell Identifier List to another.
@@ -1148,6 +1160,54 @@ int gsm0808_cell_id_list_add(struct gsm0808_cell_id_list2 *dst, const struct gsm
return added;
}
+static void _gsm0808_cell_id_list_del_idx(struct gsm0808_cell_id_list2 *dst, unsigned int idx)
+{
+ if (idx >= dst->id_list_len)
+ return;
+ if (dst->id_list_len > idx + 1)
+ memmove(&dst->id_list[idx], &dst->id_list[idx + 1],
+ sizeof(dst->id_list[0]) * (dst->id_list_len - (idx + 1)));
+ dst->id_list_len --;
+}
+
+int gsm0808_cell_id_list_del_cell(struct gsm0808_cell_id_list2 *dst, const struct gsm0808_cell_id *cid)
+{
+ int i;
+
+ if (dst->id_discr != cid->id_discr)
+ return 0;
+
+ for (i = 0; i < dst->id_list_len; i++) {
+ if (osmo_gsm0808_cell_id_u_cmp(cid->id_discr, &cid->id,
+ dst->id_discr, &dst->id_list[i])) {
+ _gsm0808_cell_id_list_del_idx(dst, i);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int gsm0808_cell_id_list_del(struct gsm0808_cell_id_list2 *dst, const struct gsm0808_cell_id_list2 *src)
+{
+ int i, j;
+ int removed = 0;
+
+ if (dst->id_discr != src->id_discr)
+ return 0;
+
+ for (i = 0; i < src->id_list_len; i++) {
+ for (j = 0; j < dst->id_list_len; j++) {
+ if (same_cell_id_list_entries(dst, j, src, i)) {
+ _gsm0808_cell_id_list_del_idx(dst, j);
+ removed++;
+ j--;
+ break;
+ }
+ }
+ }
+ return removed;
+}
+
/*! Convert a single Cell Identifier to a Cell Identifier List with one entry.
* \param dst[out] Overwrite this list.
* \param src[in] Set \a dst to contain exactly this item.
diff --git a/tests/gsm0808/gsm0808_test.c b/tests/gsm0808/gsm0808_test.c
index 8f1e299..43efad8 100644
--- a/tests/gsm0808/gsm0808_test.c
+++ b/tests/gsm0808/gsm0808_test.c
@@ -1467,7 +1467,12 @@ void test_cell_id_list_add() {
OSMO_ASSERT(rc == expect_rc); \
} while(0)
-#define ADD(other_cil, expect_rc) ADD_QUIET(other_cil, expect_rc); print_cil(&cil)
+#define ADD(other_cil, expect_rc) do { \
+ int rc = gsm0808_cell_id_list_add(&cil, &other_cil); \
+ printf("gsm0808_cell_id_list_add(&cil, &" #other_cil ") --> rc = %d\n", rc); \
+ print_cil(&cil); \
+ OSMO_ASSERT(rc == expect_rc); \
+ } while(0)
ADD(lac1, 1);
ADD(lac1, 0);