mirror of
https://github.com/yuzu-emu/unicorn
synced 2024-11-24 15:18:08 +00:00
8b2a0c4ece
Users of struct Range mess liberally with its members, which makes refactoring hard. Create a set of methods, and convert all users to call them instead of accessing members. The methods have carefully worded contracts, and use assertions to check them. Backports commit a0efbf16604770b9d805bcf210ec29942321134f from qemu
75 lines
2.2 KiB
C
75 lines
2.2 KiB
C
/*
|
|
* QEMU 64-bit address ranges
|
|
*
|
|
* Copyright (c) 2015-2016 Red Hat, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public
|
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "qemu/osdep.h"
|
|
#include "qemu/range.h"
|
|
|
|
/*
|
|
* Operations on 64 bit address ranges.
|
|
* Notes:
|
|
* - ranges must not wrap around 0, but can include the last byte ~0x0LL.
|
|
* - this can not represent a full 0 to ~0x0LL range.
|
|
*/
|
|
|
|
/* Return -1 if @a < @b, 1 if greater, and 0 if they touch or overlap. */
|
|
static inline int range_compare(Range *a, Range *b)
|
|
{
|
|
/* Zero a->end is 2**64, and therefore not less than any b->begin */
|
|
if (a->end && a->end < b->begin) {
|
|
return -1;
|
|
}
|
|
if (b->end && a->begin > b->end) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Insert @data into @list of ranges; caller no longer owns @data */
|
|
GList *range_list_insert(GList *list, Range *data)
|
|
{
|
|
GList *l;
|
|
|
|
assert(!range_is_empty(data));
|
|
|
|
/* Skip all list elements strictly less than data */
|
|
for (l = list; l && range_compare(l->data, data) < 0; l = l->next) {
|
|
}
|
|
|
|
if (!l || range_compare(l->data, data) > 0) {
|
|
/* Rest of the list (if any) is strictly greater than @data */
|
|
return g_list_insert_before(list, l, data);
|
|
}
|
|
|
|
/* Current list element overlaps @data, merge the two */
|
|
range_extend(l->data, data);
|
|
g_free(data);
|
|
|
|
/* Merge any subsequent list elements that now also overlap */
|
|
while (l->next && range_compare(l->data, l->next->data) == 0) {
|
|
GList *new_l;
|
|
|
|
range_extend(l->data, l->next->data);
|
|
g_free(l->next->data);
|
|
new_l = g_list_delete_link(list, l->next);
|
|
assert(new_l == list);
|
|
}
|
|
|
|
return list;
|
|
}
|