xref: /qemu/include/qemu/range.h (revision bf8d4924)
1 /*
2  * QEMU 64-bit address ranges
3  *
4  * Copyright (c) 2015-2016 Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #ifndef QEMU_RANGE_H
22 #define QEMU_RANGE_H
23 
24 #include "qemu/queue.h"
25 
26 /*
27  * Operations on 64 bit address ranges.
28  * Notes:
29  *   - ranges must not wrap around 0, but can include the last byte ~0x0LL.
30  *   - this can not represent a full 0 to ~0x0LL range.
31  */
32 
33 /* A structure representing a range of addresses. */
34 struct Range {
35     uint64_t begin; /* First byte of the range, or 0 if empty. */
36     uint64_t end;   /* 1 + the last byte. 0 if range empty or ends at ~0x0LL. */
37 };
38 
39 static inline void range_extend(Range *range, Range *extend_by)
40 {
41     if (!extend_by->begin && !extend_by->end) {
42         return;
43     }
44     if (!range->begin && !range->end) {
45         *range = *extend_by;
46         return;
47     }
48     if (range->begin > extend_by->begin) {
49         range->begin = extend_by->begin;
50     }
51     /* Compare last byte in case region ends at ~0x0LL */
52     if (range->end - 1 < extend_by->end - 1) {
53         range->end = extend_by->end;
54     }
55 }
56 
57 /* Get last byte of a range from offset + length.
58  * Undefined for ranges that wrap around 0. */
59 static inline uint64_t range_get_last(uint64_t offset, uint64_t len)
60 {
61     return offset + len - 1;
62 }
63 
64 /* Check whether a given range covers a given byte. */
65 static inline int range_covers_byte(uint64_t offset, uint64_t len,
66                                     uint64_t byte)
67 {
68     return offset <= byte && byte <= range_get_last(offset, len);
69 }
70 
71 /* Check whether 2 given ranges overlap.
72  * Undefined if ranges that wrap around 0. */
73 static inline int ranges_overlap(uint64_t first1, uint64_t len1,
74                                  uint64_t first2, uint64_t len2)
75 {
76     uint64_t last1 = range_get_last(first1, len1);
77     uint64_t last2 = range_get_last(first2, len2);
78 
79     return !(last2 < first1 || last1 < first2);
80 }
81 
82 GList *range_list_insert(GList *list, Range *data);
83 
84 #endif
85