summaryrefslogtreecommitdiff
path: root/source/kit/dynamic_array.h
blob: d2f2a6b1502bcd5de839e1b05d1b85f625aa1801 (plain)
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
127
128
#ifndef KIT_DYNAMIC_ARRAY_H
#define KIT_DYNAMIC_ARRAY_H

#include "allocator.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
  ptrdiff_t        capacity;
  ptrdiff_t        size;
  void            *values;
  kit_allocator_t *alloc;
} kit_da_void_t;

void kit_da_init(kit_da_void_t *array, ptrdiff_t element_size,
                 ptrdiff_t size, kit_allocator_t *alloc);

void kit_da_resize(kit_da_void_t *array, ptrdiff_t element_size,
                   ptrdiff_t size);

void kit_da_resize_exact(kit_da_void_t *array, ptrdiff_t element_size,
                         ptrdiff_t size);

/*  Dynamic array type definition.
 */
#define KIT_DA(element_type_)  \
  struct {                     \
    ptrdiff_t        capacity; \
    ptrdiff_t        size;     \
    element_type_   *values;   \
    kit_allocator_t *alloc;    \
  }

/*  Initialize dynamic array.
 */
#define KIT_DA_INIT(array_, size_, alloc_) \
  kit_da_init((kit_da_void_t *) &(array_), \
              sizeof((array_).values[0]), (size_), (alloc_))

/*  Declare and initialize dynamic array.
 */
#define KIT_DA_CREATE(name_, element_type_, size_) \
  KIT_DA(element_type_) name_;                     \
  KIT_DA_INIT(name_, (size_), NULL)

/*  Destroy dynamic array.
 */
#define KIT_DA_DESTROY(array_)                                 \
  do {                                                         \
    if ((array_).values != NULL)                               \
      kit_alloc_dispatch((array_).alloc, KIT_DEALLOCATE, 0, 0, \
                         (array_).values);                     \
  } while (0)

/*  Resize dynamic array.
 */
#define KIT_DA_RESIZE(array_, size_)         \
  kit_da_resize((kit_da_void_t *) &(array_), \
                sizeof((array_).values[0]), size_)

/*  Resize dynamic array with exact capacity.
 */
#define KIT_DA_RESIZE_EXACT(array_, capacity_)     \
  kit_da_resize_exact((kit_da_void_t *) &(array_), \
                      sizeof((array_).values[0]), capacity_)

/*  Append a value to dynamic array.
 */
#define KIT_DA_APPEND(array_, value_)              \
  do {                                             \
    ptrdiff_t kit_index_back_ = (array_).size;     \
    KIT_DA_RESIZE((array_), kit_index_back_ + 1);  \
    if (kit_index_back_ < (array_).size)           \
      (array_).values[kit_index_back_] = (value_); \
  } while (0)

/*  Insert a value into dynamic array.
 */
#define KIT_DA_INSERT(array_, index_, value_)                  \
  do {                                                         \
    ptrdiff_t kit_i_;                                          \
    ptrdiff_t kit_index_back_ = (array_).size;                 \
    ptrdiff_t kit_indert_n_   = (index_);                      \
    KIT_DA_RESIZE((array_), kit_index_back_ + 1);              \
    if (kit_index_back_ + 1 == (array_).size) {                \
      for (kit_i_ = kit_index_back_; kit_i_ > kit_indert_n_;   \
           kit_i_--)                                           \
        (array_).values[kit_i_] = (array_).values[kit_i_ - 1]; \
      (array_).values[kit_indert_n_] = (value_);               \
    }                                                          \
  } while (0)

/*  Erase a value from dynamic array.
 */
#define KIT_DA_ERASE(array_, index_)                  \
  do {                                                \
    ptrdiff_t i_;                                     \
    for (i_ = (index_) + 1; i_ < (array_).size; i_++) \
      (array_).values[i_ - 1] = (array_).values[i_];  \
    KIT_DA_RESIZE((array_), (array_).size - 1);       \
  } while (0)

typedef KIT_DA(char) kit_string_t;

#ifndef KIT_DISABLE_SHORT_NAMES
#  define da_void_t kit_da_void_t
#  define da_init kit_da_init
#  define da_resize kit_da_resize
#  define string_t kit_string_t

#  define DA KIT_DA
#  define DA_INIT KIT_DA_INIT
#  define DA_CREATE KIT_DA_CREATE
#  define DA_DESTROY KIT_DA_DESTROY
#  define DA_RESIZE KIT_DA_RESIZE
#  define DA_RESIZE_EXACT KIT_DA_RESIZE_EXACT
#  define DA_APPEND KIT_DA_APPEND
#  define DA_INSERT KIT_DA_INSERT
#  define DA_ERASE KIT_DA_ERASE
#endif

#ifdef __cplusplus
}
#endif

#endif