1/*
2 * Copyright 2016, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(D61_BSD)
11 */
12
13#include <stdio.h>
14#include <assert.h>
15#include <errno.h>
16#include <data_struct/coat.h>
17
18void coat_init(coat_t *t, int start, int end) {
19    assert(t);
20    assert(start != 0); /* zero idx is reserved. */
21    cpool_init(&t->pool, start, end);
22    cvector_init(&t->table);
23}
24
25void coat_release(coat_t *t) {
26    assert(t);
27    size_t count = cvector_count(&t->table);
28    for (int i = 0; i < count; i++) {
29        cvector_item_t obj = cvector_get(&t->table, i);
30        if (!obj) continue;
31        if (t->oat_delete) {
32            t->oat_delete(t, obj);
33        }
34    }
35    cvector_free(&t->table);
36    cpool_release(&t->pool);
37}
38
39int coat_alloc(coat_t *t, uint32_t arg[COAT_ARGS], cvector_item_t *out_obj) {
40    assert(t);
41
42    // Allocate new ID.
43    int id = cpool_alloc(&t->pool);
44    if (!id || id == COAT_INVALID_ID) {
45        goto error;
46    }
47
48    // Potentially expand ID table vector.
49    while (cvector_count(&t->table) <= id) {
50        if (t->oat_expand) {
51            t->oat_expand(&t->table);
52            continue;
53        }
54        // Defaults to adding NULL pointers to fill ID table.
55        cvector_add(&t->table, (cvector_item_t) NULL);
56    }
57
58    cvector_item_t obj = cvector_get(&t->table, id);
59    if (!obj && t->oat_create) {
60        // Create object structure and store it.
61        obj = t->oat_create(t, id, arg);
62        if (!obj) {
63            goto error;
64        }
65        cvector_set(&t->table, id, obj);
66    }
67
68    if (out_obj) {
69        (*out_obj) = obj;
70    }
71
72    return id;
73
74error:
75    if (id) cpool_free(&t->pool, id);
76    return COAT_INVALID_ID;
77}
78
79cvector_item_t coat_get(coat_t *t, int id) {
80    if (!t || id < t->pool.start || id >= t->pool.end || id >= cvector_count(&t->table)) {
81        return (cvector_item_t) NULL;
82    }
83    return cvector_get(&t->table, id);
84}
85
86int coat_free(coat_t *t, int id) {
87    assert(t);
88    if (cpool_check(&t->pool, id)) {
89        // Free but should have been allocated.
90        return -EBADF;
91    }
92    if (t->oat_delete) {
93        cvector_item_t obj = coat_get(t, id);
94        if (!obj) {
95            // No such object.
96            return -EBADF;
97        }
98        t->oat_delete(t, obj);
99    }
100    cvector_set(&t->table, id, (cvector_item_t) NULL);
101    cpool_free(&t->pool, id);
102    return 0;
103}
104