summaryrefslogtreecommitdiff
path: root/apps/tagdb/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/tagdb/file.c')
-rw-r--r--apps/tagdb/file.c268
1 files changed, 268 insertions, 0 deletions
diff --git a/apps/tagdb/file.c b/apps/tagdb/file.c
new file mode 100644
index 0000000000..de641fec38
--- /dev/null
+++ b/apps/tagdb/file.c
@@ -0,0 +1,268 @@
1#include "malloc.h" // realloc() and free()
2#include <string.h> // strncasecmp()
3
4#include "file.h"
5
6// how is our flag organized?
7#define FLAG ( 0xBF )
8#define FLAG_VALID(flag) (flag == 0xBF)
9
10static int do_resize(struct file_entry *e, const uint32_t name_len, const int zero_fill);
11
12struct file_entry* new_file_entry(const uint32_t name_len) {
13 // Start my allocating memory
14 struct file_entry *e = (struct file_entry*)malloc(sizeof(struct file_entry));
15 if( e == NULL ) {
16 DEBUGF("new_file_entry: could not allocate memory\n");
17 return NULL;
18 }
19
20 // We begin empty
21 e->name = NULL;
22 e->size.name_len = 0;
23
24 e->hash = 0;
25 e->song = 0;
26 e->rundb = 0;
27
28 e->flag = FLAG;
29
30 // and resize to the requested size
31 if( do_resize(e, name_len, 1) ) {
32 free(e);
33 return NULL;
34 }
35
36 return e;
37}
38
39int file_entry_destruct(struct file_entry *e) {
40 assert(e != NULL);
41 assert(FLAG_VALID(e->flag));
42
43 free(e->name);
44
45 free(e);
46
47 return ERR_NONE;
48}
49
50static int do_resize(struct file_entry *e, const uint32_t name_len, const int zero_fill) {
51 void* temp;
52
53 assert(e != NULL);
54 assert(FLAG_VALID(e->flag));
55
56 if( name_len != e->size.name_len ) {
57 temp = realloc(e->name, name_len);
58 if(temp == NULL) {
59 DEBUGF("file_entry_resize: out of memory to resize name\n");
60 return ERR_MALLOC;
61 }
62 e->name = (char*)temp;
63
64 // if asked, fill it with zero's
65 if( zero_fill ) {
66 uint32_t i;
67 for(i=e->size.name_len; i<name_len; i++)
68 e->name[i] = (char)0x00;
69 }
70
71 e->size.name_len = name_len;
72 }
73
74 return ERR_NONE;
75}
76
77inline int file_entry_resize(struct file_entry *e, const uint32_t name_len) {
78 return do_resize(e, name_len, 1);
79}
80
81int file_entry_serialize(FILE *fd, const struct file_entry *e) {
82 assert(fd != NULL);
83 assert(e != NULL);
84 assert(FLAG_VALID(e->flag));
85
86 // First byte we write is a flag-byte to indicate this is a valid record
87 if( fwrite(&e->flag, 1, 1, fd) != 1 ) {
88 DEBUGF("file_entry_serialize: failed to write flag-byte\n");
89 return ERR_FILE;
90 }
91
92 // First we write the length of the name field
93 if( fwrite(&e->size.name_len, sizeof(e->size.name_len), 1, fd) != 1 ) {
94 DEBUGF("file_entry_serialize: failed to write name_len\n");
95 return ERR_FILE;
96 }
97 // now the name field itself
98 if( fwrite(e->name, 1, e->size.name_len, fd) != e->size.name_len ) {
99 DEBUGF("file_entry_serialize: failed to write name\n");
100 return ERR_FILE;
101 }
102
103 // hash field
104 if( fwrite(&e->hash, sizeof(e->hash), 1, fd) != 1 ) {
105 DEBUGF("file_entry_serialize: failed to write hash\n");
106 return ERR_FILE;
107 }
108
109 // song field
110 if( fwrite(&e->song, sizeof(e->song), 1, fd) != 1 ) {
111 DEBUGF("file_entry_serialize: failed to write song\n");
112 return ERR_FILE;
113 }
114
115 // rundb field
116 if( fwrite(&e->rundb, sizeof(e->rundb), 1, fd) != 1 ) {
117 DEBUGF("file_entry_serialize: failed to write rundb\n");
118 return ERR_FILE;
119 }
120
121 return ERR_NONE;
122}
123
124int file_entry_unserialize(struct file_entry **dest, FILE *fd) {
125 uint32_t length;
126 struct file_entry *e;
127
128 assert(dest != NULL);
129 assert(fd != NULL);
130
131 // Allocate memory
132 e = new_file_entry(0);
133 if( e == NULL ) {
134 DEBUGF("file_entry_unserialize: could not create new file_entry\n");
135 return ERR_MALLOC;
136 }
137
138 // First we read the length of the name field
139 if( fread(&length, sizeof(length), 1, fd) != 1 ) {
140 DEBUGF("file_entry_unserialize: failed to read name_len\n");
141 file_entry_destruct(e);
142 return ERR_FILE;
143 }
144
145 // allocate memory for the upcomming name-field
146 if( do_resize(e, length, 0) ) {
147 DEBUGF("file_entry_unserialize: failed to allocate memory for name\n");
148 file_entry_destruct(e);
149 return ERR_MALLOC;
150 }
151
152 // read it in
153 if( fread(e->name, 1, e->size.name_len, fd) != e->size.name_len ) {
154 DEBUGF("file_entry_unserialize: failed to read name\n");
155 file_entry_destruct(e);
156 return ERR_FILE;
157 }
158
159 // hash field
160 if( fread(&e->hash, sizeof(e->hash), 1, fd) != 1 ) {
161 DEBUGF("file_entry_unserialize: failed to read hash\n");
162 file_entry_destruct(e);
163 return ERR_FILE;
164 }
165
166 // song field
167 if( fread(&e->song, sizeof(e->song), 1, fd) != 1 ) {
168 DEBUGF("file_entry_unserialize: failed to read song\n");
169 file_entry_destruct(e);
170 return ERR_FILE;
171 }
172
173 // rundb field
174 if( fread(&e->rundb, sizeof(e->rundb), 1, fd) != 1 ) {
175 DEBUGF("file_entry_unserialize: failed to read rundb\n");
176 file_entry_destruct(e);
177 return ERR_FILE;
178 }
179
180 *dest = e;
181 return ERR_NONE;
182}
183
184int file_entry_write(FILE *fd, struct file_entry *e, struct file_size *s) {
185 uint32_t be32;
186 char pad = 0x00;
187
188 assert(fd != NULL);
189 assert(e != NULL);
190 assert(FLAG_VALID(e->flag));
191
192 // file name
193 if( fwrite(e->name, 1, e->size.name_len, fd) != e->size.name_len ) {
194 DEBUGF("file_entry_write: failed to write name\n");
195 return ERR_FILE;
196 }
197 // pad the rest
198 be32 = e->size.name_len; // abuse be32 as counter
199 while( s != NULL && s->name_len > be32) {
200 if( fwrite(&pad, 1, 1, fd) == 1 ) {
201 be32++;
202 } else {
203 DEBUGF("file_entry_write: failed to pad name\n");
204 return ERR_FILE;
205 }
206 }
207
208 // hash
209 be32 = BE32(e->hash);
210 if( fwrite(&be32, sizeof(be32), 1, fd) != 1 ) {
211 DEBUGF("file_entry_write: failed to write hash\n");
212 return ERR_FILE;
213 }
214
215 // song
216 be32 = BE32(e->song);
217 if( fwrite(&be32, sizeof(be32), 1, fd) != 1 ) {
218 DEBUGF("file_entry_write: failed to write song\n");
219 return ERR_FILE;
220 }
221
222 // rundb
223 be32 = BE32(e->rundb);
224 if( fwrite(&be32, sizeof(be32), 1, fd) != 1 ) {
225 DEBUGF("file_entry_write: failed to write rundb\n");
226 return ERR_FILE;
227 }
228
229 return ERR_NONE;
230}
231
232inline int file_entry_compare(const struct file_entry *a, const struct file_entry *b) {
233 assert(a != NULL);
234 assert(b != NULL);
235 return strncasecmp(a->name, b->name, (a->size.name_len <= b->size.name_len ? a->size.name_len : b->size.name_len) );
236}
237
238struct file_size* new_file_size() {
239 struct file_size *s;
240 s = (struct file_size*)malloc(sizeof(struct file_size));
241 if( s == NULL ) {
242 DEBUGF("new_file_size: failed to allocate memory\n");
243 return NULL;
244 }
245 s->name_len = 0;
246
247 return s;
248}
249
250inline uint32_t file_size_get_length(const struct file_size *size) {
251 assert(size != NULL);
252 return size->name_len + 12;
253}
254
255inline int file_size_max(struct file_size *s, const struct file_entry *e) {
256 assert(s != NULL);
257 assert(e != NULL);
258 assert(FLAG_VALID(e->flag));
259 s->name_len = ( s->name_len >= e->size.name_len ? s->name_len : e->size.name_len );
260 return ERR_NONE;
261}
262
263int file_size_destruct(struct file_size *s) {
264 assert(s != NULL);
265 // nothing to do...
266 free(s);
267 return ERR_NONE;
268}