range: Introduce range_inverse_array()
This helper reverses a list of regions within a [low, high] span, turning original regions into holes and original holes into actual regions, covering the whole UINT64_MAX span. Signed-off-by: Eric Auger <eric.auger@redhat.com> Tested-by: Yanghang Liu <yanghliu@redhat.com> Reviewed-by: "Michael S. Tsirkin" <mst@redhat.com> Signed-off-by: Cédric Le Goater <clg@redhat.com>
This commit is contained in:
		
				
					committed by
					
						 Cédric Le Goater
						Cédric Le Goater
					
				
			
			
				
	
			
			
			
						parent
						
							908cae0de4
						
					
				
				
					commit
					b439595a08
				
			| @@ -225,4 +225,12 @@ int range_compare(Range *a, Range *b); | ||||
|  | ||||
| GList *range_list_insert(GList *list, Range *data); | ||||
|  | ||||
| /* | ||||
|  * Inverse an array of sorted ranges over the [low, high] span, ie. | ||||
|  * original ranges becomes holes in the newly allocated inv_ranges | ||||
|  */ | ||||
| void range_inverse_array(GList *in_ranges, | ||||
|                          GList **out_ranges, | ||||
|                          uint64_t low, uint64_t high); | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										55
									
								
								util/range.c
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								util/range.c
									
									
									
									
									
								
							| @@ -66,3 +66,58 @@ GList *range_list_insert(GList *list, Range *data) | ||||
|  | ||||
|     return list; | ||||
| } | ||||
|  | ||||
| static inline | ||||
| GList *append_new_range(GList *list, uint64_t lob, uint64_t upb) | ||||
| { | ||||
|     Range *new = g_new0(Range, 1); | ||||
|  | ||||
|     range_set_bounds(new, lob, upb); | ||||
|     return g_list_append(list, new); | ||||
| } | ||||
|  | ||||
|  | ||||
| void range_inverse_array(GList *in, GList **rev, | ||||
|                          uint64_t low, uint64_t high) | ||||
| { | ||||
|     Range *r, *rn; | ||||
|     GList *l = in, *out = *rev; | ||||
|  | ||||
|     for (l = in; l && range_upb(l->data) < low; l = l->next) { | ||||
|         continue; | ||||
|     } | ||||
|  | ||||
|     if (!l) { | ||||
|         out = append_new_range(out, low, high); | ||||
|         goto exit; | ||||
|     } | ||||
|     r = (Range *)l->data; | ||||
|  | ||||
|     /* first range lob is greater than min, insert a first range */ | ||||
|     if (range_lob(r) > low) { | ||||
|         out = append_new_range(out, low, MIN(range_lob(r) - 1, high)); | ||||
|     } | ||||
|  | ||||
|     /* insert a range inbetween each original range until we reach high */ | ||||
|     for (; l->next; l = l->next) { | ||||
|         r = (Range *)l->data; | ||||
|         rn = (Range *)l->next->data; | ||||
|         if (range_lob(r) >= high) { | ||||
|             goto exit; | ||||
|         } | ||||
|         if (range_compare(r, rn)) { | ||||
|             out = append_new_range(out, range_upb(r) + 1, | ||||
|                                    MIN(range_lob(rn) - 1, high)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* last range */ | ||||
|     r = (Range *)l->data; | ||||
|  | ||||
|     /* last range upb is less than max, insert a last range */ | ||||
|     if (range_upb(r) <  high) { | ||||
|         out = append_new_range(out, range_upb(r) + 1, high); | ||||
|     } | ||||
| exit: | ||||
|     *rev = out; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user