|
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 |
} |