summaryrefslogtreecommitdiff
path: root/util/range.c
AgeCommit message (Collapse)Author
2016-07-04range: Replace internal representation of RangeMarkus Armbruster
Range represents a range as follows. Member @start is the inclusive lower bound, member @end is the exclusive upper bound. Zero @end is special: if @start is also zero, the range is empty, else @end is to be interpreted as 2^64. No other empty ranges may occur. The range [0,2^64-1] cannot be represented. If you try to create it with range_set_bounds1(), you get the empty range instead. If you try to create it with range_set_bounds() or range_extend(), assertions fail. Before range_set_bounds() existed, the open-coded creation usually got you the empty range instead. Open deathtrap. Moreover, the code dealing with the janus-faced @end is too clever by half. Dumb this down to a more pedestrian representation: members @lob and @upb are inclusive lower and upper bounds. The empty range is encoded as @lob = 1, @upb = 0. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2016-07-04range: Eliminate direct Range member accessMarkus Armbruster
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. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2016-06-30qapi: Fix memleak in string visitors on int listsEric Blake
Commit 7f8f9ef1 introduced the ability to store a list of integers as a sorted list of ranges, but when merging ranges, it leaks one or more ranges. It was also using range_get_last() incorrectly within range_compare() (a range is a start/end pair, but range_get_last() is for start/len pairs), and will also mishandle a range ending in UINT64_MAX (remember, we document that no range covers 2**64 bytes, but that ranges that end on UINT64_MAX have end < begin). The whole merge algorithm was rather complex, and included unnecessary passes over data within glib functions, and enough indirection to make it hard to easily plug the data leaks. Since we are already hard-coding things to a list of ranges, just rewrite the thing to open-code the traversal and comparisons, by making the range_compare() helper function give us an answer that is easier to use, at which point we avoid the need to pass any callbacks to g_list_*(). Then by reusing range_extend() instead of duplicating effort with range_merge(), we cover the corner cases correctly. Drop the now-unused range_merge() and ranges_can_merge(). Doing this lets test-string-{input,output}-visitor pass under valgrind without leaks. Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1464712890-14262-4-git-send-email-eblake@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> [Comment hoisted out of loop] Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-06-30qapi: Simplify use of range.hEric Blake
Calling our function g_list_insert_sorted_merged is a misnomer, since we are NOT writing a glib function. Furthermore, we are making every caller pass the same comparator function of range_merge(): any caller that would try otherwise would break in weird ways since our internal call to ranges_can_merge() is hard-coded to operate only on ranges, rather than paying attention to the caller's comparator. Better is to fix things so that callers don't have to care about our internal comparator, by picking a function name and updating the parameter type away from a gratuitous use of void*, to make it obvious that we are operating specifically on a list of ranges and not a generic list. Plus, refactoring the code here will make it easier to plug a memory leak in the next patch. range_compare() is now internal only, and moves to the .c file. Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1464712890-14262-3-git-send-email-eblake@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-06-30range: Create range.c for code that should not be inlineEric Blake
g_list_insert_sorted_merged() is rather large to be an inline function; move it to its own file. range_merge() and ranges_can_merge() can likewise move, as they are only used internally. Also, it becomes obvious that the condition within range_merge() is already satisfied by its caller, and that the return value is not used. The diffstat is misleading, because of the copyright boilerplate. Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1464712890-14262-2-git-send-email-eblake@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>