-
Notifications
You must be signed in to change notification settings - Fork 0
/
file.c
146 lines (127 loc) · 3.08 KB
/
file.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include <glib.h>
#include "types.h"
#include "abstract_file.h"
#include "file.h"
#include "util.h"
#include "log.h"
#include "tagdb_util.h"
#include "key.h"
/* Files are equivalent if they have the same record in memory */
gboolean file_equal (gconstpointer a, gconstpointer b)
{
return g_direct_equal(a, b);
}
guint file_hash (gconstpointer file)
{
/* XXX: I'm not sure why the file's location in memory is
* needed as well as its name for the hash, nor am I sure
* why its ID isn't used. The id should be in a one-to-one
* mapping with the address, but it isn't always the case.
*/
File *f = (File*) file;
return (TO_S(f) << 17) ^ (g_str_hash(file_name(f)));
}
TagTable *tag_table_new()
{
return g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) result_destroy);
}
void file_init (File *f, const char *name)
{
abstract_file_init(&f->base, name);
f->tags = tag_table_new();
}
File *new_file (const char *name)
{
File *f = g_malloc(sizeof(File));
file_init(f,name);
return f;
}
// XXX: The unsafe versions were added when reference counting was employed
// on the Files. Probably not needed any longer
/* file_destroy_unsafe0 doesn't free the memory */
void file_destroy_unsafe0 (File *f)
{
abstract_file_destroy(&f->base);
g_hash_table_destroy(f->tags);
f->tags = NULL;
}
void file_destroy_unsafe (File *f)
{
file_destroy_unsafe0(f);
g_free(f);
}
/* file_destroy0 doesn't free the memory */
gboolean file_destroy0 (File *f)
{
file_destroy_unsafe0(f);
return TRUE;
}
gboolean file_destroy (File *f)
{
gboolean res = file_destroy0(f);
if (res)
{
g_free(f);
}
return res;
}
tagdb_key_t file_extract_key (File *f)
{
tagdb_key_t key = key_new();
GList *key_elems = g_hash_table_get_keys(f->tags);
GList *it = key_elems;
while (it != NULL)
{
key_push_end(key, TO_S(it->data));
it = it->next;
}
g_list_free(key_elems);
return key;
}
gboolean file_has_tags (File *f, tagdb_key_t tags)
{
if (key_is_empty(tags) && g_hash_table_size(f->tags) == 0)
return TRUE;
KL(tags, i)
{
debug("file_has_tags tags[i] = %ld", key_ref(tags,i));
if (!g_hash_table_lookup_extended(f->tags, TO_SP(key_ref(tags, i)), NULL, NULL))
return FALSE;
} KL_END;
return TRUE;
}
gboolean file_only_has_tags (File *f, tagdb_key_t tags)
{
if (key_length(tags) == g_hash_table_size(f->tags))
{
return file_has_tags(f, tags);
}
return FALSE;
}
void file_remove_tag (File *f, file_id_t tag_id)
{
if (f)
g_hash_table_remove(f->tags, TO_SP(tag_id));
}
void file_add_tag (File *f, file_id_t tag_id, tagdb_value_t *v)
{
if (f)
g_hash_table_insert(f->tags, TO_SP(tag_id), v);
}
tagdb_value_t *file_tag_value (File *f, file_id_t tag_id)
{
if (f)
{
return g_hash_table_lookup(f->tags, TO_SP(tag_id));
}
else
{
return NULL;
}
}
gboolean file_is_untagged (File *f)
{
if (f)
return (g_hash_table_size(f->tags) == 0);
return FALSE;
}