in libvmaf/src/dict.c [27:107]
int vmaf_dictionary_set(VmafDictionary **dict, const char *key, const char *val,
uint64_t flags)
{
if (!dict) return -EINVAL;
if (!key) return -EINVAL;
if (!val) return -EINVAL;
VmafDictionary *d = *dict;
if (!d) {
d = *dict = malloc(sizeof(*d));
if (!d) goto fail;
memset(d, 0, sizeof(*d));
const size_t initial_sz = 8 * sizeof(*d->entry);
d->entry = malloc(initial_sz);
if (!d->entry) {
free(d);
*dict = NULL;
goto fail;
}
memset(d->entry, 0, initial_sz);
d->size = 8;
}
char *buf = NULL;
if (flags & VMAF_DICT_NORMALIZE_NUMERICAL_VALUES) {
char *end = NULL;
double d = strtof(val, &end);
if (!(d == 0 && val == end)) {
const char *fmt = "%g";
const size_t buf_sz = snprintf(NULL, 0, fmt, d) + 1;
buf = malloc(buf_sz);
if (!buf) return -ENOMEM;
snprintf(buf, buf_sz, fmt, d);
}
}
val = buf ? buf : val;
VmafDictionaryEntry *existing_entry = vmaf_dictionary_get(&d, key, 0);
if (existing_entry && (flags & VMAF_DICT_DO_NOT_OVERWRITE)) {
int ret = !strcmp(existing_entry->val, val) ? 0 : -EINVAL;
free(buf);
return ret;
}
if (d->cnt == d->size) {
const size_t sz = d->size * sizeof(*d->entry) * 2;
VmafDictionaryEntry *entry = realloc(d->entry, sz);
if (!entry) goto fail;
d->entry = entry;
d->size *= 2;
}
const char *val_copy = strdup(val);
if (!val_copy) goto fail;
free(buf);
if (existing_entry && !(flags & VMAF_DICT_DO_NOT_OVERWRITE)) {
free((char*)existing_entry->val);
existing_entry->val = val_copy;
return 0;
}
const char *key_copy = strdup(key);
if (!key_copy) goto free_val_copy;
VmafDictionaryEntry entry = {
.key = key_copy,
.val = val_copy,
};
d->entry[d->cnt++] = entry;
return 0;
free_val_copy:
free((char*)val_copy);
fail:
return -ENOMEM;
}