int vmaf_dictionary_set()

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;
}