diff options
author | Max Kellermann <max@duempel.org> | 2010-11-18 21:44:24 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2010-11-18 21:44:24 +0100 |
commit | 11613347bedef464029c167116d226ec3fddfdcd (patch) | |
tree | 14ddc1a52d1df90c2cd63ab5316f92254f7b77b5 /src/tag_ape.c | |
parent | 8f46f1520cdb3e3e131b2021ac40325f6bdda2c8 (diff) |
tag_ape: move code to ape.c
Generic library for scanning APE tags. Eliminated one "goto"!
Diffstat (limited to 'src/tag_ape.c')
-rw-r--r-- | src/tag_ape.c | 112 |
1 files changed, 19 insertions, 93 deletions
diff --git a/src/tag_ape.c b/src/tag_ape.c index 4841b313..82e36d7a 100644 --- a/src/tag_ape.c +++ b/src/tag_ape.c @@ -21,11 +21,7 @@ #include "tag_ape.h" #include "tag.h" #include "tag_table.h" - -#include <glib.h> - -#include <assert.h> -#include <stdio.h> +#include "ape.h" static const char *const ape_tag_names[TAG_NUM_OF_ITEM_TYPES] = { [TAG_ALBUM_ARTIST] = "album artist", @@ -61,96 +57,26 @@ tag_ape_import_item(struct tag *tag, unsigned long flags, return tag; } -struct tag * -tag_ape_load(const char *file) -{ - struct tag *ret = NULL; - FILE *fp; - int tagCount; - char *buffer = NULL; - char *p; - size_t tagLen; - size_t size; - unsigned long flags; - char *key; - - struct { - unsigned char id[8]; - uint32_t version; - uint32_t length; - uint32_t tagCount; - unsigned char flags[4]; - unsigned char reserved[8]; - } footer; - - fp = fopen(file, "rb"); - if (!fp) - return NULL; - - /* determine if file has an apeV2 tag */ - if (fseek(fp, 0, SEEK_END)) - goto fail; - size = (size_t)ftell(fp); - if (fseek(fp, size - sizeof(footer), SEEK_SET)) - goto fail; - if (fread(&footer, 1, sizeof(footer), fp) != sizeof(footer)) - goto fail; - if (memcmp(footer.id, "APETAGEX", sizeof(footer.id)) != 0) - goto fail; - if (GUINT32_FROM_LE(footer.version) != 2000) - goto fail; - - /* find beginning of ape tag */ - tagLen = GUINT32_FROM_LE(footer.length); - if (tagLen <= sizeof(footer) + 10) - goto fail; - if (tagLen > 1024 * 1024) - /* refuse to load more than one megabyte of tag data */ - goto fail; - if (fseek(fp, size - tagLen, SEEK_SET)) - goto fail; - - /* read tag into buffer */ - tagLen -= sizeof(footer); - assert(tagLen > 10); - - buffer = g_malloc(tagLen); - if (fread(buffer, 1, tagLen, fp) != tagLen) - goto fail; - - /* read tags */ - tagCount = GUINT32_FROM_LE(footer.tagCount); - p = buffer; - while (tagCount-- && tagLen > 10) { - size = GUINT32_FROM_LE(*(const uint32_t *)p); - p += 4; - tagLen -= 4; - flags = GUINT32_FROM_LE(*(const uint32_t *)p); - p += 4; - tagLen -= 4; - - /* get the key */ - key = p; - while (tagLen > size && *p != '\0') { - p++; - tagLen--; - } - p++; - tagLen--; +struct tag_ape_ctx { + struct tag *tag; +}; - /* get the value */ - if (tagLen < size) - goto fail; +static bool +tag_ape_callback(unsigned long flags, const char *key, + const char *value, size_t value_length, void *_ctx) +{ + struct tag_ape_ctx *ctx = _ctx; - ret = tag_ape_import_item(ret, flags, key, p, size); + ctx->tag = tag_ape_import_item(ctx->tag, flags, key, + value, value_length); + return true; +} - p += size; - tagLen -= size; - } +struct tag * +tag_ape_load(const char *file) +{ + struct tag_ape_ctx ctx = { .tag = NULL }; -fail: - if (fp) - fclose(fp); - g_free(buffer); - return ret; + tag_ape_scan(file, tag_ape_callback, &ctx); + return ctx.tag; } |