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