1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#ifndef QEMU_RANGE_H
21#define QEMU_RANGE_H
22
23#include "qemu/queue.h"
24
25
26
27
28
29
30
31struct Range {
32
33
34
35
36
37 uint64_t lob;
38 uint64_t upb;
39};
40
41static inline void range_invariant(const Range *range)
42{
43 assert(range->lob <= range->upb || range->lob == range->upb + 1);
44}
45
46
47#define range_empty ((Range){ .lob = 1, .upb = 0 })
48
49
50static inline bool range_is_empty(const Range *range)
51{
52 range_invariant(range);
53 return range->lob > range->upb;
54}
55
56
57static inline bool range_contains(const Range *range, uint64_t val)
58{
59 return val >= range->lob && val <= range->upb;
60}
61
62
63static inline void range_make_empty(Range *range)
64{
65 *range = range_empty;
66 assert(range_is_empty(range));
67}
68
69
70
71
72
73
74
75static inline void range_set_bounds(Range *range, uint64_t lob, uint64_t upb)
76{
77 range->lob = lob;
78 range->upb = upb;
79 assert(!range_is_empty(range));
80}
81
82
83
84
85
86
87
88static inline void range_set_bounds1(Range *range,
89 uint64_t lob, uint64_t upb_plus1)
90{
91 if (!lob && !upb_plus1) {
92 *range = range_empty;
93 } else {
94 range->lob = lob;
95 range->upb = upb_plus1 - 1;
96 }
97 range_invariant(range);
98}
99
100
101static inline uint64_t range_lob(Range *range)
102{
103 assert(!range_is_empty(range));
104 return range->lob;
105}
106
107
108static inline uint64_t range_upb(Range *range)
109{
110 assert(!range_is_empty(range));
111 return range->upb;
112}
113
114
115
116
117
118
119static inline int QEMU_WARN_UNUSED_RESULT range_init(Range *range, uint64_t lob,
120 uint64_t size)
121{
122 if (lob + size < lob) {
123 return -ERANGE;
124 }
125 range->lob = lob;
126 range->upb = lob + size - 1;
127 range_invariant(range);
128 return 0;
129}
130
131
132
133
134
135static inline void range_init_nofail(Range *range, uint64_t lob, uint64_t size)
136{
137 range->lob = lob;
138 range->upb = lob + size - 1;
139 range_invariant(range);
140}
141
142
143
144
145static inline uint64_t range_size(const Range *range)
146{
147 return range->upb - range->lob + 1;
148}
149
150
151
152
153
154static inline bool range_overlaps_range(const Range *range1,
155 const Range *range2)
156{
157 if (range_is_empty(range1) || range_is_empty(range2)) {
158 return false;
159 }
160 return !(range2->upb < range1->lob || range1->upb < range2->lob);
161}
162
163
164
165
166
167static inline bool range_contains_range(const Range *range1,
168 const Range *range2)
169{
170 if (range_is_empty(range1) || range_is_empty(range2)) {
171 return false;
172 }
173 return range1->lob <= range2->lob && range1->upb >= range2->upb;
174}
175
176
177
178
179static inline void range_extend(Range *range, Range *extend_by)
180{
181 if (range_is_empty(extend_by)) {
182 return;
183 }
184 if (range_is_empty(range)) {
185 *range = *extend_by;
186 return;
187 }
188 if (range->lob > extend_by->lob) {
189 range->lob = extend_by->lob;
190 }
191 if (range->upb < extend_by->upb) {
192 range->upb = extend_by->upb;
193 }
194 range_invariant(range);
195}
196
197
198
199static inline uint64_t range_get_last(uint64_t offset, uint64_t len)
200{
201 return offset + len - 1;
202}
203
204
205static inline int range_covers_byte(uint64_t offset, uint64_t len,
206 uint64_t byte)
207{
208 return offset <= byte && byte <= range_get_last(offset, len);
209}
210
211
212
213static inline int ranges_overlap(uint64_t first1, uint64_t len1,
214 uint64_t first2, uint64_t len2)
215{
216 uint64_t last1 = range_get_last(first1, len1);
217 uint64_t last2 = range_get_last(first2, len2);
218
219 return !(last2 < first1 || last1 < first2);
220}
221
222GList *range_list_insert(GList *list, Range *data);
223
224#endif
225