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