forked from openvswitch/ovs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbitmap.c
155 lines (135 loc) · 4 KB
/
bitmap.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
* Copyright (c) 2008, 2009, 2011, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <config.h>
#include "bitmap.h"
#include <string.h>
#include "util.h"
/* Allocates and returns a bitmap initialized to all-1-bits. */
unsigned long *
bitmap_allocate1(size_t n_bits)
{
size_t n_bytes = bitmap_n_bytes(n_bits);
size_t n_longs = bitmap_n_longs(n_bits);
size_t r_bits = n_bits % BITMAP_ULONG_BITS;
unsigned long *bitmap;
/* Allocate and initialize most of the bitmap. */
bitmap = xmalloc(n_bytes);
memset(bitmap, 0xff, n_bytes);
/* Ensure that the last "unsigned long" in the bitmap only has as many
* 1-bits as there actually should be. */
if (r_bits) {
bitmap[n_longs - 1] = (1UL << r_bits) - 1;
}
return bitmap;
}
/* Sets 'count' consecutive bits in 'bitmap', starting at bit offset 'start',
* to 'value'. */
void
bitmap_set_multiple(unsigned long *bitmap, size_t start, size_t count,
bool value)
{
for (; count && start % BITMAP_ULONG_BITS; count--) {
bitmap_set(bitmap, start++, value);
}
for (; count >= BITMAP_ULONG_BITS; count -= BITMAP_ULONG_BITS) {
*bitmap_unit__(bitmap, start) = -(unsigned long) value;
start += BITMAP_ULONG_BITS;
}
for (; count; count--) {
bitmap_set(bitmap, start++, value);
}
}
/* Compares the 'n' bits in bitmaps 'a' and 'b'. Returns true if all bits are
* equal, false otherwise. */
bool
bitmap_equal(const unsigned long *a, const unsigned long *b, size_t n)
{
size_t i;
if (memcmp(a, b, n / BITMAP_ULONG_BITS * sizeof(unsigned long))) {
return false;
}
for (i = ROUND_DOWN(n, BITMAP_ULONG_BITS); i < n; i++) {
if (bitmap_is_set(a, i) != bitmap_is_set(b, i)) {
return false;
}
}
return true;
}
/* Scans 'bitmap' from bit offset 'start' to 'end', excluding 'end' itself.
* Returns the bit offset of the lowest-numbered bit set to 'target', or 'end'
* if all of the bits are set to '!target'. */
size_t
bitmap_scan(const unsigned long int *bitmap, bool target,
size_t start, size_t end)
{
/* XXX slow */
size_t i;
for (i = start; i < end; i++) {
if (bitmap_is_set(bitmap, i) == target) {
break;
}
}
return i;
}
/* Returns the number of 1-bits in the 'n'-bit bitmap at 'bitmap'. */
size_t
bitmap_count1(const unsigned long int *bitmap, size_t n)
{
size_t i;
size_t count = 0;
BUILD_ASSERT(ULONG_MAX <= UINT64_MAX);
for (i = 0; i < BITMAP_N_LONGS(n); i++) {
count += count_1bits(bitmap[i]);
}
return count;
}
/* "dst &= arg;" for n-bit dst and arg. */
void
bitmap_and(unsigned long *dst, const unsigned long *arg, size_t n)
{
size_t i;
for (i = 0; i < BITMAP_N_LONGS(n); i++) {
dst[i] &= arg[i];
}
}
/* "dst |= arg;" for n-bit dst and arg. */
void
bitmap_or(unsigned long *dst, const unsigned long *arg, size_t n)
{
size_t i;
for (i = 0; i < BITMAP_N_LONGS(n); i++) {
dst[i] |= arg[i];
}
}
/* "dst = ~dst;" for n-bit dst. */
void
bitmap_not(unsigned long *dst, size_t n)
{
size_t i;
for (i = 0; i < n / BITMAP_ULONG_BITS; i++) {
dst[i] = ~dst[i];
}
if (n % BITMAP_ULONG_BITS) {
dst[i] ^= (1u << (n % BITMAP_ULONG_BITS)) - 1;
}
}
/* Returns true if all of the 'n' bits in 'bitmap' are 0,
* false if at least one bit is a 1.*/
bool
bitmap_is_all_zeros(const unsigned long *bitmap, size_t n)
{
return bitmap_scan(bitmap, true, 0, n) == n;
}