summaryrefslogtreecommitdiffstats
path: root/src/darray.h
blob: 7e5ae5d387a1fb2824c8b4df3d69628c263004d4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/* SPDX-License-Identifier: BSD-3-Clause */
/*
 * Copyright © 2010, Zed A. Shaw.
 * Copyright © 2020 rsiddharth <s@ricketyspace.net>
 */

#ifndef _DArray_h
#define _DArray_h
#include <stdlib.h>
#include <assert.h>
#include <dbg.h>

typedef struct DArray {
    int end;
    int max;
    size_t element_size;
    size_t expand_rate;
    void **contents;
} DArray;

typedef int (*DArray_compare) (const void *a, const void *b);

DArray *DArray_create(size_t element_size, size_t initial_max);

void DArray_destroy(DArray *array);

void DArray_clear(DArray *array);

int DArray_expand(DArray *array);

int DArray_contract(DArray *array);

int DArray_push(DArray *array, void *el);

void *DArray_pop(DArray *array);

int DArray_sort_add(DArray *array, void *el, DArray_compare cmp);

int DArray_find(DArray *array, void *el, DArray_compare cmp);

void DArray_clear_destroy(DArray *array);

/**
 * Creates a new DArray using `DArray_create` and copies the
 * `contents` from array to the newly created DArray.
 *
 * Returns newly created DArray.
 */
DArray *DArray_shallow_copy(DArray *array);

#define DArray_last(A) ((A)->contents[(A)->end - 1])
#define DArray_first(A) ((A)->contents[0])
#define DArray_end(A) ((A)->end)
#define DArray_count(A) DArray_end(A)
#define DArray_max(A) ((A)->max)

#define DEFAULT_EXPAND_RATE 300

static inline int DArray_set(DArray *array, int i, void *el)
{
    check(array != NULL, "array cannot be NULL");
    check(i >= 0, "i cannot be lesser than 0");

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-overflow"
    check(i < array->max, "darray attempt to set past max");
#pragma GCC diagnostic pop

    if (i > array->end)
        array->end = i;

    array->contents[i] = el;
    return i;
 error:
    return -1;
}

static inline void *DArray_get(DArray *array, int i)
{
    check(array != NULL, "array cannot be NULL");
    check(i >= 0, "i cannot be lesser than 0");

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-overflow"
    check(i < array->max, "darray attempt to get past max");
#pragma GCC diagnostic pop

    return array->contents[i];
 error:
    return NULL;
}

static inline void *DArray_remove(DArray *array, int i)
{
    check(array != NULL, "array cannot be NULL");
    check(i >= 0, "i cannot be lesser than 0");

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-overflow"
    check(i < array->max, "darray attempt to get past max");
#pragma GCC diagnostic pop

    void *el = array->contents[i];

    array->contents[i] = NULL;

    return el;
 error:
    return NULL;
}

static inline void *DArray_new(DArray *array)
{
    check(array != NULL, "array cannot be NULL");
    check(array->element_size > 0,
          "Can't use DArray_new on 0 size darrays.");

    return calloc(1, array->element_size);

 error:
    return NULL;
}

#define DArray_free(E) free((E))

#endif