add gsm0808_cell_{id,id_list}_name() and friends

Provide comprehensive API to obtain string representations of Cell Identifiers
and -Lists.

Change gsm0808_test.c to use the new functions (which simplifies the output a
bit), so that we don't duplicate printing code in gsm0808_test.c, and so that
the not-so-trivial printing code is also tested.

In gsm0808_test, also test gsm0808_cell_id_list_name_buf()'s return value and
truncation behavior.

The rationale for gsm0808_cell_id_list_name(), i.e. printing an entire list of
cell identifiers, is that even though the maximum is 127 elements, a list of
more than a few elements is hardly ever expected in practice (even more than
one element isn't actually expected: either "entire BSS" or a single LAC). It
is thus useful to log the entire list when it shows up in Paging and Handover.

Change-Id: I9b2106805422f96c5cc96ebb9178451355582df3
diff --git a/tests/gsm0808/gsm0808_test.c b/tests/gsm0808/gsm0808_test.c
index 49673fe..78238ff 100644
--- a/tests/gsm0808/gsm0808_test.c
+++ b/tests/gsm0808/gsm0808_test.c
@@ -1073,36 +1073,12 @@
 
 static void print_cil(const struct gsm0808_cell_id_list2 *cil)
 {
-	unsigned int i;
-	if (!cil) {
-		printf("     cell_id_list == NULL\n");
-		return;
-	}
-	switch (cil->id_discr) {
-	case CELL_IDENT_WHOLE_GLOBAL:
-		printf("     cell_id_list cgi[%u] = {\n", cil->id_list_len);
-		for (i = 0; i < cil->id_list_len; i++)
-			printf("       %2d: %s\n", i, osmo_cgi_name(&cil->id_list[i].global));
-		printf("     }\n");
-		break;
-	case CELL_IDENT_LAC:
-		printf("     cell_id_list lac[%u] = {\n", cil->id_list_len);
-		for (i = 0; i < cil->id_list_len; i++)
-			printf("      %2d: %u\n", i, cil->id_list[i].lac);
-		printf("     }\n");
-		break;
-	case CELL_IDENT_BSS:
-		printf("     cell_id_list bss[%u]\n", cil->id_list_len);
-		break;
-	case CELL_IDENT_NO_CELL:
-		printf("     cell_id_list no_cell[%u]\n", cil->id_list_len);
-		break;
-	default:
-		printf("     Unimplemented id_disc\n");
-	}
+	printf("     cell_id_list == %s\n", gsm0808_cell_id_list_name(cil));
 }
 
 void test_cell_id_list_add() {
+	size_t zu;
+
 	const struct gsm0808_cell_id_list2 cgi1 = {
 		.id_discr = CELL_IDENT_WHOLE_GLOBAL,
 		.id_list_len = 1,
@@ -1220,7 +1196,7 @@
 
 #define ADD_QUIET(other_cil, expect_rc) do { \
 		int rc = gsm0808_cell_id_list_add(&cil, &other_cil); \
-		printf("\ngsm0808_cell_id_list_add(&cil, &" #other_cil ") --> rc = %d\n", rc); \
+		printf("gsm0808_cell_id_list_add(&cil, &" #other_cil ") --> rc = %d\n", rc); \
 		OSMO_ASSERT(rc == expect_rc); \
 	} while(0)
 
@@ -1233,13 +1209,13 @@
 	ADD(cil, 0);
 	ADD(cgi1, -EINVAL);
 
-	printf("\ncan't add to BSS list\n");
+	printf("* can't add to BSS list\n");
 	cil.id_list_len = 0;
 	cil.id_discr = CELL_IDENT_BSS;
 	print_cil(&cil);
 	ADD(lac1, -EINVAL);
 
-	printf("\nother types (including NO_CELL) take on new type iff empty\n");
+	printf("* other types (including NO_CELL) take on new type iff empty\n");
 	cil.id_list_len = 0;
 	cil.id_discr = CELL_IDENT_NO_CELL;
 	print_cil(&cil);
@@ -1248,15 +1224,34 @@
 	ADD(cgi2, 2);
 	ADD(cgi2, 0);
 
+	printf("* test gsm0808_cell_id_list_name_buf()'s return val\n");
+	zu = strlen(gsm0808_cell_id_list_name(&cil));
+	printf("  strlen(gsm0808_cell_id_list_name(cil)) == %zu\n", zu);
+	zu ++;
+	while (1) {
+		char buf[128] = "?";
+		int rc;
+		OSMO_ASSERT(zu < sizeof(buf));
+		buf[zu] = '#';
+		rc = gsm0808_cell_id_list_name_buf(buf, zu, &cil);
+		printf("  gsm0808_cell_id_list_name_buf(buf, %zu, cil)) == %d \"%s\"\n",
+		       zu, rc, buf);
+		OSMO_ASSERT(buf[zu] == '#');
+		if (!zu)
+			break;
+		zu /= 2;
+	}
+
+	printf("* list-full behavior\n");
 	cil.id_list_len = GSM0808_CELL_ID_LIST2_MAXLEN - 1;
-	printf("\ncil.id_list_len = %u", cil.id_list_len);
+	printf("cil.id_list_len = %u\n", cil.id_list_len);
 	ADD_QUIET(cgi2a, 1);
 	printf("cil.id_list_len = %u\n", cil.id_list_len);
 
 	cil.id_list_len = GSM0808_CELL_ID_LIST2_MAXLEN - 1;
-	printf("\ncil.id_list_len = %u", cil.id_list_len);
+	printf("cil.id_list_len = %u\n", cil.id_list_len);
 	ADD_QUIET(cgi3, -ENOSPC);
-	printf("cil.id_list_len = %u", cil.id_list_len);
+	printf("cil.id_list_len = %u\n", cil.id_list_len);
 	ADD_QUIET(cgi2a, -ENOSPC);
 	printf("cil.id_list_len = %u\n", cil.id_list_len);