/**
 * @file set.c
 * @author Radek Krejci <rkrejci@cesnet.cz>
 * @brief Generic set routines implementations
 *
 * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
 *
 * This source code is licensed under BSD 3-Clause License (the "License").
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://opensource.org/licenses/BSD-3-Clause
 */

#include "common.h"

#include <stdlib.h>
#include <string.h>

#include "log.h"
#include "set.h"

API struct ly_set *
ly_set_new(void)
{
    struct ly_set *new;

    new = calloc(1, sizeof(struct ly_set));
    LY_CHECK_ERR_RET(!new, LOGMEM(NULL), NULL);
    return new;
}

API void
ly_set_clean(struct ly_set *set, void (*destructor)(void *obj))
{
    unsigned int u;

    if (!set) {
        return;
    }

    if (destructor) {
        for (u = 0; u < set->count; ++u) {
            destructor(set->objs[u]);
        }
    }
    set->count = 0;
}

API void
ly_set_erase(struct ly_set *set, void (*destructor)(void *obj))
{
    if (!set) {
        return;
    }

    ly_set_clean(set, destructor);

    free(set->objs);
    set->size = 0;
    set->objs = NULL;
}

API void
ly_set_free(struct ly_set *set, void (*destructor)(void *obj))
{
    if (!set) {
        return;
    }

    ly_set_erase(set, destructor);

    free(set);
}

API int
ly_set_contains(const struct ly_set *set, void *object)
{
    unsigned int i;

    LY_CHECK_ARG_RET(NULL, set, -1);

    for (i = 0; i < set->count; i++) {
        if (set->objs[i] == object) {
            /* object found */
            return i;
        }
    }

    /* object not found */
    return -1;
}

API struct ly_set *
ly_set_dup(const struct ly_set *set, void *(*duplicator)(void *obj))
{
    struct ly_set *new;
    unsigned int u;

    LY_CHECK_ARG_RET(NULL, set, NULL);

    new = malloc(sizeof *new);
    LY_CHECK_ERR_RET(!new, LOGMEM(NULL), NULL);
    new->count = set->count;
    new->size = set->size;
    new->objs = malloc(new->size * sizeof *(new->objs));
    LY_CHECK_ERR_RET(!new->objs, LOGMEM(NULL); free(new), NULL);
    if (duplicator) {
        for (u = 0; u < set->count; ++u) {
            new->objs[u] = duplicator(set->objs[u]);
        }
    } else {
        memcpy(new->objs, set->objs, new->size * sizeof *(new->objs));
    }

    return new;
}

API int
ly_set_add(struct ly_set *set, void *object, int options)
{
    unsigned int i;
    void **new;

    LY_CHECK_ARG_RET(NULL, set, object, -1);

    if (!(options & LY_SET_OPT_USEASLIST)) {
        /* search for duplication */
        for (i = 0; i < set->count; i++) {
            if (set->objs[i] == object) {
                /* already in set */
                return i;
            }
        }
    }

    if (set->size == set->count) {
        new = realloc(set->objs, (set->size + 8) * sizeof *(set->objs));
        LY_CHECK_ERR_RET(!new, LOGMEM(NULL), -1);
        set->size += 8;
        set->objs = new;
    }

    set->objs[set->count++] = object;

    return set->count - 1;
}

API int
ly_set_merge(struct ly_set *trg, struct ly_set *src, int options, void *(*duplicator)(void *obj))
{
    unsigned int u, c, ret = 0;
    int i;
    void *obj;

    LY_CHECK_ARG_RET(NULL, trg, -1);
    LY_CHECK_ARG_RET(NULL, src, 0);

    for (u = 0; u < src->count; ++u) {
        if (duplicator) {
            obj = duplicator(src->objs[u]);
        } else {
            obj = src->objs[u];
        }
        c = trg->count;
        i = ly_set_add(trg, obj, options);
        if (i > 0 && (unsigned int)i == c) {
            ++ret;
        }
    }

    return ret;
}

API LY_ERR
ly_set_rm_index(struct ly_set *set, unsigned int index, void (*destructor)(void *obj))
{
    LY_CHECK_ARG_RET(NULL, set, LY_EINVAL);
    LY_CHECK_ERR_RET(index >= set->count, LOGARG(NULL, index), LY_EINVAL);

    if (destructor) {
        destructor(set->objs[index]);
    }
    if (index == set->count - 1) {
        /* removing last item in set */
        set->objs[index] = NULL;
    } else {
        /* removing item somewhere in a middle, so put there the last item */
        set->objs[index] = set->objs[set->count - 1];
        set->objs[set->count - 1] = NULL;
    }
    set->count--;

    return LY_SUCCESS;
}

API LY_ERR
ly_set_rm(struct ly_set *set, void *object, void (*destructor)(void *obj))
{
    unsigned int i;

    LY_CHECK_ARG_RET(NULL, set, object, LY_EINVAL);

    /* get index */
    for (i = 0; i < set->count; i++) {
        if (set->objs[i] == object) {
            break;
        }
    }
    LY_CHECK_ERR_RET((i == set->count), LOGARG(NULL, object), LY_EINVAL); /* object is not in set */

    return ly_set_rm_index(set, i, destructor);
}

