rizin/librz/flag/zones.c
2024-09-15 19:12:07 +08:00

143 lines
2.8 KiB
C

// SPDX-FileCopyrightText: 2016-2020 pancake <pancake@nopcode.org>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_flag.h>
#include <rz_util.h>
static RzFlagZoneItem *rz_flag_zone_get(RzFlag *f, const char *name) {
RzListIter *iter;
RzFlagZoneItem *zi;
rz_list_foreach (f->zones, iter, zi) {
if (!strcmp(name, zi->name)) {
return zi;
}
}
return NULL;
}
static RzFlagZoneItem *rz_flag_zone_get_inrange(RzFlag *f, ut64 from, ut64 to) {
RzListIter *iter;
RzFlagZoneItem *zi;
rz_list_foreach (f->zones, iter, zi) {
if (RZ_BETWEEN(from, zi->from, to)) {
return zi;
}
}
return NULL;
}
RZ_API bool rz_flag_zone_add(RzFlag *f, const char *name, ut64 addr) {
rz_return_val_if_fail(f && name && *name, false);
RzFlagZoneItem *zi = rz_flag_zone_get(f, name);
if (zi) {
if (addr < zi->from) {
zi->from = addr;
}
if (addr > zi->to) {
zi->to = addr;
}
} else {
if (!f->zones) {
rz_flag_zone_reset(f);
}
zi = RZ_NEW0(RzFlagZoneItem);
zi->name = rz_str_dup(name);
zi->from = zi->to = addr;
rz_list_append(f->zones, zi);
}
return true;
}
RZ_API bool rz_flag_zone_reset(RzFlag *f) {
rz_list_free(f->zones);
f->zones = rz_list_newf(rz_flag_zone_item_free);
return true;
}
RZ_API bool rz_flag_zone_del(RzFlag *f, const char *name) {
RzListIter *iter;
RzFlagZoneItem *zi;
rz_list_foreach (f->zones, iter, zi) {
if (!strcmp(name, zi->name)) {
rz_list_delete(f->zones, iter);
return true;
}
}
return false;
}
RZ_API void rz_flag_zone_item_free(void *a) {
RzFlagZoneItem *zi = a;
free(zi->name);
free(zi);
}
RZ_API bool rz_flag_zone_around(RzFlag *f, ut64 addr, const char **prev, const char **next) {
RzListIter *iter;
RzFlagZoneItem *zi;
*prev = *next = NULL;
ut64 h = UT64_MAX, l = 0LL;
rz_list_foreach (f->zones, iter, zi) {
if (zi->from > addr) {
if (h == UT64_MAX) {
h = zi->from;
*next = zi->name;
} else {
if (zi->from < h) {
h = zi->from;
*next = zi->name;
}
}
}
if (zi->from < addr) {
if (l == UT64_MAX) {
l = zi->from;
*prev = zi->name;
} else {
if (zi->from >= l) {
l = zi->from;
*prev = zi->name;
}
}
}
if (zi->to <= addr) {
if (l == UT64_MAX) {
l = zi->to;
*prev = zi->name;
} else {
if (zi->to >= l) {
l = zi->to;
*prev = zi->name;
}
}
}
if (zi->to > addr) {
if (h == UT64_MAX) {
h = zi->to;
*next = zi->name;
} else {
if (zi->to < h) {
h = zi->to;
*next = zi->name;
}
}
}
}
return true;
}
RZ_API RzList /*<char *>*/ *rz_flag_zone_barlist(RzFlag *f, ut64 from, ut64 bsize, int rows) {
RzList *list = rz_list_newf(NULL);
int i;
for (i = 0; i < rows; i++) {
RzFlagZoneItem *zi = rz_flag_zone_get_inrange(f, from, from + bsize);
if (zi) {
rz_list_append(list, zi->name);
} else {
rz_list_append(list, "");
}
from += bsize;
}
return list;
}