]> git.proxmox.com Git - mirror_frr.git/blame - lib/bitfield.h
*: add indent control files
[mirror_frr.git] / lib / bitfield.h
CommitLineData
50e24903
DS
1/* Bitfields
2 * Copyright (C) 2016 Cumulus Networks, Inc.
3 *
4 * This file is part of Quagga.
5 *
6 * Quagga is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * Quagga is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
896014f4
DL
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
50e24903 19 */
c3c0ac83
DS
20/**
21 * A simple bit array implementation to allocate and free IDs. An example
22 * of its usage is in allocating link state IDs for OSPFv3 as OSPFv3 has
23 * removed all address semantics from LS ID. Another usage can be in
24 * allocating IDs for BGP neighbors (and dynamic update groups) for
25 * efficient storage of adj-rib-out.
26 *
27 * An example:
28 * #include "bitfield.h"
29 *
30 * bitfield_t bitfield;
31 *
32 * bf_init(bitfield, 32);
33 * ...
34 * bf_assign_index(bitfield, id1);
35 * bf_assign_index(bitfield, id2);
36 * ...
37 * bf_release_index(bitfield, id1);
38 */
39
40#ifndef _BITFIELD_H
41#define _BITFIELD_H
42
43#include <stdio.h>
44#include <string.h>
45#include <stdlib.h>
46
47typedef unsigned int word_t;
48#define WORD_MAX 0xFFFFFFFF
49#define WORD_SIZE (sizeof(word_t) * 8)
50
51/**
52 * The bitfield structure.
53 * @data: the bits to manage.
54 * @n: The current word number that is being used.
55 * @m: total number of words in 'data'
56 */
57#define bitfield_t struct { word_t *data; size_t n, m; }
58
59/**
60 * Initialize the bits.
61 * @v: an instance of bitfield_t struct.
62 * @N: number of bits to start with, which equates to how many
63 * IDs can be allocated.
64 */
65#define bf_init(v, N) \
66 do { \
67 (v).n = 0; \
68 (v).m = ((N) / WORD_SIZE + 1); \
69 (v).data = calloc(1, ((v).m * sizeof(word_t))); \
70 } while (0)
71
72/**
73 * allocate and assign an id from bitfield v.
74 */
75#define bf_assign_index(v, id) \
76 do { \
77 bf_find_bit(v, id); \
78 bf_set_bit(v, id); \
79 } while (0)
80
4e9da201 81/*
82 * allocate and assign 0th bit in the bitfiled.
83 */
84#define bf_assign_zero_index(v) \
85 do { \
86 int id = 0; \
87 bf_assign_index(v, id); \
88 } while (0)
89
90/*
c3c0ac83
DS
91 * return an id to bitfield v
92 */
93#define bf_release_index(v, id) \
94 (v).data[bf_index(id)] &= ~(1 << (bf_offset(id)))
95
4e9da201 96/*
97 * return 0th index back to bitfield
98 */
99#define bf_release_zero_index(v) \
100 bf_release_index(v, 0)
101
c3c0ac83
DS
102#define bf_index(b) ((b) / WORD_SIZE)
103#define bf_offset(b) ((b) % WORD_SIZE)
104
105/**
106 * Set a bit in the array. If it fills up that word and we are
107 * out of words, extend it by one more word.
108 */
109#define bf_set_bit(v, b) \
110 do { \
111 size_t w = bf_index(b); \
112 (v).data[w] |= 1 << (bf_offset(b)); \
113 (v).n += ((v).data[w] == WORD_MAX); \
114 if ((v).n == (v).m) { \
115 (v).m = (v).m + 1; \
116 (v).data = realloc((v).data, (v).m * sizeof(word_t)); \
117 } \
118 } while (0)
119
120/* Find a clear bit in v and assign it to b. */
121#define bf_find_bit(v, b) \
122 do { \
45ef4300 123 word_t word = 0; \
c3c0ac83
DS
124 unsigned int w, sh; \
125 for (w = 0; w <= (v).n; w++) { \
126 if ((word = (v).data[w]) != WORD_MAX) break; \
127 } \
128 (b) = ((word & 0xFFFF) == 0xFFFF) << 4; word >>= (b); \
129 sh = ((word & 0xFF) == 0xFF) << 3; word >>= sh; (b) |= sh; \
130 sh = ((word & 0xF) == 0xF) << 2; word >>= sh; (b) |= sh; \
131 sh = ((word & 0x3) == 0x3) << 1; word >>= sh; (b) |= sh; \
132 sh = ((word & 0x1) == 0x1) << 0; word >>= sh; (b) |= sh; \
133 (b) += (w * WORD_SIZE); \
134 } while (0)
135
4e9da201 136/*
137 * Free the allocated memory for data
138 * @v: an instance of bitfield_t struct.
139 */
140#define bf_free(v) \
141 do { \
142 if ((v).data) { \
143 free((v).data); \
144 } \
145 } while (0)
146
c3c0ac83 147#endif