summaryrefslogtreecommitdiff
path: root/apps/tagdb/file.c
diff options
context:
space:
mode:
authorNiels Laukens <niobos@rockbox.org>2005-07-06 11:03:20 +0000
committerNiels Laukens <niobos@rockbox.org>2005-07-06 11:03:20 +0000
commitd1c294c17de95615b7af428da938b686830b42df (patch)
tree950080f5b6c9503c090df6e4f0929f13eae8891e /apps/tagdb/file.c
parent5e9f52f6d1f3356bc6df75a675e1a2d5cdbf9d77 (diff)
downloadrockbox-d1c294c17de95615b7af428da938b686830b42df.zip
rockbox-d1c294c17de95615b7af428da938b686830b42df.tar.gz
rockbox-d1c294c17de95615b7af428da938b686830b42df.tar.bz2
rockbox-d1c294c17de95615b7af428da938b686830b42df.tar.xz
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.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 0000000..de641fe
--- /dev/null
+++ b/apps/tagdb/file.c
@@ -0,0 +1,268 @@
+#include "malloc.h" // realloc() and free()
+#include <string.h> // strncasecmp()
+
+#include "file.h"
+
+// how is our flag organized?
+#define FLAG ( 0xBF )
+#define FLAG_VALID(flag) (flag == 0xBF)
+
+static int do_resize(struct file_entry *e, const uint32_t name_len, const int zero_fill);
+
+struct file_entry* new_file_entry(const uint32_t name_len) {
+ // Start my allocating memory
+ struct file_entry *e = (struct file_entry*)malloc(sizeof(struct file_entry));
+ if( e == NULL ) {
+ DEBUGF("new_file_entry: could not allocate memory\n");
+ return NULL;
+ }
+
+ // We begin empty
+ e->name = NULL;
+ e->size.name_len = 0;
+
+ e->hash = 0;
+ e->song = 0;
+ e->rundb = 0;
+
+ e->flag = FLAG;
+
+ // and resize to the requested size
+ if( do_resize(e, name_len, 1) ) {
+ free(e);
+ return NULL;
+ }
+
+ return e;
+}
+
+int file_entry_destruct(struct file_entry *e) {
+ assert(e != NULL);
+ assert(FLAG_VALID(e->flag));
+
+ free(e->name);
+
+ free(e);
+
+ return ERR_NONE;
+}
+
+static int do_resize(struct file_entry *e, const uint32_t name_len, const int zero_fill) {
+ void* temp;
+
+ assert(e != NULL);
+ assert(FLAG_VALID(e->flag));
+
+ if( name_len != e->size.name_len ) {
+ temp = realloc(e->name, name_len);
+ if(temp == NULL) {
+ DEBUGF("file_entry_resize: out of memory to resize name\n");
+ return ERR_MALLOC;
+ }
+ e->name = (char*)temp;
+
+ // if asked, fill it with zero's
+ if( zero_fill ) {
+ uint32_t i;
+ for(i=e->size.name_len; i<name_len; i++)
+ e->name[i] = (char)0x00;
+ }
+
+ e->size.name_len = name_len;
+ }
+
+ return ERR_NONE;
+}
+
+inline int file_entry_resize(struct file_entry *e, const uint32_t name_len) {
+ return do_resize(e, name_len, 1);
+}
+
+int file_entry_serialize(FILE *fd, const struct file_entry *e) {
+ assert(fd != NULL);
+ assert(e != NULL);
+ assert(FLAG_VALID(e->flag));
+
+ // First byte we write is a flag-byte to indicate this is a valid record
+ if( fwrite(&e->flag, 1, 1, fd) != 1 ) {
+ DEBUGF("file_entry_serialize: failed to write flag-byte\n");
+ return ERR_FILE;
+ }
+
+ // First we write the length of the name field
+ if( fwrite(&e->size.name_len, sizeof(e->size.name_len), 1, fd) != 1 ) {
+ DEBUGF("file_entry_serialize: failed to write name_len\n");
+ return ERR_FILE;
+ }
+ // now the name field itself
+ if( fwrite(e->name, 1, e->size.name_len, fd) != e->size.name_len ) {
+ DEBUGF("file_entry_serialize: failed to write name\n");
+ return ERR_FILE;
+ }
+
+ // hash field
+ if( fwrite(&e->hash, sizeof(e->hash), 1, fd) != 1 ) {
+ DEBUGF("file_entry_serialize: failed to write hash\n");
+ return ERR_FILE;
+ }
+
+ // song field
+ if( fwrite(&e->song, sizeof(e->song), 1, fd) != 1 ) {
+ DEBUGF("file_entry_serialize: failed to write song\n");
+ return ERR_FILE;
+ }
+
+ // rundb field
+ if( fwrite(&e->rundb, sizeof(e->rundb), 1, fd) != 1 ) {
+ DEBUGF("file_entry_serialize: failed to write rundb\n");
+ return ERR_FILE;
+ }
+
+ return ERR_NONE;
+}
+
+int file_entry_unserialize(struct file_entry **dest, FILE *fd) {
+ uint32_t length;
+ struct file_entry *e;
+
+ assert(dest != NULL);
+ assert(fd != NULL);
+
+ // Allocate memory
+ e = new_file_entry(0);
+ if( e == NULL ) {
+ DEBUGF("file_entry_unserialize: could not create new file_entry\n");
+ return ERR_MALLOC;
+ }
+
+ // First we read the length of the name field
+ if( fread(&length, sizeof(length), 1, fd) != 1 ) {
+ DEBUGF("file_entry_unserialize: failed to read name_len\n");
+ file_entry_destruct(e);
+ return ERR_FILE;
+ }
+
+ // allocate memory for the upcomming name-field
+ if( do_resize(e, length, 0) ) {
+ DEBUGF("file_entry_unserialize: failed to allocate memory for name\n");
+ file_entry_destruct(e);
+ return ERR_MALLOC;
+ }
+
+ // read it in
+ if( fread(e->name, 1, e->size.name_len, fd) != e->size.name_len ) {
+ DEBUGF("file_entry_unserialize: failed to read name\n");
+ file_entry_destruct(e);
+ return ERR_FILE;
+ }
+
+ // hash field
+ if( fread(&e->hash, sizeof(e->hash), 1, fd) != 1 ) {
+ DEBUGF("file_entry_unserialize: failed to read hash\n");
+ file_entry_destruct(e);
+ return ERR_FILE;
+ }
+
+ // song field
+ if( fread(&e->song, sizeof(e->song), 1, fd) != 1 ) {
+ DEBUGF("file_entry_unserialize: failed to read song\n");
+ file_entry_destruct(e);
+ return ERR_FILE;
+ }
+
+ // rundb field
+ if( fread(&e->rundb, sizeof(e->rundb), 1, fd) != 1 ) {
+ DEBUGF("file_entry_unserialize: failed to read rundb\n");
+ file_entry_destruct(e);
+ return ERR_FILE;
+ }
+
+ *dest = e;
+ return ERR_NONE;
+}
+
+int file_entry_write(FILE *fd, struct file_entry *e, struct file_size *s) {
+ uint32_t be32;
+ char pad = 0x00;
+
+ assert(fd != NULL);
+ assert(e != NULL);
+ assert(FLAG_VALID(e->flag));
+
+ // file name
+ if( fwrite(e->name, 1, e->size.name_len, fd) != e->size.name_len ) {
+ DEBUGF("file_entry_write: failed to write name\n");
+ return ERR_FILE;
+ }
+ // pad the rest
+ be32 = e->size.name_len; // abuse be32 as counter
+ while( s != NULL && s->name_len > be32) {
+ if( fwrite(&pad, 1, 1, fd) == 1 ) {
+ be32++;
+ } else {
+ DEBUGF("file_entry_write: failed to pad name\n");
+ return ERR_FILE;
+ }
+ }
+
+ // hash
+ be32 = BE32(e->hash);
+ if( fwrite(&be32, sizeof(be32), 1, fd) != 1 ) {
+ DEBUGF("file_entry_write: failed to write hash\n");
+ return ERR_FILE;
+ }
+
+ // song
+ be32 = BE32(e->song);
+ if( fwrite(&be32, sizeof(be32), 1, fd) != 1 ) {
+ DEBUGF("file_entry_write: failed to write song\n");
+ return ERR_FILE;
+ }
+
+ // rundb
+ be32 = BE32(e->rundb);
+ if( fwrite(&be32, sizeof(be32), 1, fd) != 1 ) {
+ DEBUGF("file_entry_write: failed to write rundb\n");
+ return ERR_FILE;
+ }
+
+ return ERR_NONE;
+}
+
+inline int file_entry_compare(const struct file_entry *a, const struct file_entry *b) {
+ assert(a != NULL);
+ assert(b != NULL);
+ return strncasecmp(a->name, b->name, (a->size.name_len <= b->size.name_len ? a->size.name_len : b->size.name_len) );
+}
+
+struct file_size* new_file_size() {
+ struct file_size *s;
+ s = (struct file_size*)malloc(sizeof(struct file_size));
+ if( s == NULL ) {
+ DEBUGF("new_file_size: failed to allocate memory\n");
+ return NULL;
+ }
+ s->name_len = 0;
+
+ return s;
+}
+
+inline uint32_t file_size_get_length(const struct file_size *size) {
+ assert(size != NULL);
+ return size->name_len + 12;
+}
+
+inline int file_size_max(struct file_size *s, const struct file_entry *e) {
+ assert(s != NULL);
+ assert(e != NULL);
+ assert(FLAG_VALID(e->flag));
+ s->name_len = ( s->name_len >= e->size.name_len ? s->name_len : e->size.name_len );
+ return ERR_NONE;
+}
+
+int file_size_destruct(struct file_size *s) {
+ assert(s != NULL);
+ // nothing to do...
+ free(s);
+ return ERR_NONE;
+}