1 /*
2  * This file is part of the Yices SMT Solver.
3  * Copyright (C) 2017 SRI International.
4  *
5  * Yices is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * Yices is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with Yices.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 /*
20  * VECTORS OF POINTERS WITH HIDDEN HEADER
21  */
22 
23 #ifndef __POINTER_VECTORS_H
24 #define __POINTER_VECTORS_H
25 
26 #include <stddef.h>
27 #include <stdint.h>
28 #include <stdbool.h>
29 #include <stdlib.h>
30 #include <assert.h>
31 
32 #include "utils/memalloc.h"
33 
34 
35 // Header + array
36 typedef struct ptr_vector_s {
37   uint32_t capacity;  // size of data array
38   uint32_t size;      // number of elements
39   void *data[0];      // real size = capacity
40 } ptr_vector_t;
41 
42 
43 /*
44  * Access to the header
45  */
pv_header(void ** v)46 static inline ptr_vector_t *pv_header(void **v) {
47   return (ptr_vector_t *) (((char *) v) - offsetof(ptr_vector_t, data));
48 }
49 
pv_size(void ** v)50 static inline uint32_t pv_size(void **v) {
51   return pv_header(v)->size;
52 }
53 
pv_capacity(void ** v)54 static inline uint32_t pv_capacity(void **v) {
55   return pv_header(v)->capacity;
56 }
57 
58 
59 /*
60  * Default and maximal size
61  */
62 #define DEF_PTR_VECTOR_SIZE 10
63 #define MAX_PTR_VECTOR_SIZE (((uint32_t)(UINT32_MAX - sizeof(ptr_vector_t)))/8)
64 
65 
66 /*
67  * Add elem p at the end of vector *v
68  * - if *v is NULL, allocate a fresh vector of default size
69  */
70 extern void add_ptr_to_vector(void ***v, void *p);
71 
72 
73 /*
74  * Increase v's capacity for at least n elements
75  * - if *v is NULL, a fresh vector of capacity = max(n, default size) is allocated
76  * - if *v is large enough already, nothing is done
77  * The size of v is not changed.
78  */
79 extern void resize_ptr_vector(void ***v, uint32_t n);
80 
81 
82 
83 /*
84  * Delete vector v
85  */
delete_ptr_vector(void ** v)86 static inline void delete_ptr_vector(void **v) {
87   if (v != NULL) {
88     safe_free(pv_header(v));
89   }
90 }
91 
92 
93 /*
94  * Empty vector v
95  */
reset_ptr_vector(void ** v)96 static inline void reset_ptr_vector(void **v) {
97   if (v != NULL) {
98     pv_header(v)->size = 0;
99   }
100 }
101 
102 
103 /*
104  * Keep only the n first elements of v
105  * - v must be non NULL
106  * - n must be <= size of v
107  */
ptr_vector_shrink(void ** v,uint32_t n)108 static inline void ptr_vector_shrink(void **v, uint32_t n) {
109   assert(v != NULL && pv_size(v) >= n);
110   pv_header(v)->size = n;
111 }
112 
113 
114 
115 /*
116  * Remove the last element of v
117  * - v must be non-null and non-empty
118  */
ptr_vector_pop(void ** v)119 static inline void ptr_vector_pop(void **v) {
120   assert(v != NULL && pv_size(v) > 0);
121   pv_header(v)->size --;
122 }
123 
124 
125 /*
126  * Get the last element of v
127  * - v must be non-null and non-empty
128  */
ptr_vector_last(void ** v)129 static inline void *ptr_vector_last(void **v) {
130   assert(v != NULL && pv_size(v) > 0);
131   return v[pv_size(v) - 1];
132 }
133 
134 
135 #endif /* __POINTER_VECTORS_H */
136