What?
I have an algorithm that parses comma separated lists of unsigned 32-bit ints from strings. Here is an example of what a list could look like:
1302,51,2312,2,52
The algorithm uses a custom data structure called parse_input
which is a data structure that is a FIFO of numbers. This structure is passed to another unrelated function that parses some data with the help of this list of numbers. parse_input_push
is used to add a number to the queue.
The byte_array
structure used in the tests has a separate code review.
I would like feedback on everything. Even the tests!
Files
Source
#define MAX_NUM_GLYPHS 11
static bool number_len_ok(const char *literal_num, size_t curr_num_len)
{
if (curr_num_len != MAX_NUM_GLYPHS - 1) return true;
size_t i = 0;
char *max_literal_num = "4294967296";
for (; i < curr_num_len; i++) {
if (literal_num[i] > max_literal_num[i]) return false;
}
return true;
}
int parse_num_list(struct parse_input *lookup, char *num_list)
{
size_t i = 0;
size_t curr_num_len = 0;
size_t list_len = strlen(num_list);
char literals[MAX_NUM_GLYPHS] = {0};
char curr_glyph;
bool prev_was_comma = false;
for (; i < list_len; i++) {
if (curr_num_len >= MAX_NUM_GLYPHS) return -1;
curr_glyph = num_list[i];
if (curr_glyph == ',') {
if (prev_was_comma) return -2;
if (!number_len_ok(literals, curr_num_len)) return -1;
parse_input_push(lookup, atoi(literals));
memset(literals, '\0', 10);
curr_num_len = 0;
prev_was_comma = true;
continue;
}
if (curr_glyph < '0' || curr_glyph > '9') return -2;
prev_was_comma = false;
literals[curr_num_len++] = curr_glyph;
}
if (!number_len_ok(literals, curr_num_len)) return -1;
parse_input_push(lookup, atoi(literals));
return 0;
}
Tests
void test_ok_parse_num_list()
{
char num_list[] = "124,1231231,2,20202,4294967296,1";
struct byte_array *lookup_name = byte_array_from_cstring("chr1");
struct parse_input *lookup = parse_input_create(lookup_name);
int ret = parse_num_list(lookup, num_list);
byte_array_decref(lookup_name);
parse_input_decref(lookup);
assert(ret == 0);
printf("[ OK ] Parse num list\n");
}
void test_too_big_parse_num_list()
{
char num_list[] = "124,1231231,2,20202,42949672952,1";
char num_list2[] = "124,1231231,2,20202,9999999999,666";
char num_list3[] = "124,1231231,2,20202,4294967297,1";
struct byte_array *lookup_name = byte_array_from_cstring("chr1");
struct parse_input *lookup = parse_input_create(lookup_name);
int ret = parse_num_list(lookup, num_list);
assert(ret == -1);
ret = parse_num_list(lookup, num_list2);
assert(ret == -1);
ret = parse_num_list(lookup, num_list3);
assert(ret == -1);
byte_array_decref(lookup_name);
parse_input_decref(lookup);
printf("[ OK ] Parse too big num list\n");
}
void test_invalid_parse_num_list()
{
char num_list[] = "124,1231231.,2,20202,429496,1";
char num_list2[] = "124,1231231,2,20202,99999999ö,666";
char num_list3[] = "124,1231231,2,20202,4294967,1,,,,";
struct byte_array *lookup_name = byte_array_from_cstring("chr1");
struct parse_input *lookup = parse_input_create(lookup_name);
int ret = parse_num_list(lookup, num_list);
assert(ret == -2);
ret = parse_num_list(lookup, num_list2);
assert(ret == -2);
ret = parse_num_list(lookup, num_list3);
assert(ret == -2);
byte_array_decref(lookup_name);
parse_input_decref(lookup);
printf("[ OK ] Parse invalid num list\n");
}