Merge lp:~charlesk/indicator-appmenu/remove-dead-file into lp:indicator-appmenu/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
Reviewer Review Type Date Requested Status
Sebastien Bacher Approve
Review via email: mp+100807@code.launchpad.net
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-}

Subscribers

People subscribed via source and target branches