Замена многих вызовов функции на более элегантное решение (цикл)
Допустим у меня есть функция для парсинга Url, и для того что бы распарсить каждую часть, а так же помимо этого добавить флаг присутствия той или иной части, вызывается одна функция, в которую передается enum (флаги), и на данный момент это выглядит примерно так:
enum libkodik_url_flag_e {
libkodik_url_flag_scheme = 1u << 0u,
libkodik_url_flag_user = 1u << 1u,
libkodik_url_flag_password = 1u << 2u,
libkodik_url_flag_host = 1u << 3u,
libkodik_url_flag_port = 1u << 4u,
libkodik_url_flag_path = 1u << 5u,
libkodik_url_flag_query = 1u << 6u,
libkodik_url_flag_fragment = 1u << 7u,
libkodik_url_flag_max = 1u << 8u
};
KODIK_CORE_API libkodik_url_t *
libkodik_url_parse(char const *url, int *error) {
libkodik_url_t* p_data = NULL;
...
uint32_t i_parts_count = 0;
p_data = libkodik_url_alloc();
p_data->psz_raw = strdup(url);
char *psz_part = libkodik_url_parse_part(url, libkodik_url_flag_scheme);
if(NULL != psz_part) {
i_parts_count++;
p_data->i_flags |= libkodik_url_flag_scheme;
p_data->p_url_parts = realloc(p_data->p_url_parts,
i_parts_count * sizeof(libkodik_url_part_t));
libkodik_url_write_part(&p_data->p_url_parts[i_parts_count],
psz_part, libkodik_url_flag_scheme);
...
} else {
psz_part = url;
}
...
*error = 0;
return p_data;
}
Но я хотел бы сделать это дело циклом, т.е. данные там устанавливаются одинаково, но я не понимаю как мне перебрать enum в цикле, т.к. он является значением флагов...
Повторяющаяся часть кода:
char *psz_part = libkodik_url_parse_part(url, libkodik_url_flag_scheme);
if(NULL != psz_part) {
i_parts_count++;
p_data->i_flags |= libkodik_url_flag_scheme;
p_data->p_url_parts = realloc(p_data->p_url_parts,
i_parts_count * sizeof(libkodik_url_part_t));
libkodik_url_write_part(&p_data->p_url_parts[i_parts_count],
psz_part, libkodik_url_flag_scheme);
...
} else {
psz_part = url;
}
P.S. libkodik_url_flag_max не учитывается.
Ответы (1 шт):
Так как флаги у вас идут подряд, можно перебирать циклом просто сдвигая нужный бит. Флаг libkodik_url_flag_scheme = 1u << 0u имеет значение 000000001b. А флаг libkodik_url_flag_user = 1u << 1u равен 000000010b. И наконец последний libkodik_url_flag_max = 1u << 8u равен 100000000b.
Перебираем циклом начиная с первого флага до последнего так :
enum libkodik_url_flag_e flag ;
for ( flag = libkodik_url_flag_scheme ;
flag != libkodik_url_flag_max ; flag <<= 1 )
/* нужная работа со значением флага flag */;
На следующий флаг переходим с помощью битового сдвига <<= 1. И если был флаг flag = 000010000b. То с помощью flag <<= 1 он станет равным 000100000b.