static inline void _heap_up(RBinHeap *h, size_t i, void *x) { size_t j; for (; i && (j = (i-1) >> 1, h->cmp (x, r_pvector_at (&h->a, j)) < 0); i = j) { r_pvector_set (&h->a, i, r_pvector_at (&h->a, j)); } r_pvector_set (&h->a, i, x); }
static inline void _heap_down(RBinHeap *h, size_t i, void *x) { size_t j; for (; j = i * 2 + 1, j < h->a.v.len; i = j) { if (j + 1 < h->a.v.len && h->cmp (r_pvector_at (&h->a, j+1), r_pvector_at (&h->a, j)) < 0) { j++; } if (h->cmp (r_pvector_at (&h->a, j), x) >= 0) { break; } r_pvector_set (&h->a, i, r_pvector_at (&h->a, j)); } r_pvector_set (&h->a, i, x); }
R_API void *r_pvector_pop_front(RPVector *vec) { void *r = r_pvector_at (vec, 0); r_vector_pop_front (&vec->v, NULL); return r; }
R_API void *r_pvector_pop(RPVector *vec) { void *r = r_pvector_at (vec, vec->v.len - 1); r_vector_pop (&vec->v, NULL); return r; }
R_API void *r_pvector_remove_at(RPVector *vec, size_t index) { void *r = r_pvector_at (vec, index); r_vector_remove_at (&vec->v, index, NULL); return r; }
// If prefix_mode is true, returns the number of bytes of operated prefix; returns < 0 on error. // If prefix_mode is false, operates in non-stop mode and returns true iff all IO operations on overlapped maps are complete. static st64 on_map_skyline(RIO *io, ut64 vaddr, ut8 *buf, int len, int match_flg, cbOnIterMap op, bool prefix_mode) { const RPVector *skyline = &io->map_skyline; ut64 addr = vaddr; size_t i; bool ret = true, wrap = !prefix_mode && vaddr + len < vaddr; #define CMP(addr, part) (addr < r_itv_end (((RIOMapSkyline *)part)->itv) - 1 ? -1 : \ addr > r_itv_end (((RIOMapSkyline *)part)->itv) - 1 ? 1 : 0) // Let i be the first skyline part whose right endpoint > addr if (!len) { i = r_pvector_len (skyline); } else { r_pvector_lower_bound (skyline, addr, i, CMP); if (i == r_pvector_len (skyline) && wrap) { wrap = false; i = 0; addr = 0; } } #undef CMP while (i < r_pvector_len (skyline)) { const RIOMapSkyline *part = r_pvector_at (skyline, i); // Right endpoint <= addr if (r_itv_end (part->itv) - 1 < addr) { i++; if (wrap && i == r_pvector_len (skyline)) { wrap = false; i = 0; addr = 0; } continue; } if (addr < part->itv.addr) { // [addr, part->itv.addr) is a gap if (prefix_mode || len <= part->itv.addr - vaddr) { break; } addr = part->itv.addr; } // Now left endpoint <= addr < right endpoint ut64 len1 = R_MIN (vaddr + len - addr, r_itv_end (part->itv) - addr); // The map satisfies the permission requirement or p_cache is enabled if (((part->map->flags & match_flg) == match_flg || io->p_cache)) { st64 result = op (io, part->map->fd, part->map->delta + addr - part->map->itv.addr, buf + addr - vaddr, len1, part->map, NULL); if (prefix_mode) { if (result < 0) { return result; } addr += result; if (result != len1) { break; } } else { if (result != len1) { ret = false; } addr += len1; } } else if (prefix_mode) { break; } else { addr += len1; ret = false; } // Reaches the end if (addr == vaddr + len) { break; } // Wrap to the beginning of skyline if address wraps if (!addr) { i = 0; } } return prefix_mode ? addr - vaddr : ret; }
R_API void *r_binheap_pop(RBinHeap *h) { void *ret = r_pvector_at (&h->a, 0); h->a.v.len--; _heap_down (h, 0, r_pvector_at (&h->a, h->a.v.len)); return ret; }