1*9508192eSchristos /* Id: dba_array.c,v 1.1 2016/07/19 21:31:55 schwarze Exp */
2*9508192eSchristos /*
3*9508192eSchristos * Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org>
4*9508192eSchristos *
5*9508192eSchristos * Permission to use, copy, modify, and distribute this software for any
6*9508192eSchristos * purpose with or without fee is hereby granted, provided that the above
7*9508192eSchristos * copyright notice and this permission notice appear in all copies.
8*9508192eSchristos *
9*9508192eSchristos * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10*9508192eSchristos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*9508192eSchristos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12*9508192eSchristos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*9508192eSchristos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*9508192eSchristos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15*9508192eSchristos * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*9508192eSchristos *
17*9508192eSchristos * Allocation-based arrays for the mandoc database, for read-write access.
18*9508192eSchristos * The interface is defined in "dba_array.h".
19*9508192eSchristos */
20*9508192eSchristos #include <assert.h>
21*9508192eSchristos #include <stdint.h>
22*9508192eSchristos #include <stdlib.h>
23*9508192eSchristos #include <string.h>
24*9508192eSchristos
25*9508192eSchristos #include "mandoc_aux.h"
26*9508192eSchristos #include "dba_write.h"
27*9508192eSchristos #include "dba_array.h"
28*9508192eSchristos
29*9508192eSchristos struct dba_array {
30*9508192eSchristos void **ep; /* Array of entries. */
31*9508192eSchristos int32_t *em; /* Array of map positions. */
32*9508192eSchristos int flags;
33*9508192eSchristos int32_t ea; /* Entries allocated. */
34*9508192eSchristos int32_t eu; /* Entries used (including deleted). */
35*9508192eSchristos int32_t ed; /* Entries deleted. */
36*9508192eSchristos int32_t ec; /* Currently active entry. */
37*9508192eSchristos int32_t pos; /* Map position of this array. */
38*9508192eSchristos };
39*9508192eSchristos
40*9508192eSchristos
41*9508192eSchristos struct dba_array *
dba_array_new(int32_t ea,int flags)42*9508192eSchristos dba_array_new(int32_t ea, int flags)
43*9508192eSchristos {
44*9508192eSchristos struct dba_array *array;
45*9508192eSchristos
46*9508192eSchristos assert(ea > 0);
47*9508192eSchristos array = mandoc_malloc(sizeof(*array));
48*9508192eSchristos array->ep = mandoc_reallocarray(NULL, ea, sizeof(*array->ep));
49*9508192eSchristos array->em = mandoc_reallocarray(NULL, ea, sizeof(*array->em));
50*9508192eSchristos array->ea = ea;
51*9508192eSchristos array->eu = 0;
52*9508192eSchristos array->ed = 0;
53*9508192eSchristos array->ec = 0;
54*9508192eSchristos array->flags = flags;
55*9508192eSchristos array->pos = 0;
56*9508192eSchristos return array;
57*9508192eSchristos }
58*9508192eSchristos
59*9508192eSchristos void
dba_array_free(struct dba_array * array)60*9508192eSchristos dba_array_free(struct dba_array *array)
61*9508192eSchristos {
62*9508192eSchristos int32_t ie;
63*9508192eSchristos
64*9508192eSchristos if (array == NULL)
65*9508192eSchristos return;
66*9508192eSchristos if (array->flags & DBA_STR)
67*9508192eSchristos for (ie = 0; ie < array->eu; ie++)
68*9508192eSchristos free(array->ep[ie]);
69*9508192eSchristos free(array->ep);
70*9508192eSchristos free(array->em);
71*9508192eSchristos free(array);
72*9508192eSchristos }
73*9508192eSchristos
74*9508192eSchristos void
dba_array_set(struct dba_array * array,int32_t ie,void * entry)75*9508192eSchristos dba_array_set(struct dba_array *array, int32_t ie, void *entry)
76*9508192eSchristos {
77*9508192eSchristos assert(ie >= 0);
78*9508192eSchristos assert(ie < array->ea);
79*9508192eSchristos assert(ie <= array->eu);
80*9508192eSchristos if (ie == array->eu)
81*9508192eSchristos array->eu++;
82*9508192eSchristos if (array->flags & DBA_STR)
83*9508192eSchristos entry = mandoc_strdup(entry);
84*9508192eSchristos array->ep[ie] = entry;
85*9508192eSchristos array->em[ie] = 0;
86*9508192eSchristos }
87*9508192eSchristos
88*9508192eSchristos void
dba_array_add(struct dba_array * array,void * entry)89*9508192eSchristos dba_array_add(struct dba_array *array, void *entry)
90*9508192eSchristos {
91*9508192eSchristos if (array->eu == array->ea) {
92*9508192eSchristos assert(array->flags & DBA_GROW);
93*9508192eSchristos array->ep = mandoc_reallocarray(array->ep,
94*9508192eSchristos 2, sizeof(*array->ep) * array->ea);
95*9508192eSchristos array->em = mandoc_reallocarray(array->em,
96*9508192eSchristos 2, sizeof(*array->em) * array->ea);
97*9508192eSchristos array->ea *= 2;
98*9508192eSchristos }
99*9508192eSchristos dba_array_set(array, array->eu, entry);
100*9508192eSchristos }
101*9508192eSchristos
102*9508192eSchristos void *
dba_array_get(struct dba_array * array,int32_t ie)103*9508192eSchristos dba_array_get(struct dba_array *array, int32_t ie)
104*9508192eSchristos {
105*9508192eSchristos if (ie < 0 || ie >= array->eu || array->em[ie] == -1)
106*9508192eSchristos return NULL;
107*9508192eSchristos return array->ep[ie];
108*9508192eSchristos }
109*9508192eSchristos
110*9508192eSchristos void
dba_array_start(struct dba_array * array)111*9508192eSchristos dba_array_start(struct dba_array *array)
112*9508192eSchristos {
113*9508192eSchristos array->ec = array->eu;
114*9508192eSchristos }
115*9508192eSchristos
116*9508192eSchristos void *
dba_array_next(struct dba_array * array)117*9508192eSchristos dba_array_next(struct dba_array *array)
118*9508192eSchristos {
119*9508192eSchristos if (array->ec < array->eu)
120*9508192eSchristos array->ec++;
121*9508192eSchristos else
122*9508192eSchristos array->ec = 0;
123*9508192eSchristos while (array->ec < array->eu && array->em[array->ec] == -1)
124*9508192eSchristos array->ec++;
125*9508192eSchristos return array->ec < array->eu ? array->ep[array->ec] : NULL;
126*9508192eSchristos }
127*9508192eSchristos
128*9508192eSchristos void
dba_array_del(struct dba_array * array)129*9508192eSchristos dba_array_del(struct dba_array *array)
130*9508192eSchristos {
131*9508192eSchristos if (array->ec < array->eu && array->em[array->ec] != -1) {
132*9508192eSchristos array->em[array->ec] = -1;
133*9508192eSchristos array->ed++;
134*9508192eSchristos }
135*9508192eSchristos }
136*9508192eSchristos
137*9508192eSchristos void
dba_array_undel(struct dba_array * array)138*9508192eSchristos dba_array_undel(struct dba_array *array)
139*9508192eSchristos {
140*9508192eSchristos memset(array->em, 0, sizeof(*array->em) * array->eu);
141*9508192eSchristos }
142*9508192eSchristos
143*9508192eSchristos void
dba_array_setpos(struct dba_array * array,int32_t ie,int32_t pos)144*9508192eSchristos dba_array_setpos(struct dba_array *array, int32_t ie, int32_t pos)
145*9508192eSchristos {
146*9508192eSchristos array->em[ie] = pos;
147*9508192eSchristos }
148*9508192eSchristos
149*9508192eSchristos int32_t
dba_array_getpos(struct dba_array * array)150*9508192eSchristos dba_array_getpos(struct dba_array *array)
151*9508192eSchristos {
152*9508192eSchristos return array->pos;
153*9508192eSchristos }
154*9508192eSchristos
155*9508192eSchristos void
dba_array_sort(struct dba_array * array,dba_compare_func func)156*9508192eSchristos dba_array_sort(struct dba_array *array, dba_compare_func func)
157*9508192eSchristos {
158*9508192eSchristos assert(array->ed == 0);
159*9508192eSchristos qsort(array->ep, array->eu, sizeof(*array->ep), func);
160*9508192eSchristos }
161*9508192eSchristos
162*9508192eSchristos int32_t
dba_array_writelen(struct dba_array * array,int32_t nmemb)163*9508192eSchristos dba_array_writelen(struct dba_array *array, int32_t nmemb)
164*9508192eSchristos {
165*9508192eSchristos dba_int_write(array->eu - array->ed);
166*9508192eSchristos return dba_skip(nmemb, array->eu - array->ed);
167*9508192eSchristos }
168*9508192eSchristos
169*9508192eSchristos void
dba_array_writepos(struct dba_array * array)170*9508192eSchristos dba_array_writepos(struct dba_array *array)
171*9508192eSchristos {
172*9508192eSchristos int32_t ie;
173*9508192eSchristos
174*9508192eSchristos array->pos = dba_tell();
175*9508192eSchristos for (ie = 0; ie < array->eu; ie++)
176*9508192eSchristos if (array->em[ie] != -1)
177*9508192eSchristos dba_int_write(array->em[ie]);
178*9508192eSchristos }
179*9508192eSchristos
180*9508192eSchristos void
dba_array_writelst(struct dba_array * array)181*9508192eSchristos dba_array_writelst(struct dba_array *array)
182*9508192eSchristos {
183*9508192eSchristos const char *str;
184*9508192eSchristos
185*9508192eSchristos dba_array_FOREACH(array, str)
186*9508192eSchristos dba_str_write(str);
187*9508192eSchristos dba_char_write('\0');
188*9508192eSchristos }
189