xref: /openbsd-src/usr.bin/mandoc/dba_array.c (revision ff2dbb0f77feb7ad872603e25f443eae80e0c642)
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