libr/diff/diff.c
author pancake@pair
Sat, 04 Feb 2012 03:51:22 +0100
changeset 2007 ef840cc3d292
parent 1772 9b4af93d5460
permissions -rw-r--r--
* Initial support for the z80 CPU
- assembler, disassembler and basic code analysis
- code analysis is very primitive atm
pancake@372
     1
/* radare - LGPL - Copyright 2009-2010 pancake<nopcode.org> */
youterm@0
     2
youterm@0
     3
#include <r_diff.h>
youterm@0
     4
pancake@485
     5
R_API RDiff *r_diff_new(ut64 off_a, ut64 off_b) {
pancake@819
     6
	RDiff *d = R_NEW (RDiff);
nibble@647
     7
	if (d) {
nibble@647
     8
		d->delta = 1;
nibble@647
     9
		d->user = NULL;
nibble@647
    10
		d->off_a = off_a;
nibble@647
    11
		d->off_b = off_b;
nibble@647
    12
	}
pancake@485
    13
	return d;
pancake@485
    14
}
pancake@485
    15
pancake@485
    16
R_API RDiff *r_diff_free(RDiff *d) {
pancake@485
    17
	free (d);
youterm@0
    18
	return NULL;
youterm@0
    19
}
youterm@0
    20
pancake@485
    21
R_API int r_diff_set_callback(RDiff *d, RDiffCallback callback, void *user) {
youterm@0
    22
	d->callback = callback;
youterm@0
    23
	d->user = user;
youterm@0
    24
	return 1;
youterm@0
    25
}
youterm@0
    26
pancake@485
    27
R_API int r_diff_set_delta(RDiff *d, int delta) {
youterm@0
    28
	d->delta = delta;
youterm@0
    29
	return 1;
youterm@0
    30
}
youterm@0
    31
pancake@485
    32
R_API int r_diff_buffers_static(RDiff *d, const ut8 *a, int la, const ut8 *b, int lb) {
youterm@0
    33
	int i, len;
youterm@0
    34
	int hit = 0;
youterm@0
    35
	la = R_ABS(la);
youterm@0
    36
	lb = R_ABS(lb);
youterm@0
    37
	if (la != lb) {
youterm@0
    38
	 	len = R_MIN(la, lb);
youterm@0
    39
		fprintf(stderr,
youterm@0
    40
			"Buffer truncated to %d bytes (%d not compared)\n",
youterm@0
    41
			len, R_ABS(lb-la));
youterm@0
    42
	} else len = la;
youterm@0
    43
	for(i = 0; i<len; i++) {
youterm@0
    44
		if (a[i]!=b[i]) {
youterm@0
    45
			hit++;
youterm@0
    46
		} else {
youterm@0
    47
			if (hit>0) {
youterm@0
    48
				struct r_diff_op_t o = {
youterm@0
    49
					.a_off = d->off_a+i-hit, .a_buf = a+i-hit, .a_len = hit,
youterm@0
    50
					.b_off = d->off_b+i-hit, .b_buf = b+i-hit, .b_len = hit 
youterm@0
    51
				};
pancake@372
    52
				d->callback (d, d->user, &o);
youterm@0
    53
				hit = 0;
youterm@0
    54
			}
youterm@0
    55
		}
youterm@0
    56
	}
youterm@0
    57
	if (hit>0) {
youterm@0
    58
		struct r_diff_op_t o = {
youterm@0
    59
			.a_off = d->off_a+i-hit, .a_buf = a+i-hit, .a_len = hit,
youterm@0
    60
			.b_off = d->off_b+i-hit, .b_buf = b+i-hit, .b_len = hit 
youterm@0
    61
		};
pancake@372
    62
		d->callback (d, d->user, &o);
youterm@0
    63
		hit = 0;
youterm@0
    64
	}
youterm@0
    65
	return 0;
youterm@0
    66
}
youterm@0
    67
pancake@485
    68
R_API int r_diff_buffers_radiff(RDiff *d, const ut8 *a, int la, const ut8 *b, int lb) {
pancake@372
    69
	char *ptr, *str, buf[64];
youterm@0
    70
	FILE *fd;
youterm@0
    71
	char oop = 0;
pancake@372
    72
	int ret, atl, btl, hit;
pancake@372
    73
	ut8 at[128], bt[128];
nibble@212
    74
	ut64 ooa, oob;
youterm@0
    75
youterm@0
    76
	hit = atl = btl = 0;
youterm@0
    77
	ooa = oob = 0LL;
youterm@0
    78
	oop = -1;
youterm@0
    79
pancake@372
    80
	r_file_dump (".a", a, la);
pancake@372
    81
	r_file_dump (".b", b, lb);
pancake@372
    82
	r_sys_cmd ("radiff -d .a .b | rsc uncolor > .d");
pancake@372
    83
	fd = fopen (".d", "r");
youterm@0
    84
pancake@372
    85
	while (!feof (fd)) {
nibble@212
    86
		ut64 oa, ob; // offset
pancake@1895
    87
		int ba, bb = 0; // byte
youterm@0
    88
		char op; // operation
youterm@0
    89
youterm@0
    90
		oa = ob = 0LL;
pancake@1206
    91
		if (!fgets (buf, 63, fd))
pancake@1206
    92
			break;
pancake@1206
    93
		if (feof (fd))
youterm@0
    94
			break;
youterm@0
    95
		str = buf;
youterm@0
    96
pancake@1206
    97
		ptr = strchr (buf, ' ');
youterm@0
    98
		if (!ptr) continue;
youterm@0
    99
		*ptr='\0';
nopcode@619
   100
		sscanf (str, "0x%08"PFMT64x"", &oa);
youterm@0
   101
pancake@372
   102
		str = r_str_ichr (ptr+1, ' ');
youterm@0
   103
		if (*str!='|'&&*str!='>'&&*str!='<') {
pancake@372
   104
			ptr = strchr (str, ' ');
youterm@0
   105
			if (!ptr) continue;
youterm@0
   106
			*ptr='\0';
pancake@372
   107
			sscanf (str, "%02x", &ba);
youterm@0
   108
		} else ba = 0;
youterm@0
   109
pancake@372
   110
		str = r_str_ichr (ptr+1, ' ');
pancake@372
   111
		ptr = strchr (str, ' ');
youterm@0
   112
		if (!ptr) continue;
youterm@0
   113
		*ptr='\0';
pancake@372
   114
		sscanf (str, "%c", &op);
youterm@0
   115
pancake@372
   116
		str = r_str_ichr (ptr+1, ' ');
pancake@1895
   117
		if (str[0]!='0' || str[1]!='x') {
youterm@0
   118
			ptr = strchr(str, ' ');
youterm@0
   119
			if (!ptr) continue;
pancake@1895
   120
			*ptr = '\0';
pancake@372
   121
			sscanf (str, "%02x", &bb);
youterm@0
   122
		}
youterm@0
   123
youterm@0
   124
		str = ptr+1;
pancake@372
   125
		ptr = strchr (str, '\n');
youterm@0
   126
		if (!ptr) continue;
youterm@0
   127
		*ptr='\0';
nopcode@619
   128
		sscanf (str, "0x%08"PFMT64x"", &ob);
youterm@0
   129
youterm@0
   130
		if (oop == op || oop==-1) {
youterm@0
   131
			if (hit == 0) {
youterm@0
   132
				ooa = oa;
youterm@0
   133
				oob = ob;
youterm@0
   134
			}
pancake@1895
   135
			at[atl] = ba;
pancake@1895
   136
			bt[btl] = bb;
pancake@372
   137
			switch (op) {
youterm@0
   138
			case '|':
youterm@0
   139
				atl++;
youterm@0
   140
				btl++;
youterm@0
   141
				break;
youterm@0
   142
			case '>':
youterm@0
   143
				btl++;
youterm@0
   144
				break;
youterm@0
   145
			case '<':
youterm@0
   146
				atl++;
youterm@0
   147
				break;
youterm@0
   148
			}
youterm@0
   149
			hit++;
youterm@0
   150
		} else {
youterm@0
   151
			if (hit>0) {
youterm@0
   152
				struct r_diff_op_t o = {
youterm@0
   153
					.a_off = ooa, .a_buf = at, .a_len = atl,
youterm@0
   154
					.b_off = oob, .b_buf = bt, .b_len = btl
youterm@0
   155
				};
pancake@372
   156
				ret = d->callback(d, d->user, &o);
pancake@372
   157
					break;
youterm@0
   158
				atl = btl = 0;
youterm@0
   159
				hit = 0;
pancake@372
   160
				if (!ret)
pancake@372
   161
					break;
youterm@0
   162
			}
youterm@0
   163
		}
youterm@0
   164
		oop = op;
youterm@0
   165
	}
youterm@0
   166
	if (hit>0) {
youterm@0
   167
		struct r_diff_op_t o = {
youterm@0
   168
			.a_off = ooa, .a_buf = at, .a_len = atl,
youterm@0
   169
			.b_off = oob, .b_buf = bt, .b_len = btl
youterm@0
   170
		};
pancake@372
   171
		if (!d->callback (d, d->user, &o))
pancake@485
   172
			return 0;
youterm@0
   173
		atl = btl = 0;
youterm@0
   174
		hit = 0;
youterm@0
   175
	}
youterm@0
   176
	fclose(fd);
youterm@0
   177
	unlink(".a");
youterm@0
   178
	unlink(".b");
youterm@0
   179
	unlink(".d");
youterm@0
   180
	return 0;
youterm@0
   181
}
youterm@0
   182
pancake@485
   183
R_API int r_diff_buffers(RDiff *d, const ut8 *a, ut32 la, const ut8 *b, ut32 lb) {
pancake@372
   184
	if (d->delta)
pancake@372
   185
		return r_diff_buffers_delta (d, a, la, b, lb);
pancake@372
   186
	return r_diff_buffers_static (d, a, la, b, lb);
youterm@0
   187
}
nibble@108
   188
pancake@117
   189
/* TODO: Move into r_util maybe? */
pancake@485
   190
R_API int r_diff_buffers_distance(RDiff *d, const ut8 *a, ut32 la, const ut8 *b, ut32 lb,
pancake@485
   191
		ut32 *distance, double *similarity) {
nibble@108
   192
	int i, j, cost, tmin, **m;
nibble@108
   193
pancake@1772
   194
	if (!a || !b || la < 1 || lb < 1)
nibble@108
   195
		return R_FALSE;
nibble@108
   196
nibble@681
   197
	if ((m = malloc ((la+1) * sizeof(int*))) == NULL)
nibble@108
   198
		return R_FALSE;
nibble@108
   199
	for(i = 0; i <= la; i++)
nibble@681
   200
		if ((m[i] = malloc ((lb+1) * sizeof(int))) == NULL)
nibble@108
   201
			return R_FALSE;
nibble@108
   202
nibble@108
   203
	for (i = 0; i <= la; i++)
nibble@108
   204
		m[i][0] = i;
nibble@108
   205
	for (j = 0; j <= lb; j++)
nibble@108
   206
		m[0][j] = j;
nibble@108
   207
nibble@108
   208
	for (i = 1; i <= la; i++) {
nibble@108
   209
		for (j = 1; j <= lb; j++) {
nibble@108
   210
			if (a[i-1] == b[j-1])
nibble@108
   211
				cost = 0;
nibble@108
   212
			else cost = 1;
pancake@485
   213
			tmin = R_MIN (m[i-1][j] + 1, m[i][j-1] + 1);
pancake@485
   214
			m[i][j] = R_MIN (tmin, m[i-1][j-1] + cost);
nibble@108
   215
		}
nibble@108
   216
	}
nibble@108
   217
	
nibble@108
   218
	if (distance != NULL)
nibble@108
   219
		*distance = m[la][lb];
nibble@1132
   220
	if (similarity != NULL) {
nibble@1132
   221
		if (la == 0 || lb == 0)
nibble@1132
   222
			*similarity = 0;
nibble@1132
   223
		else
nibble@1132
   224
			*similarity = (double)1 - (double)(m[la][lb])/(double)(R_MAX(la, lb));
nibble@1132
   225
	}
nibble@108
   226
pancake@372
   227
	for(i = 0; i <= la; i++)
pancake@372
   228
		free (m[i]);
pancake@372
   229
	free (m);
pancake@372
   230
nibble@108
   231
	return R_TRUE;
nibble@108
   232
}