diff options
author | Niels Laukens <niobos@rockbox.org> | 2005-07-06 11:03:20 +0000 |
---|---|---|
committer | Niels Laukens <niobos@rockbox.org> | 2005-07-06 11:03:20 +0000 |
commit | d1c294c17de95615b7af428da938b686830b42df (patch) | |
tree | 950080f5b6c9503c090df6e4f0929f13eae8891e /apps/tagdb/file.c | |
parent | 5e9f52f6d1f3356bc6df75a675e1a2d5cdbf9d77 (diff) | |
download | rockbox-d1c294c17de95615b7af428da938b686830b42df.tar.gz rockbox-d1c294c17de95615b7af428da938b686830b42df.zip |
Initial import of tagdb
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7039 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/tagdb/file.c')
-rw-r--r-- | apps/tagdb/file.c | 268 |
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 | |||
10 | static int do_resize(struct file_entry *e, const uint32_t name_len, const int zero_fill); | ||
11 | |||
12 | struct 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 | |||
39 | int 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 | |||
50 | static 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 | |||
77 | inline int file_entry_resize(struct file_entry *e, const uint32_t name_len) { | ||
78 | return do_resize(e, name_len, 1); | ||
79 | } | ||
80 | |||
81 | int 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 | |||
124 | int 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 | |||
184 | int 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 | |||
232 | inline 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 | |||
238 | struct 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 | |||
250 | inline uint32_t file_size_get_length(const struct file_size *size) { | ||
251 | assert(size != NULL); | ||
252 | return size->name_len + 12; | ||
253 | } | ||
254 | |||
255 | inline 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 | |||
263 | int file_size_destruct(struct file_size *s) { | ||
264 | assert(s != NULL); | ||
265 | // nothing to do... | ||
266 | free(s); | ||
267 | return ERR_NONE; | ||
268 | } | ||