Впервые довелось столкнуться с библиотекой libconfig. Довольно таки популярной, насколько я могу судить. Тем удивительнее было обнаружить там описанный ниже косяк.
Чтобы получить значение целочисленного параметра нужно использовать функцию config_setting_get_int:
int config_setting_get_int (const config_setting_t * setting)
long long config_setting_get_int64 (const config_setting_t * setting)These functions return the value of the given setting. If the type of the setting does not match the type requested, a 0 value is returned.
Т.е. если мы пытаемся получить значение параметра, а нам возвращают 0, то этот ноль может означать:
- что значение не получено, т.к. оно имеет другой тип. Например, вместо my_param=0 задано my_param="0" или my_param="zero";
- что значение получено и это таки ноль. Просто ноль.
Получается, что если для нашего параметра ноль -- это допустимое значение, то получив ноль из config_setting_get_int мы не знаем, ноль -- это ноль, или же это признак неправильного значения в конфиге.
Аналогичная проблема есть и с семейством функций config_lookup_int/config_lookup_int64 и прочих вариантов lookup-чего-то-там. Эти функции возвращают CONFIG_FALSE и в случае, если параметр вообще не был найдет, и в случае, если был найден, но содержит не тот тип (например, строка вместо числа).
При этом, насколько я могу судить по коду libconfig, в случае несовпадения типа для значения libconfig даже errno не меняет.
Т.е. получив 0 из config_setting_get_int или CONFIG_FALSE из config_lookup_int у меня нет возможности разобраться с тем есть ли ошибка и, если есть, какая она.
Хотя, как по мне, избежать этой проблемы можно было бы очень просто, если бы у config_setting_get_int был другой формат:
int config_setting_get_int(
// Где искать значение.
const config_setting_t * setting,
// Куда помещать значение.
int * value_receiver)
И возвращаемое значение означало бы признак успешности, вроде такого: 0 -- все OK, -1 -- значение имеет другой тип, -2 -- значение слишком большое, чтобы уместиться в int и т.д.
Очевидная, вроде бы, вещь. Но почему-то не сделанная... 🙁
2 комментария:
Я с libconfig незнаком, но подозреваю, что стоит поискать также функцию bool config_setting_has_int(...). Обычно 'has' и 'get' идут в паре.
Оказалось, что там есть config_setting_type, которая возвращает значения типа CONFIG_TYPE_INT, CONFIG_TYPE_INT64, CONFIG_TYPE_FLOAT, CONFIG_TYPE_STRING, ...
Т.е. возможность проверить что к чему есть. Но как-то через ж сделанная.
Отправить комментарий