Merge lp:~charlesk/indicator-appmenu/remove-dead-file into lp:indicator-appmenu/0.4
- remove-dead-file
- Merge into trunk.0.4
Proposed by
Charles Kerr
Status: | Merged |
---|---|
Approved by: | Charles Kerr |
Approved revision: | 199 |
Merged at revision: | 199 |
Proposed branch: | lp:~charlesk/indicator-appmenu/remove-dead-file |
Merge into: | lp:indicator-appmenu/0.4 |
Diff against target: |
416 lines (+0/-412) 1 file modified
src/distance.c.THIS (+0/-412) |
To merge this branch: | bzr merge lp:~charlesk/indicator-appmenu/remove-dead-file |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Sebastien Bacher | Approve | ||
Review via email: mp+100807@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Sebastien Bacher (seb128) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === removed file 'src/distance.c.THIS' |
2 | --- src/distance.c.THIS 2012-04-03 20:31:54 +0000 |
3 | +++ src/distance.c.THIS 1970-01-01 00:00:00 +0000 |
4 | @@ -1,412 +0,0 @@ |
5 | -/* |
6 | -Functions to calculate the distance between two strings. |
7 | - |
8 | -Copyright 2011 Canonical Ltd. |
9 | - |
10 | -Authors: |
11 | - Ted Gould <ted@canonical.com> |
12 | - |
13 | -This program is free software: you can redistribute it and/or modify it |
14 | -under the terms of the GNU General Public License version 3, as published |
15 | -by the Free Software Foundation. |
16 | - |
17 | -This program is distributed in the hope that it will be useful, but |
18 | -WITHOUT ANY WARRANTY; without even the implied warranties of |
19 | -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
20 | -PURPOSE. See the GNU General Public License for more details. |
21 | - |
22 | -You should have received a copy of the GNU General Public License along |
23 | -with this program. If not, see <http://www.gnu.org/licenses/>. |
24 | -*/ |
25 | - |
26 | -#include "distance.h" |
27 | - |
28 | -#include <glib-object.h> |
29 | -#include <glib/gprintf.h> |
30 | -#include <glib/gi18n.h> |
31 | -#include <gio/gio.h> |
32 | - |
33 | -#include "hudsettings.h" |
34 | - |
35 | -#define ADD_PENALTY hud_settings.add_penalty |
36 | -#define PRE_ADD_PENALTY hud_settings.add_penalty_pre |
37 | -#define DROP_PENALTY hud_settings.drop_penalty |
38 | -#define END_DROP_PENALTY hud_settings.drop_penalty_end |
39 | -#define TRANSPOSE_PENALTY hud_settings.transpose_penalty |
40 | -#define SWAP_PENALTY hud_settings.swap_penalty |
41 | -#define SWAP_CASE_PENALTY hud_settings.swap_penalty_case |
42 | - |
43 | -/* Figure out how far off we are from a set of characters, basically |
44 | - whether they match or not */ |
45 | -static guint |
46 | -swap_cost (gunichar a, gunichar b) |
47 | -{ |
48 | - if (a == b) |
49 | - return 0; |
50 | - if (g_unichar_toupper(a) == g_unichar_toupper(b)) |
51 | - return SWAP_CASE_PENALTY; /* Some penalty, but close */ |
52 | - return SWAP_PENALTY; |
53 | -} |
54 | - |
55 | -#define MATRIX_VAL(needle_loc, haystack_loc) (penalty_matrix[(needle_loc + 1) + (haystack_loc + 1) * (len_needle + 1)]) |
56 | - |
57 | -/* A function to print out the matrix for debugging purposes. It is |
58 | - mostly used in the test suite, though it could be used else where if |
59 | - needed */ |
60 | -static void |
61 | -dumpmatrix (const gchar * needle, guint len_needle, const gchar * haystack, guint len_haystack, guint * penalty_matrix) |
62 | -{ |
63 | -#ifndef DUMP_MATRIX |
64 | - return; |
65 | -#endif |
66 | - gint i, j; |
67 | - |
68 | - g_printf("\n"); |
69 | - /* Character Column */ |
70 | - g_printf(" "); |
71 | - /* Base val column */ |
72 | - g_printf(" "); |
73 | - for (i = 0; i < len_needle; i++) { |
74 | - g_printf("%c ", needle[i]); |
75 | - } |
76 | - g_printf("\n"); |
77 | - |
78 | - /* Character Column */ |
79 | - g_printf(" "); |
80 | - for (i = -1; i < (gint)len_needle; i++) { |
81 | - g_printf("%u ", MATRIX_VAL(i, -1)); |
82 | - } |
83 | - g_printf("\n"); |
84 | - |
85 | - for (j = 0; j < len_haystack; j++) { |
86 | - g_printf("%c ", haystack[j]); |
87 | - for (i = -1; i < (gint)len_needle; i++) { |
88 | - g_printf("%u ", MATRIX_VAL(i, j)); |
89 | - } |
90 | - g_printf("\n"); |
91 | - } |
92 | - g_printf("\n"); |
93 | - |
94 | - return; |
95 | -} |
96 | - |
97 | -/* Looks at two individual tokens, builds a matrix and calculates the |
98 | - distance between them by moving through the matrix. |
99 | - If you believe, you can see the matrix, otherwise it looks just like |
100 | - an array. */ |
101 | -static guint |
102 | -calculate_token_distance (const gchar * needle, const gchar * haystack) |
103 | -{ |
104 | - // g_debug("Comparing token '%s' to token '%s'", needle, haystack); |
105 | - |
106 | - guint len_needle = 0; |
107 | - guint len_haystack = 0; |
108 | - |
109 | - if (needle != NULL) { |
110 | - len_needle = g_utf8_strlen(needle, -1); |
111 | - } |
112 | - |
113 | - if (haystack != NULL) { |
114 | - len_haystack = g_utf8_strlen(haystack, -1); |
115 | - } |
116 | - |
117 | - /* Handle the cases of very short or NULL strings quickly */ |
118 | - if (len_needle == 0) { |
119 | - return DROP_PENALTY * len_haystack; |
120 | - } |
121 | - |
122 | - if (len_haystack == 0) { |
123 | - return ADD_PENALTY * len_needle; |
124 | - } |
125 | - |
126 | - /* Allocate the matrix of penalties */ |
127 | - guint * penalty_matrix = g_malloc0(sizeof(guint) * (len_needle + 1) * (len_haystack + 1)); |
128 | - gint len_difference; |
129 | - gint penalty; |
130 | - int i; |
131 | - |
132 | - /* Take the first row and first column and make them additional letter penalties */ |
133 | - penalty = 0; |
134 | - for (i = 0; i < len_needle + 1; i++) { |
135 | - MATRIX_VAL(i - 1, -1) = penalty; |
136 | - penalty += ADD_PENALTY; |
137 | - } |
138 | - |
139 | - len_difference = len_haystack - len_needle; |
140 | - penalty = 0; |
141 | - for (i = 0; i < len_difference; i++) { |
142 | - MATRIX_VAL(-1, i - 1) = penalty; |
143 | - penalty += PRE_ADD_PENALTY; |
144 | - } |
145 | - for (; i < len_haystack + 1; i++) { |
146 | - MATRIX_VAL(-1, i - 1) = penalty; |
147 | - penalty += DROP_PENALTY; |
148 | - } |
149 | - |
150 | - /* Now go through the matrix building up the penalties */ |
151 | - int ineedle, ihaystack; |
152 | - gchar * needle_head, * haystack_head; |
153 | - for (needle_head = (gchar *)needle, ineedle = 0; |
154 | - needle_head[0] != '\0'; |
155 | - needle_head = g_utf8_next_char(needle_head), ineedle++) { |
156 | - for (haystack_head = (gchar *)haystack, ihaystack = 0; |
157 | - haystack_head[0] != '\0'; |
158 | - haystack_head = g_utf8_next_char(haystack_head), ihaystack++) { |
159 | - gunichar needle_let = g_utf8_get_char(needle_head); |
160 | - gunichar haystack_let = g_utf8_get_char(haystack_head); |
161 | - |
162 | - guint subst_pen = MATRIX_VAL(ineedle - 1, ihaystack - 1) + swap_cost(needle_let, haystack_let); |
163 | - guint drop_pen = MATRIX_VAL(ineedle - 1, ihaystack); |
164 | - if (ineedle < ihaystack) { |
165 | - drop_pen += DROP_PENALTY; |
166 | - } else { |
167 | - drop_pen += END_DROP_PENALTY; |
168 | - } |
169 | - |
170 | - guint add_pen = MATRIX_VAL(ineedle, ihaystack - 1); |
171 | - if (len_haystack - len_needle - ineedle > 0) { |
172 | - add_pen += PRE_ADD_PENALTY; |
173 | - } else { |
174 | - add_pen += ADD_PENALTY; |
175 | - } |
176 | - guint transpose_pen = drop_pen + 1; /* ensures won't be chosen */ |
177 | - |
178 | - if (ineedle > 0 && ihaystack > 0 && needle_let == haystack[ihaystack - 1] && haystack_let == needle[ineedle - 1]) { |
179 | - transpose_pen = MATRIX_VAL(ineedle - 2, ihaystack - 2) + TRANSPOSE_PENALTY; |
180 | - } |
181 | - |
182 | - MATRIX_VAL(ineedle, ihaystack) = MIN(MIN(subst_pen, drop_pen), MIN(add_pen, transpose_pen)); |
183 | - } |
184 | - } |
185 | - |
186 | - dumpmatrix(needle, len_needle, haystack, len_haystack, penalty_matrix); |
187 | - |
188 | - guint retval = penalty_matrix[(len_needle + 1) * (len_haystack + 1) - 1]; |
189 | - g_free(penalty_matrix); |
190 | - |
191 | - return retval; |
192 | -} |
193 | - |
194 | -/* Looks through the array of paths and tries to find a minimum path |
195 | - looking up from the needle specified. This way we can look through |
196 | - all the possible paths */ |
197 | -guint |
198 | -minimize_distance_recurse (guint needle, guint num_needles, guint haystack, guint num_haystacks, guint * distances, guint * matches) |
199 | -{ |
200 | - gint i; |
201 | - |
202 | - /* Put where we are in the array so that we don't forget */ |
203 | - matches[needle] = haystack; |
204 | - |
205 | - /* First check to see if we've already used this entry */ |
206 | - for (i = needle - 1; i >= 0; i--) { |
207 | - if (matches[i] == haystack) { |
208 | - return G_MAXUINT; |
209 | - } |
210 | - } |
211 | - |
212 | - /* If we're the last needle, we can return our distance */ |
213 | - if (needle + 1 >= num_needles) { |
214 | - return distances[(needle * num_haystacks) + haystack]; |
215 | - } |
216 | - |
217 | - guint * local_match = g_new0(guint, num_needles); |
218 | - for (i = 0; i < num_needles && i < needle + 1; i++) { |
219 | - local_match[i] = matches[i]; |
220 | - } |
221 | - |
222 | - /* Now look where we can get the minimum with the other needles */ |
223 | - guint min = G_MAXUINT; |
224 | - for (i = 0; i < num_haystacks; i++) { |
225 | - guint local = minimize_distance_recurse(needle + 1, num_needles, i, num_haystacks, distances, local_match); |
226 | - |
227 | - if (local < min) { |
228 | - min = local; |
229 | - |
230 | - int j; |
231 | - for (j = needle + 1; j < num_needles; j++) { |
232 | - matches[j] = local_match[j]; |
233 | - } |
234 | - } |
235 | - } |
236 | - |
237 | - g_free(local_match); |
238 | - |
239 | - /* Return the min of everyone else plus our distance */ |
240 | - if (min < G_MAXUINT) { |
241 | - min += distances[(needle * num_haystacks) + haystack]; |
242 | - } |
243 | - |
244 | - return min; |
245 | -} |
246 | - |
247 | -/* Figuring out the lowest path through the distance array |
248 | - where we don't use the same haystack tokens */ |
249 | -guint |
250 | -minimize_distance (guint num_needles, guint num_haystacks, guint * distances, guint * matches) |
251 | -{ |
252 | - guint final_distance = G_MAXUINT; |
253 | - guint * local_matches = g_new0(guint, num_needles); |
254 | - |
255 | - guint haystack_token; |
256 | - for (haystack_token = 0; haystack_token < num_haystacks; haystack_token++) { |
257 | - guint distance = minimize_distance_recurse(0, num_needles, haystack_token, num_haystacks, distances, local_matches); |
258 | - |
259 | - if (distance < final_distance) { |
260 | - final_distance = distance; |
261 | - |
262 | - guint match_cnt; |
263 | - for (match_cnt = 0; match_cnt < num_needles; match_cnt++) { |
264 | - matches[match_cnt] = local_matches[match_cnt]; |
265 | - } |
266 | - } |
267 | - } |
268 | - |
269 | - g_free(local_matches); |
270 | - |
271 | - return final_distance; |
272 | -} |
273 | - |
274 | -/* Dups a specific token in the array of strv arrays */ |
275 | -gchar * |
276 | -find_token (guint token_number, GStrv * haystacks, guint num_haystacks) |
277 | -{ |
278 | - guint haystack; |
279 | - |
280 | - for (haystack = 0; haystack < num_haystacks; haystack++) { |
281 | - guint strvlen = g_strv_length(haystacks[haystack]); |
282 | - |
283 | - if (token_number < strvlen) { |
284 | - return g_strdup(haystacks[haystack][token_number]); |
285 | - } |
286 | - |
287 | - token_number -= strvlen; |
288 | - } |
289 | - |
290 | - return NULL; |
291 | -} |
292 | - |
293 | -/* Normalize a set of strings so that we can compare them |
294 | - without worry about accents and the such */ |
295 | -static GStrv |
296 | -normalize_gstrv (GStrv inlist) |
297 | -{ |
298 | - /* The identity property */ |
299 | - if (inlist == NULL) return NULL; |
300 | - |
301 | - guint length = g_strv_length(inlist); |
302 | - GStrv out = g_new0(gchar *, length + 1); |
303 | - gint i; |
304 | - |
305 | - for (i = 0; i < length; i++) { |
306 | - out[i] = g_utf8_normalize(inlist[i], -1, G_NORMALIZE_ALL); |
307 | - } |
308 | - |
309 | - return out; |
310 | -} |
311 | - |
312 | -#define SEPARATORS " .->" |
313 | - |
314 | -guint |
315 | -calculate_distance (const gchar * needle, GStrv haystacks, GStrv * matches) |
316 | -{ |
317 | - g_return_val_if_fail(needle != NULL || haystacks != NULL, G_MAXUINT); |
318 | - guint final_distance = G_MAXUINT; |
319 | - |
320 | - if (needle == NULL || !g_utf8_validate(needle, -1, NULL)) { |
321 | - return DROP_PENALTY * g_utf8_strlen(haystacks[0], 1024); |
322 | - } |
323 | - if (haystacks == NULL) { |
324 | - return ADD_PENALTY * g_utf8_strlen(needle, 1024); |
325 | - } |
326 | - |
327 | - /* Check to make sure we have valid haystacks */ |
328 | - gint i; |
329 | - guint num_haystacks = g_strv_length(haystacks); |
330 | - |
331 | - for (i = 0; i < num_haystacks; i++) { |
332 | - if (!g_utf8_validate(haystacks[i], -1, NULL)) { |
333 | - return ADD_PENALTY * g_utf8_strlen(needle, 1024); |
334 | - } |
335 | - } |
336 | - |
337 | - /* Tokenize all the haystack strings */ |
338 | - guint num_haystack_tokens = 0; |
339 | - GStrv * haystacks_array = g_new0(GStrv, num_haystacks); |
340 | - |
341 | - for (i = 0; i < num_haystacks; i++) { |
342 | - GStrv split = g_strsplit_set(haystacks[i], SEPARATORS, 0); |
343 | - haystacks_array[i] = normalize_gstrv(split); |
344 | - g_strfreev(split); |
345 | - num_haystack_tokens += g_strv_length(haystacks_array[i]); |
346 | - } |
347 | - |
348 | - /* Tokenize our needles the same way */ |
349 | - GStrv needle_split = g_strsplit_set(needle, SEPARATORS, 0); |
350 | - GStrv needle_tokens = normalize_gstrv(needle_split); |
351 | - g_strfreev(needle_split); |
352 | - guint num_needle_tokens = g_strv_length(needle_tokens); |
353 | - |
354 | - if (num_needle_tokens <= num_haystack_tokens) { |
355 | - |
356 | - /* We need a place to store all the distances */ |
357 | - guint * distances = g_new0(guint, num_haystack_tokens * num_needle_tokens); |
358 | - |
359 | - /* Calculate all the distance combinations */ |
360 | - gint needle_token; |
361 | - for (needle_token = 0; needle_tokens[needle_token] != NULL; needle_token++) { |
362 | - gchar * ineedle = needle_tokens[needle_token]; |
363 | - |
364 | - guint haystacks_cnt; |
365 | - guint haystack_token_cnt = 0; |
366 | - for (haystacks_cnt = 0; haystacks_cnt < num_haystacks; haystacks_cnt++) { |
367 | - guint haystack_cnt; |
368 | - for (haystack_cnt = 0; haystacks_array[haystacks_cnt][haystack_cnt] != NULL; haystack_cnt++) { |
369 | - gchar * ihaystack = haystacks_array[haystacks_cnt][haystack_cnt]; |
370 | - guint distance = calculate_token_distance(ineedle, ihaystack); |
371 | - |
372 | - distances[(needle_token * num_haystack_tokens) + haystack_token_cnt] = distance; |
373 | - haystack_token_cnt++; |
374 | - } |
375 | - } |
376 | - } |
377 | - |
378 | - /* Now, try to find a path through the array that results in the |
379 | - lowest total value */ |
380 | - guint * final_matches = g_new0(guint, num_needle_tokens); |
381 | - |
382 | - final_distance = minimize_distance(num_needle_tokens, num_haystack_tokens, distances, final_matches); |
383 | - |
384 | - /* Set up an array for matches so that we can enter |
385 | - the items as we go */ |
386 | - if (matches != NULL) { |
387 | - GStrv match_array = NULL; |
388 | - match_array = g_new0(gchar *, num_needle_tokens + 1); |
389 | - match_array[num_needle_tokens] = NULL; |
390 | - |
391 | - /* Copy the strings that we care about */ |
392 | - int i; |
393 | - for (i = 0; i < num_needle_tokens; i++) { |
394 | - match_array[i] = find_token(final_matches[i], haystacks_array, num_haystacks); |
395 | - } |
396 | - |
397 | - *matches = match_array; |
398 | - } |
399 | - |
400 | - g_free(final_matches); |
401 | - g_free(distances); |
402 | - } |
403 | - |
404 | - /* token cleanup */ |
405 | - g_strfreev(needle_tokens); |
406 | - for (i = 0; i < num_haystacks; i++) { |
407 | - g_strfreev(haystacks_array[i]); |
408 | - } |
409 | - g_free(haystacks_array); |
410 | - |
411 | - if (final_distance != G_MAXUINT) { |
412 | - return final_distance / num_needle_tokens; |
413 | - } else { |
414 | - return G_MAXUINT; |
415 | - } |
416 | -} |