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