66 #define NUM2PTR(x) ((void *)(intptr_t)(x))
67 #define PTR2NUM(x) ((intptr_t)(void *)(x))
157 const void *elem = elem_at(diff->
b,
i);
158 if (ignore && ignore(elem)) {
173 RZ_LOG_ERROR(
"rz_diff_set_b: cannot append index to list\n");
201 if (!
set_a(diff,
a, a_size)) {
205 if (!
set_b(diff,
b, b_size)) {
229 if (!a_lines || !b_lines) {
260 rz_return_val_if_fail(
a &&
b && methods && methods->elem_at && methods->elem_hash && methods->compare && methods->stringify,
NULL);
273 if (methods->ignore) {
279 if (!
set_a(diff,
a, a_size)) {
283 if (!
set_b(diff,
b, b_size)) {
299 if (diff->methods.free) {
300 diff->methods.free(diff->a);
301 diff->methods.free(diff->b);
303 ht_pp_free(diff->b_hits);
333 block->
a_low = a_low;
335 block->
b_low = b_low;
362 HtUU *len_map =
NULL;
364 const ut8 *
a = diff->
a;
365 const ut8 *
b = diff->
b;
366 const void *elem_a =
NULL;
367 const void *elem_b =
NULL;
381 len_map = ht_uu_new0();
383 RZ_LOG_ERROR(
"find_longest_match: cannot allocate len_map\n");
384 goto find_longest_match_fail;
387 for (
ut32 a_pos = a_low; a_pos < a_hi; ++a_pos) {
388 elem_a = elem_at(
a, a_pos);
391 RZ_LOG_ERROR(
"find_longest_match: cannot allocate tmp\n");
392 goto find_longest_match_fail;
396 rz_list_foreach (
list, it, pnum) {
400 }
else if (b_pos >= b_hi) {
403 ut32 len = ht_uu_find(len_map, b_pos - 1,
NULL) + 1;
404 ht_uu_insert(
tmp, b_pos,
len);
405 if (
len > hit_size) {
406 hit_a = a_pos -
len + 1;
407 hit_b = b_pos -
len + 1;
418 while (hit_a > a_low && hit_b > b_low) {
419 elem_a = elem_at(
a, hit_a - 1);
420 elem_b = elem_at(
b, hit_b - 1);
421 if (ignore(elem_b) ||
compare(elem_a, elem_b)) {
429 while (hit_a + hit_size < a_hi && hit_b + hit_size < b_hi) {
430 elem_a = elem_at(
a, hit_a + hit_size);
431 elem_b = elem_at(
b, hit_b + hit_size);
432 if (ignore(elem_b) ||
compare(elem_a, elem_b)) {
439 while (hit_a > a_low && hit_b > b_low) {
440 elem_a = elem_at(
a, hit_a - 1);
441 elem_b = elem_at(
b, hit_b - 1);
442 if (!ignore(elem_b) ||
compare(elem_a, elem_b)) {
450 while (hit_a + hit_size < a_hi && hit_b + hit_size < b_hi) {
451 elem_a = elem_at(
a, hit_a + hit_size);
452 elem_b = elem_at(
b, hit_b + hit_size);
453 if (!ignore(elem_b) ||
compare(elem_a, elem_b)) {
461 RZ_LOG_ERROR(
"find_longest_match: cannot allocate RzDiffMatch\n");
462 goto find_longest_match_fail;
468 find_longest_match_fail:
477 }
else if (m0->
a < m1->
a) {
479 }
else if (m0->
b > m1->
b) {
481 }
else if (m0->
b < m1->
b) {
505 ut32 adj_a = 0, adj_b = 0, adj_size = 0;
509 RZ_LOG_ERROR(
"rz_diff_matches_new: cannot allocate matches\n");
510 goto rz_diff_matches_new_fail;
514 RZ_LOG_ERROR(
"rz_diff_matches_new: cannot allocate non_adjacent\n");
515 goto rz_diff_matches_new_fail;
520 RZ_LOG_ERROR(
"rz_diff_matches_new: cannot allocate stack\n");
521 goto rz_diff_matches_new_fail;
525 RZ_LOG_ERROR(
"rz_diff_matches_new: cannot append initial block "
527 goto rz_diff_matches_new_fail;
537 if (
match->size > 0) {
539 RZ_LOG_ERROR(
"rz_diff_matches_new: cannot append match into matches\n");
541 goto rz_diff_matches_new_fail;
545 RZ_LOG_ERROR(
"rz_diff_matches_new: cannot append low block into stack\n");
546 goto rz_diff_matches_new_fail;
551 RZ_LOG_ERROR(
"rz_diff_matches_new: cannot append high block into stack\n");
552 goto rz_diff_matches_new_fail;
565 rz_list_foreach (matches, it,
match) {
566 if ((adj_a + adj_size) ==
match->a && (adj_b + adj_size) ==
match->b) {
567 adj_size +=
match->size;
571 RZ_LOG_ERROR(
"rz_diff_matches_new: cannot append match into non_adjacent\n");
573 goto rz_diff_matches_new_fail;
577 adj_size =
match->size;
582 RZ_LOG_ERROR(
"rz_diff_matches_new: cannot append match into non_adjacent\n");
584 goto rz_diff_matches_new_fail;
589 RZ_LOG_ERROR(
"rz_diff_matches_new: cannot append match into non_adjacent\n");
591 goto rz_diff_matches_new_fail;
598 rz_diff_matches_new_fail:
643 goto rz_diff_opcodes_new_fail;
648 RZ_LOG_ERROR(
"rz_diff_opcodes_new: cannot allocate opcodes\n");
649 goto rz_diff_opcodes_new_fail;
654 rz_list_foreach (matches, it,
match) {
657 if (a < match->
a && b < match->
b) {
659 }
else if (a < match->
a) {
661 }
else if (b < match->
b) {
668 RZ_LOG_ERROR(
"rz_diff_opcodes_new: cannot allocate op\n");
669 goto rz_diff_opcodes_new_fail;
671 RZ_LOG_ERROR(
"rz_diff_opcodes_new: cannot append op into opcodes\n");
673 goto rz_diff_opcodes_new_fail;
679 if (
match->size > 0) {
682 RZ_LOG_ERROR(
"rz_diff_opcodes_new: cannot allocate op\n");
683 goto rz_diff_opcodes_new_fail;
685 RZ_LOG_ERROR(
"rz_diff_opcodes_new: cannot append op into opcodes\n");
687 goto rz_diff_opcodes_new_fail;
695 rz_diff_opcodes_new_fail:
719 st32 a_beg = 0, b_beg = 0, max_groups = 0;
721 max_groups = n_groups << 1;
725 RZ_LOG_ERROR(
"rz_diff_opcodes_grouped_new: cannot allocate groups\n");
726 goto rz_diff_opcodes_grouped_new_fail;
731 goto rz_diff_opcodes_grouped_new_fail;
737 RZ_LOG_ERROR(
"rz_diff_opcodes_grouped_new: cannot allocate op for opcodes\n");
738 goto rz_diff_opcodes_grouped_new_fail;
740 RZ_LOG_ERROR(
"rz_diff_opcodes_grouped_new: cannot append op into opcodes\n");
742 goto rz_diff_opcodes_grouped_new_fail;
758 RZ_LOG_ERROR(
"rz_diff_opcodes_grouped_new: cannot allocate group\n");
759 goto rz_diff_opcodes_grouped_new_fail;
770 RZ_LOG_ERROR(
"rz_diff_opcodes_grouped_new: cannot allocate op for group\n");
771 goto rz_diff_opcodes_grouped_new_fail;
773 RZ_LOG_ERROR(
"rz_diff_opcodes_grouped_new: cannot append op into group\n");
775 goto rz_diff_opcodes_grouped_new_fail;
777 RZ_LOG_ERROR(
"rz_diff_opcodes_grouped_new: cannot append group into groups\n");
779 goto rz_diff_opcodes_grouped_new_fail;
784 RZ_LOG_ERROR(
"rz_diff_opcodes_grouped_new: cannot allocate new group\n");
785 goto rz_diff_opcodes_grouped_new_fail;
787 a_beg =
RZ_MAX(a_beg,
op->a_end - n_groups);
788 b_beg =
RZ_MAX(b_beg,
op->b_end - n_groups);
794 RZ_LOG_ERROR(
"rz_diff_opcodes_grouped_new: cannot allocate op for group\n");
795 goto rz_diff_opcodes_grouped_new_fail;
797 RZ_LOG_ERROR(
"rz_diff_opcodes_grouped_new: cannot append op into group\n");
800 goto rz_diff_opcodes_grouped_new_fail;
807 RZ_LOG_ERROR(
"rz_diff_opcodes_grouped_new: cannot append group into groups\n");
809 goto rz_diff_opcodes_grouped_new_fail;
818 rz_diff_opcodes_grouped_new_fail:
842 rz_list_foreach (matches, it,
match) {
848 double d_hits = hits;
849 double d_size = diff->a_size + diff->b_size;
851 *result = (2.0 * d_hits) / d_size;
869 double d_hits =
RZ_MIN(diff->a_size, diff->b_size);
870 double d_size = diff->a_size + diff->b_size;
872 *result = (2.0 * d_hits) / d_size;
static const MethodsInternal methods_bytes
static int cmp_matches(RzDiffMatch *m0, RzDiffMatch *m1)
static bool set_b(RzDiff *diff, const void *b, ut32 b_size)
static void opcode_set(RzDiffOp *op, RzDiffOpType type, st32 a_beg, st32 a_end, st32 b_beg, st32 b_end)
RZ_API RZ_OWN RzDiff * rz_diff_generic_new(RZ_BORROW const void *a, ut32 a_size, RZ_BORROW const void *b, ut32 b_size, RZ_NONNULL RzDiffMethods *methods)
Returns the structure needed to diff arrays of user defined types.
RZ_API RZ_BORROW const void * rz_diff_get_b(RZ_NONNULL RzDiff *diff)
returns the pointer of the B array that passed to rz_diff_XXX_new()
RZ_API RZ_OWN RzList * rz_diff_opcodes_new(RZ_NONNULL RzDiff *diff)
Generates a list of steps needed to go from A to B.
static RzDiffMatch * match_new(ut32 a, ut32 b, ut32 size)
RZ_API ut32 rz_diff_hash_data(RZ_NULLABLE const ut8 *buffer, ut32 size)
Calculates the hash of any given data.
RZ_API RZ_BORROW const void * rz_diff_get_a(RZ_NONNULL RzDiff *diff)
returns the pointer of the A array that passed to rz_diff_XXX_new()
static bool stack_append_block(RzList *stack, ut32 a_low, ut32 a_hi, ut32 b_low, ut32 b_hi)
static void group_op_free(RzList *ops)
RZ_API RZ_OWN RzList * rz_diff_matches_new(RZ_NONNULL RzDiff *diff)
generates a list of matching blocks
static ut32 default_ksize(const void *a)
static bool fake_ignore(const void *value)
struct methods_internal_t MethodsInternal
RZ_API bool rz_diff_sizes_ratio(RZ_NONNULL RzDiff *diff, RZ_NONNULL double *result)
Calculates the size ratio between A and B.
static RzDiffMatch * find_longest_match(RzDiff *diff, Block *block)
void(* RzDiffMethodFree)(const void *array)
RZ_API bool rz_diff_ratio(RZ_NONNULL RzDiff *diff, RZ_NONNULL double *result)
Calculates the similarity ratio between A and B.
RZ_API RZ_OWN RzDiff * rz_diff_lines_new(RZ_BORROW const char *a, RZ_BORROW const char *b, RZ_NULLABLE RzDiffIgnoreLine ignore)
Returns the structure needed to diff lines.
static RzDiffOp * opcode_new(RzDiffOpType type, st32 a_beg, st32 a_end, st32 b_beg, st32 b_end)
RZ_API RZ_OWN RzDiff * rz_diff_bytes_new(RZ_BORROW const ut8 *a, ut32 a_size, RZ_BORROW const ut8 *b, ut32 b_size, RZ_NULLABLE RzDiffIgnoreByte ignore)
Returns the structure needed to diff buffers of ut8.
static void free_hits(HtPPKv *kv)
RZ_API RZ_OWN RzList * rz_diff_opcodes_grouped_new(RZ_NONNULL RzDiff *diff, ut32 n_groups)
Generates groups of opcodes needed to go from A to B.
static bool set_a(RzDiff *diff, const void *a, ut32 a_size)
RZ_API void rz_diff_free(RZ_NULLABLE RzDiff *diff)
frees the diff structure
unsigned char match[65280+2]
RZ_API void Ht_() free(HtName_(Ht) *ht)
static int compare(const char *s1, const char *s2, int l1, int l2)
static void list(RzEgg *egg)
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
RZ_API RZ_OWN void * rz_list_pop(RZ_NONNULL RzList *list)
Removes and returns the last element of the list.
RZ_API void rz_list_sort(RZ_NONNULL RzList *list, RZ_NONNULL RzListComparator cmp)
Sorts via merge sort or via insertion sort a list.
RZ_API RZ_BORROW void * rz_list_first(RZ_NONNULL const RzList *list)
Returns the first element of the list.
RZ_API RZ_BORROW void * rz_list_last(RZ_NONNULL const RzList *list)
Returns the last element of the list.
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
static const MethodsInternal methods_lines
static RzList * tokenize_lines(const char *string)
#define rz_return_val_if_fail(expr, val)
const void *(* RzDiffMethodElemAt)(RZ_BORROW const void *array, ut32 index)
ut32(* RzDiffMethodElemHash)(RZ_BORROW const void *elem)
bool(* RzDiffMethodIgnore)(RZ_BORROW const void *elem)
bool(* RzDiffIgnoreLine)(RZ_BORROW const char *line)
void(* RzDiffMethodStringify)(RZ_BORROW const void *elem, RZ_BORROW RzStrBuf *sb)
int(* RzDiffMethodCompare)(RZ_BORROW const void *a_elem, RZ_BORROW const void *b_elem)
bool(* RzDiffIgnoreByte)(const ut64 byte)
enum rz_diff_op_type_t RzDiffOpType
void(* RzListFree)(void *ptr)
int(* RzListComparator)(const void *value, const void *list_data)
#define RZ_LOG_ERROR(fmtstr,...)
RzDiffMethodIgnore ignore
RzDiffMethodElemAt elem_at
RzDiffMethodStringify stringify
RzDiffMethodElemHash elem_hash
RzDiffMethodCompare compare
ut64(WINAPI *w32_GetEnabledXStateFeatures)()