Always evaluate BT_ASSERT(); add BT_ASSERT_DBG() for debug mode only
[babeltrace.git] / src / lib / integer-range-set.c
CommitLineData
fb91c0ef
PP
1/*
2 * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#define BT_LOG_TAG "LIB/INT-RANGE-SET"
24#include "lib/logging.h"
25
26#include <babeltrace2/babeltrace.h>
27#include "lib/assert-pre.h"
28#include "common/assert.h"
29#include "func-status.h"
30#include "integer-range-set.h"
31
6769570a
PP
32uint64_t bt_integer_range_unsigned_get_lower(
33 const struct bt_integer_range_unsigned *u_range)
fb91c0ef
PP
34{
35 const struct bt_integer_range *range = (const void *) u_range;
36
6769570a 37 BT_ASSERT_PRE_DEV_NON_NULL(range, "Integer range");
fb91c0ef
PP
38 return range->lower.u;
39}
40
6769570a
PP
41uint64_t bt_integer_range_unsigned_get_upper(
42 const struct bt_integer_range_unsigned *u_range)
fb91c0ef
PP
43{
44 const struct bt_integer_range *range = (const void *) u_range;
45
6769570a 46 BT_ASSERT_PRE_DEV_NON_NULL(range, "Integer range");
fb91c0ef
PP
47 return range->upper.u;
48}
49
6769570a
PP
50int64_t bt_integer_range_signed_get_lower(
51 const struct bt_integer_range_signed *i_range)
fb91c0ef
PP
52{
53 const struct bt_integer_range *range = (const void *) i_range;
54
6769570a 55 BT_ASSERT_PRE_DEV_NON_NULL(range, "Integer range");
fb91c0ef
PP
56 return range->lower.i;
57}
58
6769570a
PP
59int64_t bt_integer_range_signed_get_upper(
60 const struct bt_integer_range_signed *i_range)
fb91c0ef
PP
61{
62 const struct bt_integer_range *range = (const void *) i_range;
63
6769570a 64 BT_ASSERT_PRE_DEV_NON_NULL(range, "Integer range");
fb91c0ef
PP
65 return range->upper.i;
66}
67
68static
69bool compare_ranges(const struct bt_integer_range *range_a,
70 const struct bt_integer_range *range_b)
71{
72 return range_a->lower.u == range_b->lower.u &&
73 range_a->upper.u == range_b->upper.u;
74}
75
cd933d89 76bt_bool bt_integer_range_unsigned_is_equal(
fb91c0ef
PP
77 const struct bt_integer_range_unsigned *range_a,
78 const struct bt_integer_range_unsigned *range_b)
79{
6769570a
PP
80 BT_ASSERT_PRE_DEV_NON_NULL(range_a, "Integer range A");
81 BT_ASSERT_PRE_DEV_NON_NULL(range_b, "Integer range B");
fb91c0ef
PP
82 return (bt_bool) compare_ranges((const void *) range_a,
83 (const void *) range_b);
84}
85
cd933d89 86bt_bool bt_integer_range_signed_is_equal(
fb91c0ef
PP
87 const struct bt_integer_range_signed *range_a,
88 const struct bt_integer_range_signed *range_b)
89{
6769570a
PP
90 BT_ASSERT_PRE_DEV_NON_NULL(range_a, "Integer range A");
91 BT_ASSERT_PRE_DEV_NON_NULL(range_b, "Integer range B");
fb91c0ef
PP
92 return (bt_bool) compare_ranges((const void *) range_a,
93 (const void *) range_b);
94}
95
96uint64_t bt_integer_range_set_get_range_count(
97 const bt_integer_range_set *range_set)
98{
6769570a 99 BT_ASSERT_PRE_DEV_NON_NULL(range_set, "Integer range set");
fb91c0ef
PP
100 return (uint64_t) range_set->ranges->len;
101}
102
6769570a
PP
103const struct bt_integer_range_unsigned *
104bt_integer_range_set_unsigned_borrow_range_by_index_const(
105 const bt_integer_range_set_unsigned *u_range_set,
106 uint64_t index)
fb91c0ef 107{
6769570a
PP
108 const struct bt_integer_range_set *range_set =
109 (const void *) u_range_set;
fb91c0ef 110
6769570a 111 BT_ASSERT_PRE_DEV_NON_NULL(range_set, "Integer range set");
fb91c0ef 112 BT_ASSERT_PRE_DEV_VALID_INDEX(index, range_set->ranges->len);
6769570a
PP
113 return (const void *) BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(range_set,
114 index);
fb91c0ef
PP
115}
116
6769570a
PP
117const struct bt_integer_range_signed *
118bt_integer_range_set_signed_borrow_range_by_index_const(
fb91c0ef
PP
119 const bt_integer_range_set_signed *i_range_set, uint64_t index)
120{
6769570a
PP
121 const struct bt_integer_range_set *range_set =
122 (const void *) i_range_set;
fb91c0ef 123
6769570a 124 BT_ASSERT_PRE_DEV_NON_NULL(range_set, "Integer range set");
fb91c0ef 125 BT_ASSERT_PRE_DEV_VALID_INDEX(index, range_set->ranges->len);
6769570a
PP
126 return (const void *) BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(range_set,
127 index);
fb91c0ef
PP
128}
129
130static
131void destroy_range_set(struct bt_object *obj)
132{
133 struct bt_integer_range_set *range_set = (void *) obj;
134
6769570a
PP
135 BT_LIB_LOGD("Destroying integer range set: %!+R", range_set);
136
fb91c0ef
PP
137 if (range_set->ranges) {
138 g_array_free(range_set->ranges, TRUE);
139 range_set->ranges = NULL;
140 }
141
142 g_free(range_set);
143}
144
145static
146struct bt_integer_range_set *create_range_set(void)
147{
6769570a
PP
148 struct bt_integer_range_set *range_set;
149
150 BT_LOGD_STR("Creating empty integer range set.");
151 range_set = g_new0(struct bt_integer_range_set, 1);
fb91c0ef
PP
152
153 if (!range_set) {
6769570a
PP
154 BT_LIB_LOGE_APPEND_CAUSE(
155 "Failed to allocate one integer range set.");
fb91c0ef
PP
156 goto error;
157 }
158
159 bt_object_init_shared(&range_set->base, destroy_range_set);
160 range_set->ranges = g_array_new(FALSE, TRUE,
161 sizeof(struct bt_integer_range));
162 if (!range_set->ranges) {
163 BT_LIB_LOGE_APPEND_CAUSE(
6769570a 164 "Failed to allocate integer range set's range array.");
fb91c0ef
PP
165 goto error;
166 }
167
6769570a 168 BT_LOGD_STR("Created empty integer range set.");
fb91c0ef
PP
169 goto end;
170
171error:
172 BT_OBJECT_PUT_REF_AND_RESET(range_set);
173
174end:
175 return range_set;
176}
177
178struct bt_integer_range_set_unsigned *bt_integer_range_set_unsigned_create(void)
179{
180 return (void *) create_range_set();
181}
182
183struct bt_integer_range_set_signed *bt_integer_range_set_signed_create(void)
184{
185 return (void *) create_range_set();
186}
187
188void add_range_to_range_set(struct bt_integer_range_set *range_set,
189 uint64_t u_lower, uint64_t u_upper)
190{
191 struct bt_integer_range range = {
192 .lower.u = u_lower,
193 .upper.u = u_upper,
194 };
195
6769570a
PP
196 BT_ASSERT_PRE_NON_NULL(range_set, "Integer range set");
197 BT_ASSERT_PRE_DEV_HOT(range_set, "Integer range set", ": %!+R",
198 range_set);
fb91c0ef 199 g_array_append_val(range_set->ranges, range);
6769570a
PP
200 BT_LIB_LOGD("Added integer range to integer range set: "
201 "%![range-set-]+R, lower-unsigned=%" PRIu64 ", "
202 "upper-unsigned=%" PRIu64, range_set, u_lower, u_upper);
fb91c0ef
PP
203}
204
6769570a
PP
205enum bt_integer_range_set_add_range_status
206bt_integer_range_set_unsigned_add_range(
fb91c0ef
PP
207 struct bt_integer_range_set_unsigned *range_set,
208 uint64_t lower, uint64_t upper)
209{
210 BT_ASSERT_PRE(lower <= upper,
211 "Range's upper bound is less than lower bound: "
212 "upper=%" PRIu64 ", lower=%" PRIu64, lower, upper);
213 add_range_to_range_set((void *) range_set, lower, upper);
214 return BT_FUNC_STATUS_OK;
215}
216
6769570a
PP
217enum bt_integer_range_set_add_range_status
218bt_integer_range_set_signed_add_range(
fb91c0ef
PP
219 struct bt_integer_range_set_signed *range_set,
220 int64_t lower, int64_t upper)
221{
222 BT_ASSERT_PRE(lower <= upper,
223 "Range's upper bound is less than lower bound: "
224 "upper=%" PRId64 ", lower=%" PRId64, lower, upper);
225 add_range_to_range_set((void *) range_set,
226 (int64_t) lower, (int64_t) upper);
227 return BT_FUNC_STATUS_OK;
228}
229
230BT_HIDDEN
231void _bt_integer_range_set_freeze(const struct bt_integer_range_set *range_set)
232{
233 BT_ASSERT(range_set);
6769570a 234 BT_LIB_LOGD("Freezing integer range set: %!+R", range_set);
fb91c0ef
PP
235 ((struct bt_integer_range_set *) range_set)->frozen = true;
236}
237
238BT_HIDDEN
6769570a
PP
239bool bt_integer_range_set_unsigned_has_overlaps(
240 const struct bt_integer_range_set *range_set)
fb91c0ef
PP
241{
242 uint64_t i, j;
243 bool has_overlap = false;
244
245 BT_ASSERT(range_set);
246
247 for (i = 0; i < range_set->ranges->len; i++) {
248 const struct bt_integer_range *range_i =
249 BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(range_set, i);
250
251 for (j = 0; j < range_set->ranges->len; j++) {
252 const struct bt_integer_range *range_j =
6769570a
PP
253 BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(
254 range_set, j);
fb91c0ef
PP
255
256 if (i == j) {
257 continue;
258 }
259
260 if (range_i->lower.u <= range_j->upper.u &&
261 range_j->lower.u <= range_i->upper.u) {
262 has_overlap = true;
263 goto end;
264 }
265 }
266 }
267
268end:
269 return has_overlap;
270}
271
272BT_HIDDEN
6769570a
PP
273bool bt_integer_range_set_signed_has_overlaps(
274 const struct bt_integer_range_set *range_set)
fb91c0ef
PP
275{
276 uint64_t i, j;
277 bool has_overlap = false;
278
279 BT_ASSERT(range_set);
280
281 for (i = 0; i < range_set->ranges->len; i++) {
282 const struct bt_integer_range *range_i =
283 BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(range_set, i);
284
285 for (j = 0; j < range_set->ranges->len; j++) {
286 const struct bt_integer_range *range_j =
6769570a
PP
287 BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(
288 range_set, j);
fb91c0ef
PP
289
290 if (i == j) {
291 continue;
292 }
293
294 if (range_i->lower.i <= range_j->upper.i &&
295 range_j->lower.i <= range_i->upper.i) {
296 has_overlap = true;
297 goto end;
298 }
299 }
300 }
301
302end:
303 return has_overlap;
304}
305
306static
307bool compare_range_sets(const struct bt_integer_range_set *range_set_a,
308 const struct bt_integer_range_set *range_set_b)
309{
310 uint64_t a_i, b_i;
311 bool is_equal = true;
312
98b15851
PP
313 BT_ASSERT_DBG(range_set_a);
314 BT_ASSERT_DBG(range_set_b);
fb91c0ef
PP
315
316 if (range_set_a == range_set_b) {
317 goto end;
318 }
319
320 /*
321 * Not super effective for the moment: do a O(N²) compare, also
322 * checking that the sizes match.
323 */
324 if (range_set_a->ranges->len != range_set_b->ranges->len) {
325 is_equal = false;
326 goto end;
327 }
328
329 for (a_i = 0; a_i < range_set_a->ranges->len; a_i++) {
330 const struct bt_integer_range *range_a =
331 BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(range_set_a,
332 a_i);
333 bool b_has_range = false;
334
335 for (b_i = 0; b_i < range_set_b->ranges->len; b_i++) {
336 const struct bt_integer_range *range_b =
337 BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(
338 range_set_b, b_i);
339
340 if (compare_ranges(range_a, range_b)) {
341 b_has_range = true;
342 break;
343 }
344 }
345
346 if (!b_has_range) {
347 is_equal = false;
348 goto end;
349 }
350 }
351
352end:
353 return is_equal;
354}
355
cd933d89 356bt_bool bt_integer_range_set_unsigned_is_equal(
fb91c0ef
PP
357 const struct bt_integer_range_set_unsigned *range_set_a,
358 const struct bt_integer_range_set_unsigned *range_set_b)
359{
360 BT_ASSERT_PRE_DEV_NON_NULL(range_set_a, "Range set A");
361 BT_ASSERT_PRE_DEV_NON_NULL(range_set_b, "Range set B");
362 return (bt_bool) compare_range_sets((const void *) range_set_a,
363 (const void *) range_set_b);
364}
365
cd933d89 366bt_bool bt_integer_range_set_signed_is_equal(
fb91c0ef
PP
367 const struct bt_integer_range_set_signed *range_set_a,
368 const struct bt_integer_range_set_signed *range_set_b)
369{
370 BT_ASSERT_PRE_DEV_NON_NULL(range_set_a, "Range set A");
371 BT_ASSERT_PRE_DEV_NON_NULL(range_set_b, "Range set B");
372 return (bt_bool) compare_range_sets((const void *) range_set_a,
373 (const void *) range_set_b);
374}
375
376void bt_integer_range_set_unsigned_get_ref(
377 const struct bt_integer_range_set_unsigned *range_set)
378{
379 bt_object_get_ref(range_set);
380}
381
382void bt_integer_range_set_unsigned_put_ref(
383 const struct bt_integer_range_set_unsigned *range_set)
384{
385 bt_object_put_ref(range_set);
386}
387
6769570a
PP
388void bt_integer_range_set_signed_get_ref(
389 const struct bt_integer_range_set_signed *range_set)
fb91c0ef
PP
390{
391 bt_object_get_ref(range_set);
392}
393
6769570a
PP
394void bt_integer_range_set_signed_put_ref(
395 const struct bt_integer_range_set_signed *range_set)
fb91c0ef
PP
396{
397 bt_object_put_ref(range_set);
398}
This page took 0.044947 seconds and 4 git commands to generate.