NAME
SYNOPSIS
#include
ApeTag* ApeTag_new(FILE* file, u_int32_t flags);
int ApeTag_free(ApeTag* tag);
int ApeTag_exists(ApeTag* tag);
int ApeTag_remove(ApeTag* tag);
int ApeTag_raw(ApeTag* tag, char** raw);
int ApeTag_parse(ApeTag* tag);
int ApeTag_update(ApeTag* tag);
int ApeTag_add_field(ApeTag* tag, ApeItem* item);
int ApeTag_remove_field(ApeTag* tag, char* key);
int ApeTag_clear_fields(ApeTag* tag);
DESCRIPTION
int ApeTag_free(ApeTag* tag);
int ApeTag_exists(ApeTag* tag);
int ApeTag_remove(ApeTag* tag);
int ApeTag_raw(ApeTag* tag, char** raw);
int ApeTag_parse(ApeTag* tag);
int ApeTag_update(ApeTag* tag);
int ApeTag_add_field(ApeTag* tag, ApeItem* item);
int ApeTag_remove_field(ApeTag* tag, char* key);
int ApeTag_clear_fields(ApeTag* tag);
AUTHOR
SEE ALSO

NAME

apetag - APEv2 tag reader/writer/updater

SYNOPSIS

#include

ApeTag* ApeTag_new(FILE* file, u_int32_t flags);

int ApeTag_free(ApeTag* tag);

int ApeTag_exists(ApeTag* tag);

int ApeTag_remove(ApeTag* tag);

int ApeTag_raw(ApeTag* tag, char** raw);

int ApeTag_parse(ApeTag* tag);

int ApeTag_update(ApeTag* tag);

int ApeTag_add_field(ApeTag* tag, ApeItem* item);

int ApeTag_remove_field(ApeTag* tag, char* key);

int ApeTag_clear_fields(ApeTag* tag);

DESCRIPTION

QUICK INTRO

apetag's API is fairly straight forward. Some common things to remember:

·

Most functions assert that their pointer arguments are not NULL.

·

For the public functions that return an int, negative numbers imply an error:

·

·

·

·

-1: Check errno, see tag->error for function name.

-2: File error, check ferror, see tag->error for function name.

-3: Apetag consistancy error, see tag->error for reason.

All ApeItems added to the database must be created on the heap.

·

The fields of the tag are stored in a DB_HASH format database.

·

·

·

The keys are NULL-terminated strings ( char*)

The values are ApeItem**

ApeItem keys are NULL-terminated strings.

·

ApeItem values are unterminated strings, since they can contain '\0'. The size of the value is stored in the ApeItem's size.

·

All ApeItems and their keys and values must be stored on the heap.

DATA STRUCTURES
The apetag library exists to read/write/update APEv2 tags in files. The library is written in
an object oriented fashion, using two C structures:

#include <apetag.h>

typedef struct {

FILE* file;
DB* fields;

/* file containing tag */
/* DB_HASH format database */
/* Keys are NULL-terminated */
/* Values are ApeItem** */

char* tag_header; /* Tag Header data */
char* tag_data; /* Tag body data */
char* tag_footer; /* Tag footer data */
char* id3; /* ID3 data, if any */
char* error; /* String for last error */
u_int32_t flags; /* Internal tag flags */


u_int32_t size; /* On disk size in bytes */
u_int32_t item_count; /* On disk item count */
u_int32_t num_fields; /* In database item count */
long offset; /* Start of tag in file */
} ApeTag;

file and flags are the only members that should be set by the user, and they should only be set using ApeTag_new. The values in the fields member are ApeItem**, where ApeItem is defined as:

typedef struct {
u_int32_t size;


/* Size of the value */

u_int32_t flags;
char* key;
char* value;
} ApeItem;

/* Flags on the item */
/* NULL-terminated string */
/* Unterminated string */

Adding new fields to the tag requires creating the ApeItem manually, using malloc for both the ApeItem itself, as well as its key and value, as all must be stored on the heap. A pointer to the item is then passed to ApeTag_add_field.

FUNCTIONS
ApeTag* ApeTag_new(FILE* file, u_int32_t flags);

For a given file and flags, allocates an empty ApeTag, initializes it to the default values and returns a pointer to it. The only flag the should be passed is APE_NO_ID3, which tells the library to ignore any existing ID3 tag when reading a tag, and not to write an ID3 tag.

Returns a valid ApeTag* if successful; otherwise a null pointer is returned and errno is set to ENOMEM.

int ApeTag_free(ApeTag* tag);

Frees all data associated with an ApeTag, except for the file pointer. This includes freeing all related ApeItems and their keys and values. Since you pass the file pointer to ApeTag_new, you are expected to free it yourself.

Returns 0 if successful, and -1 if there were problems closing tag->fields. Note that you can't check tag->error on error, as tag has already been freed.

int ApeTag_exists(ApeTag* tag);

Checks if the file associated with tag already contains a valid APE tag.

Returns 1 if the tag exists, 0 if it does not, <0 on error.

int ApeTag_remove(ApeTag* tag);

Removes the APE tag from the file associated with tag, if the file has one.

This function parses the header and footer of the tag and will error instead of removing a tag if the header or footer of the tag is corrupt.

Returns 1 if the tag doesn't exist, 0 if it does exist and the tag was removed successfully, <0 on error.

int ApeTag_raw(ApeTag* tag, char** raw);

Populates the passed pointer with the raw string for the entire tag. The length of the raw string will always be TAG_LENGTH(tag).

Note that you need to pass a char**, not a char*, and you are responsible for freeing the char*.

Returns 0 on success, <0 on error.

int ApeTag_parse(ApeTag* tag);

Parses the tag and populates tag->fields. Calls ApeTag_ape_field to add each field, and operates no differently than adding all the fields manually.

Returns 0 on success, <0 on error.

int ApeTag_update(ApeTag* tag);

Updates tag->file with the new tag information. Writes an ID3 tag as well as an APE tag unless the APE_NO_ID3 flag is used or the file already has an APE tag but doesn't have an ID3 tag.

Note that if you want to update an existing tag, you need to populate tag->fields with ApeTag_parse before call- ing ApeTag_update. Otherwise, it'll overwrite the tag instead of updating it.

Returns 0 on success, <0 on error.

int ApeTag_add_field(ApeTag* tag, ApeItem* item);

Adds a field to tag->fields. The field cannot already exist in tag->fields. The item itself, as well as item->key and item->value, must be created on the heap, as they are all freed when calling ApeTag_free, ApeTag_clear_fields, or ApeTag_remove_field.

This function creates tag->fields if it doesn't already exist. It also increments tag->num_fields. Adding fields directly to tag->fields without going through ApeTag_add_field is not recommended nor supported.

Returns 0 on success, <0 on error.

int ApeTag_remove_field(ApeTag* tag, char* key);

Removes the field with a matching key from tag->fields. Also decrements tag->num_fields. Removing fields directly from tag->fields without going through ApeTag_remove_field is not recommended nor supported.

Returns 0 on success, 1 if the field did not exist tag->fields, <0 on error.

int ApeTag_clear_fields(ApeTag* tag);

Frees all ApeItems referenced in tag->fields, and then closes tag->fields.

Returns 0 on success, -1 on error.

AUTHOR

apetag is written by Jeremy Evans. You can contact the author at code@jeremyevans.net, and suggestions or bug reports are welcome.

SEE ALSO

apeinfo(1), malloc(3), ferror(3)