]> Sergey Matveev's repositories - bfs.git/blob - src/darray.c
Formatting fixes
[bfs.git] / src / darray.c
1 // Copyright © Tavian Barnes <tavianator@tavianator.com>
2 // SPDX-License-Identifier: 0BSD
3
4 #include "darray.h"
5 #include <stdlib.h>
6 #include <string.h>
7
8 /**
9  * The darray header.
10  */
11 struct darray {
12         /** The current capacity of the array, as a count of elements. */
13         size_t capacity;
14         /** The current length of the array. */
15         size_t length;
16
17         // The array elements are stored after this header in memory.  Not using
18         // a flexible array member to avoid worrying about strict aliasing.  We
19         // assume that 2*sizeof(size_t) keeps any memory allocation suitably
20         // aligned for the element type.
21 };
22
23 /** Get the header for a darray. */
24 static struct darray *darray_header(const void *da) {
25         return (struct darray *)da - 1;
26 }
27
28 /** Get the array from a darray header. */
29 static char *darray_data(struct darray *header) {
30         return (char *)(header + 1);
31 }
32
33 size_t darray_length(const void *da) {
34         if (da) {
35                 return darray_header(da)->length;
36         } else {
37                 return 0;
38         }
39 }
40
41 void *darray_push(void *da, const void *item, size_t size) {
42         struct darray *header;
43         if (da) {
44                 header = darray_header(da);
45         } else {
46                 header = malloc(sizeof(*header) + size);
47                 if (!header) {
48                         return NULL;
49                 }
50                 header->capacity = 1;
51                 header->length = 0;
52         }
53
54         size_t capacity = header->capacity;
55         size_t i = header->length++;
56         if (i >= capacity) {
57                 capacity *= 2;
58                 header = realloc(header, sizeof(*header) + capacity * size);
59                 if (!header) {
60                         // This failure will be detected by darray_check()
61                         return da;
62                 }
63                 header->capacity = capacity;
64         }
65
66         char *data = darray_data(header);
67         memcpy(data + i * size, item, size);
68         return data;
69 }
70
71 int darray_check(void *da) {
72         if (!da) {
73                 return -1;
74         }
75
76         struct darray *header = darray_header(da);
77         if (header->length <= header->capacity) {
78                 return 0;
79         } else {
80                 // realloc() failed in darray_push(), so reset the length and report the failure
81                 header->length = header->capacity;
82                 return -1;
83         }
84 }
85
86 void darray_free(void *da) {
87         if (da) {
88                 free(darray_header(da));
89         }
90 }