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