2 * SPDX-License-Identifier: MIT
4 * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
7 #define BT_LOG_TAG "LIB/INT-RANGE-SET"
8 #include "lib/logging.h"
12 #include <babeltrace2/babeltrace.h>
14 #include "lib/assert-cond.h"
15 #include "common/assert.h"
16 #include "func-status.h"
17 #include "integer-range-set.h"
20 uint64_t bt_integer_range_unsigned_get_lower(
21 const struct bt_integer_range_unsigned
*u_range
)
23 const struct bt_integer_range
*range
= (const void *) u_range
;
25 BT_ASSERT_PRE_DEV_INT_RANGE_NON_NULL(range
);
26 return range
->lower
.u
;
30 uint64_t bt_integer_range_unsigned_get_upper(
31 const struct bt_integer_range_unsigned
*u_range
)
33 const struct bt_integer_range
*range
= (const void *) u_range
;
35 BT_ASSERT_PRE_DEV_INT_RANGE_NON_NULL(range
);
36 return range
->upper
.u
;
40 int64_t bt_integer_range_signed_get_lower(
41 const struct bt_integer_range_signed
*i_range
)
43 const struct bt_integer_range
*range
= (const void *) i_range
;
45 BT_ASSERT_PRE_DEV_INT_RANGE_NON_NULL(range
);
46 return range
->lower
.i
;
50 int64_t bt_integer_range_signed_get_upper(
51 const struct bt_integer_range_signed
*i_range
)
53 const struct bt_integer_range
*range
= (const void *) i_range
;
55 BT_ASSERT_PRE_DEV_INT_RANGE_NON_NULL(range
);
56 return range
->upper
.i
;
60 bool compare_ranges(const struct bt_integer_range
*range_a
,
61 const struct bt_integer_range
*range_b
)
63 return range_a
->lower
.u
== range_b
->lower
.u
&&
64 range_a
->upper
.u
== range_b
->upper
.u
;
68 bt_bool
bt_integer_range_unsigned_is_equal(
69 const struct bt_integer_range_unsigned
*range_a
,
70 const struct bt_integer_range_unsigned
*range_b
)
72 BT_ASSERT_PRE_DEV_NON_NULL("integer-range-a", range_a
,
74 BT_ASSERT_PRE_DEV_NON_NULL("integer-range-b", range_b
,
76 return (bt_bool
) compare_ranges((const void *) range_a
,
77 (const void *) range_b
);
81 bt_bool
bt_integer_range_signed_is_equal(
82 const struct bt_integer_range_signed
*range_a
,
83 const struct bt_integer_range_signed
*range_b
)
85 BT_ASSERT_PRE_DEV_NON_NULL("integer-range-a", range_a
,
87 BT_ASSERT_PRE_DEV_NON_NULL("integer-range-b", range_b
,
89 return (bt_bool
) compare_ranges((const void *) range_a
,
90 (const void *) range_b
);
94 uint64_t bt_integer_range_set_get_range_count(
95 const bt_integer_range_set
*range_set
)
97 BT_ASSERT_PRE_DEV_INT_RANGE_SET_NON_NULL(range_set
);
98 return (uint64_t) range_set
->ranges
->len
;
102 const struct bt_integer_range_unsigned
*
103 bt_integer_range_set_unsigned_borrow_range_by_index_const(
104 const bt_integer_range_set_unsigned
*u_range_set
,
107 const struct bt_integer_range_set
*range_set
=
108 (const void *) u_range_set
;
110 BT_ASSERT_PRE_DEV_INT_RANGE_SET_NON_NULL(range_set
);
111 BT_ASSERT_PRE_DEV_VALID_INDEX(index
, range_set
->ranges
->len
);
112 return (const void *) BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(range_set
,
117 const struct bt_integer_range_signed
*
118 bt_integer_range_set_signed_borrow_range_by_index_const(
119 const bt_integer_range_set_signed
*i_range_set
, uint64_t index
)
121 const struct bt_integer_range_set
*range_set
=
122 (const void *) i_range_set
;
124 BT_ASSERT_PRE_DEV_INT_RANGE_SET_NON_NULL(range_set
);
125 BT_ASSERT_PRE_DEV_VALID_INDEX(index
, range_set
->ranges
->len
);
126 return (const void *) BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(range_set
,
131 void destroy_range_set(struct bt_object
*obj
)
133 struct bt_integer_range_set
*range_set
= (void *) obj
;
135 BT_LIB_LOGD("Destroying integer range set: %!+R", range_set
);
137 if (range_set
->ranges
) {
138 g_array_free(range_set
->ranges
, TRUE
);
139 range_set
->ranges
= NULL
;
146 struct bt_integer_range_set
*create_range_set(void)
148 struct bt_integer_range_set
*range_set
;
150 BT_LOGD_STR("Creating empty integer range set.");
151 range_set
= g_new0(struct bt_integer_range_set
, 1);
154 BT_LIB_LOGE_APPEND_CAUSE(
155 "Failed to allocate one integer range set.");
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(
164 "Failed to allocate integer range set's range array.");
168 BT_LOGD_STR("Created empty integer range set.");
172 BT_OBJECT_PUT_REF_AND_RESET(range_set
);
179 struct bt_integer_range_set_unsigned
*bt_integer_range_set_unsigned_create(void)
181 BT_ASSERT_PRE_NO_ERROR();
183 return (void *) create_range_set();
187 struct bt_integer_range_set_signed
*bt_integer_range_set_signed_create(void)
189 BT_ASSERT_PRE_NO_ERROR();
191 return (void *) create_range_set();
195 void add_range_to_range_set(struct bt_integer_range_set
*range_set
,
196 uint64_t u_lower
, uint64_t u_upper
)
198 struct bt_integer_range range
= {
203 BT_ASSERT_PRE_INT_RANGE_SET_NON_NULL(range_set
);
204 BT_ASSERT_PRE_DEV_HOT("integer-range-set", range_set
,
205 "Integer range set", ": %!+R", range_set
);
206 g_array_append_val(range_set
->ranges
, range
);
207 BT_LIB_LOGD("Added integer range to integer range set: "
208 "%![range-set-]+R, lower-unsigned=%" PRIu64
", "
209 "upper-unsigned=%" PRIu64
, range_set
, u_lower
, u_upper
);
213 enum bt_integer_range_set_add_range_status
214 bt_integer_range_set_unsigned_add_range(
215 struct bt_integer_range_set_unsigned
*range_set
,
216 uint64_t lower
, uint64_t upper
)
218 BT_ASSERT_PRE_NO_ERROR();
219 BT_ASSERT_PRE("lower-lteq-upper", lower
<= upper
,
220 "Range's upper bound is less than lower bound: "
221 "upper=%" PRIu64
", lower=%" PRIu64
, lower
, upper
);
222 add_range_to_range_set((void *) range_set
, lower
, upper
);
223 return BT_FUNC_STATUS_OK
;
227 enum bt_integer_range_set_add_range_status
228 bt_integer_range_set_signed_add_range(
229 struct bt_integer_range_set_signed
*range_set
,
230 int64_t lower
, int64_t upper
)
232 BT_ASSERT_PRE_NO_ERROR();
233 BT_ASSERT_PRE("lower-lteq-upper", lower
<= upper
,
234 "Range's upper bound is less than lower bound: "
235 "upper=%" PRId64
", lower=%" PRId64
, lower
, upper
);
236 add_range_to_range_set((void *) range_set
,
237 (int64_t) lower
, (int64_t) upper
);
238 return BT_FUNC_STATUS_OK
;
241 void _bt_integer_range_set_freeze(const struct bt_integer_range_set
*range_set
)
243 BT_ASSERT(range_set
);
244 BT_LIB_LOGD("Freezing integer range set: %!+R", range_set
);
245 ((struct bt_integer_range_set
*) range_set
)->frozen
= true;
248 bool bt_integer_range_set_unsigned_has_overlaps(
249 const struct bt_integer_range_set
*range_set
)
252 bool has_overlap
= false;
254 BT_ASSERT(range_set
);
256 for (i
= 0; i
< range_set
->ranges
->len
; i
++) {
257 const struct bt_integer_range
*range_i
=
258 BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(range_set
, i
);
260 for (j
= 0; j
< range_set
->ranges
->len
; j
++) {
261 const struct bt_integer_range
*range_j
=
262 BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(
269 if (range_i
->lower
.u
<= range_j
->upper
.u
&&
270 range_j
->lower
.u
<= range_i
->upper
.u
) {
281 bool bt_integer_range_set_signed_has_overlaps(
282 const struct bt_integer_range_set
*range_set
)
285 bool has_overlap
= false;
287 BT_ASSERT(range_set
);
289 for (i
= 0; i
< range_set
->ranges
->len
; i
++) {
290 const struct bt_integer_range
*range_i
=
291 BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(range_set
, i
);
293 for (j
= 0; j
< range_set
->ranges
->len
; j
++) {
294 const struct bt_integer_range
*range_j
=
295 BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(
302 if (range_i
->lower
.i
<= range_j
->upper
.i
&&
303 range_j
->lower
.i
<= range_i
->upper
.i
) {
315 bool compare_range_sets(const struct bt_integer_range_set
*range_set_a
,
316 const struct bt_integer_range_set
*range_set_b
)
319 bool is_equal
= true;
321 BT_ASSERT_DBG(range_set_a
);
322 BT_ASSERT_DBG(range_set_b
);
324 if (range_set_a
== range_set_b
) {
329 * Not super effective for the moment: do a O(N²) compare, also
330 * checking that the sizes match.
332 if (range_set_a
->ranges
->len
!= range_set_b
->ranges
->len
) {
337 for (a_i
= 0; a_i
< range_set_a
->ranges
->len
; a_i
++) {
338 const struct bt_integer_range
*range_a
=
339 BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(range_set_a
,
341 bool b_has_range
= false;
343 for (b_i
= 0; b_i
< range_set_b
->ranges
->len
; b_i
++) {
344 const struct bt_integer_range
*range_b
=
345 BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(
348 if (compare_ranges(range_a
, range_b
)) {
365 bt_bool
bt_integer_range_set_unsigned_is_equal(
366 const struct bt_integer_range_set_unsigned
*range_set_a
,
367 const struct bt_integer_range_set_unsigned
*range_set_b
)
369 BT_ASSERT_PRE_DEV_NON_NULL("integer-range-set-a", range_set_a
,
371 BT_ASSERT_PRE_DEV_NON_NULL("integer-range-set-b", range_set_b
,
373 return (bt_bool
) compare_range_sets((const void *) range_set_a
,
374 (const void *) range_set_b
);
378 bt_bool
bt_integer_range_set_signed_is_equal(
379 const struct bt_integer_range_set_signed
*range_set_a
,
380 const struct bt_integer_range_set_signed
*range_set_b
)
382 BT_ASSERT_PRE_DEV_NON_NULL("integer-range-set-a", range_set_a
,
384 BT_ASSERT_PRE_DEV_NON_NULL("integer-range-set-b", range_set_b
,
386 return (bt_bool
) compare_range_sets((const void *) range_set_a
,
387 (const void *) range_set_b
);
391 void bt_integer_range_set_unsigned_get_ref(
392 const struct bt_integer_range_set_unsigned
*range_set
)
394 bt_object_get_ref(range_set
);
398 void bt_integer_range_set_unsigned_put_ref(
399 const struct bt_integer_range_set_unsigned
*range_set
)
401 bt_object_put_ref(range_set
);
405 void bt_integer_range_set_signed_get_ref(
406 const struct bt_integer_range_set_signed
*range_set
)
408 bt_object_get_ref(range_set
);
412 void bt_integer_range_set_signed_put_ref(
413 const struct bt_integer_range_set_signed
*range_set
)
415 bt_object_put_ref(range_set
);