Graphviz 13.1.2~dev.20250807.2324
Loading...
Searching...
No Matches
bitarray.h
Go to the documentation of this file.
1
22
23#pragma once
24
25#include <assert.h>
26#include <inttypes.h>
27#include <stdbool.h>
28#include <stdint.h>
29#include <stdlib.h>
30#include <string.h>
31#include <util/alloc.h>
32
38typedef struct {
39 union {
40 uint8_t block[sizeof(uint8_t *)];
41 uint8_t *base;
42 };
43 size_t size_bits;
45
47static inline bitarray_t bitarray_new(size_t size_bits) {
48
49 bitarray_t ba = {.size_bits = size_bits};
50
51 // if the array is small enough, we can use inline storage
52 if (size_bits <= sizeof(ba.block) * 8) {
53 // nothing to be done
54
55 // otherwise we need to heap-allocate
56 } else {
57 size_t capacity = size_bits / 8 + (size_bits % 8 == 0 ? 0 : 1);
58 ba.base = gv_calloc(capacity, sizeof(uint8_t));
59 }
60
61 return ba;
62}
63
65static inline bool bitarray_get(bitarray_t self, size_t index) {
66 assert(index < self.size_bits && "out of bounds access");
67
68 // determine if this array is stored inline or not
69 const uint8_t *base;
70 if (self.size_bits <= sizeof(self.block) * 8) {
71 base = self.block;
72 } else {
73 base = self.base;
74 }
75
76 return (base[index / 8] >> (index % 8)) & 1;
77}
78
80static inline void bitarray_set(bitarray_t *self, size_t index, bool value) {
81 assert(index < self->size_bits && "out of bounds access");
82
83 // determine if this array is stored inline or not
84 uint8_t *base;
85 if (self->size_bits <= sizeof(self->block) * 8) {
86 base = self->block;
87 } else {
88 base = self->base;
89 }
90
91 if (value) {
92 base[index / 8] |= (uint8_t)(UINT8_C(1) << (index % 8));
93 } else {
94 base[index / 8] &= (uint8_t)~(UINT8_C(1) << (index % 8));
95 }
96}
97
99static inline void bitarray_clear(bitarray_t *self) {
100 assert(self != NULL);
101
102 // determine if this array is stored inline or not
103 uint8_t *const base =
104 self->size_bits <= sizeof(self->block) * 8 ? self->block : self->base;
105
106 // calculate byte extent covering the array
107 const size_t size = self->size_bits / 8 + (self->size_bits % 8 == 0 ? 0 : 1);
108
109 // zero all bits
110 memset(base, 0, size);
111}
112
114static inline void bitarray_reset(bitarray_t *self) {
115 assert(self != NULL);
116
117 // is this array stored out of line?
118 if (self->size_bits > sizeof(self->block) * 8)
119 free(self->base);
120
121 *self = (bitarray_t){0};
122}
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
static bitarray_t bitarray_new(size_t size_bits)
create an array of the given element length
Definition bitarray.h:47
static void bitarray_clear(bitarray_t *self)
clear all bits in a bit array
Definition bitarray.h:99
static bool bitarray_get(bitarray_t self, size_t index)
get the value of the given element
Definition bitarray.h:65
static void bitarray_set(bitarray_t *self, size_t index, bool value)
set or clear the value of the given element
Definition bitarray.h:80
static void bitarray_reset(bitarray_t *self)
free underlying resources and leave a bit array empty
Definition bitarray.h:114
void free(void *)
node NULL
Definition grammar.y:180
uint8_t block[sizeof(uint8_t *)]
inline storage for small arrays
Definition bitarray.h:40
size_t size_bits
extent in bits
Definition bitarray.h:43
uint8_t * base
start of the underlying allocated buffer
Definition bitarray.h:41
Definition block.h:26