| /* Copyright (c) 2015 Google Inc |
| * Davide Libenzi <dlibenzi@google.com> |
| * See LICENSE for details. |
| */ |
| |
| #include <ros/errno.h> |
| #include <sys/types.h> |
| #include <stdio.h> |
| #include <sort.h> |
| #include <address_range.h> |
| |
| static int address_range_cmp(const void *f1, const void *f2) |
| { |
| return ((const struct address_range *) f1)->start < |
| ((const struct address_range *) f2)->start ? -1 : 1; |
| } |
| |
| int address_range_validate(const struct address_range *ars, size_t count) |
| { |
| for (size_t i = 0; i < count; i++) { |
| if (ars[i].start > ars[i].end) |
| return -EINVAL; |
| if ((i > 0) && (ars[i - 1].end >= ars[i].start)) |
| return -EINVAL; |
| } |
| |
| return 0; |
| } |
| |
| int address_range_init(struct address_range *ars, size_t count) |
| { |
| sort(ars, count, sizeof(*ars), address_range_cmp); |
| |
| return address_range_validate(ars, count); |
| } |
| |
| const struct address_range *address_range_find(const struct address_range *ars, |
| size_t count, uintptr_t addr) |
| { |
| ssize_t l = 0, r = count - 1; |
| |
| while (l <= r) { |
| ssize_t x = l + (r - l) / 2; |
| const struct address_range *car = ars + x; |
| |
| if (car->end < addr) |
| l = x + 1; |
| else if (car->start > addr) |
| r = x - 1; |
| else |
| return car; |
| } |
| |
| return NULL; |
| } |