]> Dogcows Code - chaz/homebank/blob - src/hb-tag.c
Merge branch 'upstream'
[chaz/homebank] / src / hb-tag.c
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2019 Maxime DOYEN
3 *
4 * This file is part of HomeBank.
5 *
6 * HomeBank is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * HomeBank is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "homebank.h"
21 #include "hb-tag.h"
22
23 #define MYDEBUG 0
24
25 #if MYDEBUG
26 #define DB(x) (x);
27 #else
28 #define DB(x);
29 #endif
30
31 /* our global datas */
32 extern struct HomeBank *GLOBALS;
33
34
35 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
36
37 void da_tag_free(Tag *item)
38 {
39 DB( g_print("da_tag_free\n") );
40 if(item != NULL)
41 {
42 DB( g_print(" => %d, %s\n", item->key, item->name) );
43
44 g_free(item->name);
45 g_free(item);
46 }
47 }
48
49
50 Tag *da_tag_malloc(void)
51 {
52 DB( g_print("da_tag_malloc\n") );
53 return g_malloc0(sizeof(Tag));
54 }
55
56
57 void da_tag_destroy(void)
58 {
59 DB( g_print("da_tag_destroy\n") );
60 g_hash_table_destroy(GLOBALS->h_tag);
61 }
62
63
64 void da_tag_new(void)
65 {
66 DB( g_print("da_tag_new\n") );
67 GLOBALS->h_tag = g_hash_table_new_full(g_int_hash, g_int_equal, (GDestroyNotify)g_free, (GDestroyNotify)da_tag_free);
68 }
69
70
71 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
72 static void da_tag_max_key_ghfunc(gpointer key, Tag *item, guint32 *max_key)
73 {
74 *max_key = MAX(*max_key, item->key);
75 }
76
77 static gboolean da_tag_name_grfunc(gpointer key, Tag *item, gchar *name)
78 {
79 if( name && item->name )
80 {
81 if(!strcasecmp(name, item->name))
82 return TRUE;
83 }
84 return FALSE;
85 }
86
87 /**
88 * da_tag_length:
89 *
90 * Return value: the number of elements
91 */
92 guint da_tag_length(void)
93 {
94 return g_hash_table_size(GLOBALS->h_tag);
95 }
96
97 /**
98 * da_tag_remove:
99 *
100 * delete an tag from the GHashTable
101 *
102 * Return value: TRUE if the key was found and deleted
103 *
104 */
105 gboolean da_tag_remove(guint32 key)
106 {
107 DB( g_print("da_tag_remove %d\n", key) );
108
109 return g_hash_table_remove(GLOBALS->h_tag, &key);
110 }
111
112 /**
113 * da_tag_insert:
114 *
115 * insert an tag into the GHashTable
116 *
117 * Return value: TRUE if inserted
118 *
119 */
120 gboolean da_tag_insert(Tag *item)
121 {
122 guint32 *new_key;
123
124 DB( g_print("da_tag_insert\n") );
125
126 new_key = g_new0(guint32, 1);
127 *new_key = item->key;
128 g_hash_table_insert(GLOBALS->h_tag, new_key, item);
129
130 return TRUE;
131 }
132
133
134 /**
135 * da_tag_append:
136 *
137 * append a new tag into the GHashTable
138 *
139 * Return value: TRUE if inserted
140 *
141 */
142 gboolean da_tag_append(Tag *item)
143 {
144 Tag *existitem;
145 guint32 *new_key;
146
147 DB( g_print("da_tag_append\n") );
148
149 if( item->name != NULL )
150 {
151 /* ensure no duplicate */
152 //g_strstrip(item->name);
153 existitem = da_tag_get_by_name( item->name );
154 if( existitem == NULL )
155 {
156 new_key = g_new0(guint32, 1);
157 *new_key = da_tag_get_max_key() + 1;
158 item->key = *new_key;
159
160 DB( g_print(" -> append id: %d\n", *new_key) );
161
162 g_hash_table_insert(GLOBALS->h_tag, new_key, item);
163 return TRUE;
164 }
165 }
166
167 DB( g_print(" -> %s already exist: %d\n", item->name, item->key) );
168
169 return FALSE;
170 }
171
172 /**
173 * da_tag_get_max_key:
174 *
175 * Get the biggest key from the GHashTable
176 *
177 * Return value: the biggest key value
178 *
179 */
180 guint32 da_tag_get_max_key(void)
181 {
182 guint32 max_key = 0;
183
184 g_hash_table_foreach(GLOBALS->h_tag, (GHFunc)da_tag_max_key_ghfunc, &max_key);
185 return max_key;
186 }
187
188
189 /**
190 * da_tag_get_by_name:
191 *
192 * Get an tag structure by its name
193 *
194 * Return value: Tag * or NULL if not found
195 *
196 */
197 Tag *da_tag_get_by_name(gchar *name)
198 {
199 DB( g_print("da_tag_get_by_name\n") );
200
201 return g_hash_table_find(GLOBALS->h_tag, (GHRFunc)da_tag_name_grfunc, name);
202 }
203
204
205
206 /**
207 * da_tag_get:
208 *
209 * Get an tag structure by key
210 *
211 * Return value: Tag * or NULL if not found
212 *
213 */
214 Tag *da_tag_get(guint32 key)
215 {
216 DB( g_print("da_tag_get_tag\n") );
217
218 return g_hash_table_lookup(GLOBALS->h_tag, &key);
219 }
220
221
222 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
223
224 guint
225 tags_count(guint32 *tags)
226 {
227 guint count = 0;
228
229 DB( g_print("\n[tags] count\n") );
230
231 if( tags == NULL )
232 return 0;
233
234 while(*tags++ != 0 && count < 32)
235 count++;
236
237 return count;
238 }
239
240
241 guint32 *tags_clone(guint32 *tags)
242 {
243 guint32 *newtags = NULL;
244 guint count;
245
246 count = tags_count(tags);
247 if(count > 0)
248 {
249 //1501962: we must also copy the final 0
250 newtags = g_memdup(tags, (count+1)*sizeof(guint32));
251 }
252
253 return newtags;
254 }
255
256
257 static gboolean
258 tags_key_exists(guint32 *tags, guint32 key)
259 {
260 guint count = 0;
261 while(*tags != 0 && count < 32)
262 {
263 if( *tags == key )
264 return TRUE;
265 tags++;
266 count++;
267 }
268 return FALSE;
269 }
270
271
272 guint32 *
273 tags_parse(const gchar *tagstring)
274 {
275 gchar **str_array;
276 guint32 *tags = NULL;
277 guint32 *ptags;
278 guint count, i;
279 Tag *tag;
280
281 DB( g_print("\n[tags] parse\n") );
282
283 if( tagstring )
284 {
285 str_array = g_strsplit (tagstring, " ", 0);
286 count = g_strv_length( str_array );
287 DB( g_print("- %d tags '%s'\n", count, tagstring) );
288 if( count > 0 )
289 {
290 tags = g_new0(guint32, count + 1);
291 ptags = tags;
292 for(i=0;i<count;i++)
293 {
294 //5.2.3 fixed empty tag
295 if( strlen(str_array[i]) == 0 )
296 continue;
297
298 DB( g_print("- %d search '%s'\n", i, str_array[i]) );
299 tag = da_tag_get_by_name(str_array[i]);
300 if(tag == NULL)
301 {
302 Tag *newtag = da_tag_malloc();
303
304 newtag->name = g_strdup(str_array[i]);
305 da_tag_append(newtag);
306 tag = da_tag_get_by_name(str_array[i]);
307 }
308 DB( g_print("- array add %d '%s'\n", tag->key, tag->name) );
309
310 //5.3 fixed duplicate tag in same tags
311 if( tags_key_exists(tags, tag->key) == FALSE )
312 *ptags++ = tag->key;
313 }
314 *ptags = 0;
315 }
316
317 g_strfreev (str_array);
318 }
319 return tags;
320 }
321
322
323
324 gchar *
325 tags_tostring(guint32 *tags)
326 {
327 guint count, i;
328 gchar **str_array, **tptr;
329 gchar *tagstring;
330 Tag *tag;
331
332 DB( g_print("\n[tags] tostring\n") );
333 if( tags == NULL )
334 {
335 return NULL;
336 }
337 else
338 {
339 count = tags_count(tags);
340 str_array = g_new0(gchar*, count+1);
341 tptr = str_array;
342 for(i=0;i<count;i++)
343 {
344 tag = da_tag_get(tags[i]);
345 if( tag )
346 {
347 *tptr++ = tag->name;
348 }
349 }
350 *tptr = NULL;
351
352 tagstring = g_strjoinv(" ", str_array);
353 g_free (str_array);
354 }
355 return tagstring;
356 }
357
358
359 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
360
361
362 #if MYDEBUG
363
364 static void
365 da_tag_debug_list_ghfunc(gpointer key, gpointer value, gpointer user_data)
366 {
367 guint32 *id = key;
368 Tag *item = value;
369
370 DB( g_print(" %d :: %s\n", *id, item->name) );
371
372 }
373
374 static void
375 da_tag_debug_list(void)
376 {
377
378 DB( g_print("\n** debug **\n") );
379
380 g_hash_table_foreach(GLOBALS->h_tag, da_tag_debug_list_ghfunc, NULL);
381
382 DB( g_print("\n** end debug **\n") );
383
384 }
385
386 #endif
387
388 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
389
390
391 gboolean
392 tag_rename(Tag *item, const gchar *newname)
393 {
394 Tag *existitem;
395 gchar *stripname;
396 gboolean retval = FALSE;
397
398 stripname = g_strdup(newname);
399 g_strstrip(stripname);
400
401 existitem = da_tag_get_by_name(stripname);
402
403 if( existitem != NULL && existitem->key != item->key)
404 {
405 DB( g_print("- error, same name already exist with other key %d <> %d\n",existitem->key, item->key) );
406 g_free(stripname);
407 }
408 else
409 {
410 DB( g_print("- renaming\n") );
411 g_free(item->name);
412 item->name = stripname;
413 retval = TRUE;
414 }
415
416 return retval;
417 }
418
419
420
421 static gint
422 tag_glist_name_compare_func(Tag *a, Tag *b)
423 {
424 return hb_string_utf8_compare(a->name, b->name);
425 }
426
427
428 static gint
429 tag_glist_key_compare_func(Tag *a, Tag *b)
430 {
431 return a->key - b->key;
432 }
433
434
435 GList *tag_glist_sorted(gint column)
436 {
437 GList *list = g_hash_table_get_values(GLOBALS->h_tag);
438
439 if(column == 0)
440 return g_list_sort(list, (GCompareFunc)tag_glist_key_compare_func);
441 else
442 return g_list_sort(list, (GCompareFunc)tag_glist_name_compare_func);
443 }
444
445
446
447
448
This page took 0.050816 seconds and 4 git commands to generate.