1 #include "malloc.h" // realloc() and free()
2 #include <string.h> // strncasecmp()
6 // how is our flag organized?
8 #define FLAG_VALID(flag) (flag == 0xBF)
10 static int do_resize(struct file_entry
*e
, const uint32_t name_len
, const int zero_fill
);
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
));
16 DEBUGF("new_file_entry: could not allocate memory\n");
30 // and resize to the requested size
31 if( do_resize(e
, name_len
, 1) ) {
39 int file_entry_destruct(struct file_entry
*e
) {
41 assert(FLAG_VALID(e
->flag
));
50 static int do_resize(struct file_entry
*e
, const uint32_t name_len
, const int zero_fill
) {
54 assert(FLAG_VALID(e
->flag
));
56 if( name_len
!= e
->size
.name_len
) {
57 temp
= realloc(e
->name
, name_len
);
59 DEBUGF("file_entry_resize: out of memory to resize name\n");
62 e
->name
= (char*)temp
;
64 // if asked, fill it with zero's
67 for(i
=e
->size
.name_len
; i
<name_len
; i
++)
68 e
->name
[i
] = (char)0x00;
71 e
->size
.name_len
= name_len
;
77 inline int file_entry_resize(struct file_entry
*e
, const uint32_t name_len
) {
78 return do_resize(e
, name_len
, 1);
81 int file_entry_serialize(FILE *fd
, const struct file_entry
*e
) {
84 assert(FLAG_VALID(e
->flag
));
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");
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");
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");
104 if( fwrite(&e
->hash
, sizeof(e
->hash
), 1, fd
) != 1 ) {
105 DEBUGF("file_entry_serialize: failed to write hash\n");
110 if( fwrite(&e
->song
, sizeof(e
->song
), 1, fd
) != 1 ) {
111 DEBUGF("file_entry_serialize: failed to write song\n");
116 if( fwrite(&e
->rundb
, sizeof(e
->rundb
), 1, fd
) != 1 ) {
117 DEBUGF("file_entry_serialize: failed to write rundb\n");
124 int file_entry_unserialize(struct file_entry
**dest
, FILE *fd
) {
126 struct file_entry
*e
;
128 assert(dest
!= NULL
);
132 e
= new_file_entry(0);
134 DEBUGF("file_entry_unserialize: could not create new file_entry\n");
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
);
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
);
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
);
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
);
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
);
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
);
184 int file_entry_write(FILE *fd
, struct file_entry
*e
, struct file_size
*s
) {
190 assert(FLAG_VALID(e
->flag
));
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");
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 ) {
203 DEBUGF("file_entry_write: failed to pad name\n");
209 be32
= BE32(e
->hash
);
210 if( fwrite(&be32
, sizeof(be32
), 1, fd
) != 1 ) {
211 DEBUGF("file_entry_write: failed to write hash\n");
216 be32
= BE32(e
->song
);
217 if( fwrite(&be32
, sizeof(be32
), 1, fd
) != 1 ) {
218 DEBUGF("file_entry_write: failed to write song\n");
223 be32
= BE32(e
->rundb
);
224 if( fwrite(&be32
, sizeof(be32
), 1, fd
) != 1 ) {
225 DEBUGF("file_entry_write: failed to write rundb\n");
232 inline int file_entry_compare(const struct file_entry
*a
, const struct file_entry
*b
) {
235 return strncasecmp(a
->name
, b
->name
, (a
->size
.name_len
<= b
->size
.name_len
? a
->size
.name_len
: b
->size
.name_len
) );
238 struct file_size
* new_file_size() {
240 s
= (struct file_size
*)malloc(sizeof(struct file_size
));
242 DEBUGF("new_file_size: failed to allocate memory\n");
250 inline uint32_t file_size_get_length(const struct file_size
*size
) {
251 assert(size
!= NULL
);
252 return size
->name_len
+ 12;
255 inline int file_size_max(struct file_size
*s
, const struct file_entry
*e
) {
258 assert(FLAG_VALID(e
->flag
));
259 s
->name_len
= ( s
->name_len
>= e
->size
.name_len
? s
->name_len
: e
->size
.name_len
);
263 int file_size_destruct(struct file_size
*s
) {