add FLAC__metadata_chain_read_with_callbacks()
authorJosh Coalson <jcoalson@users.sourceforce.net>
Sat, 10 Jul 2004 22:28:03 +0000 (22:28 +0000)
committerJosh Coalson <jcoalson@users.sourceforce.net>
Sat, 10 Jul 2004 22:28:03 +0000 (22:28 +0000)
include/FLAC/metadata.h
src/libFLAC/metadata_iterators.c

index 3e72c67..7164678 100644 (file)
@@ -585,9 +585,12 @@ typedef enum {
        FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR,
        /**< Memory allocation failed */
 
-       FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR
+       FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR,
        /**< The caller violated an assertion or an unexpected error occurred */
 
+       FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS
+       /**< One or more of the required callbacks was NULL */
+
 } FLAC__Metadata_ChainStatus;
 
 /** Maps a FLAC__Metadata_ChainStatus to a C string.
@@ -640,6 +643,24 @@ FLAC_API FLAC__Metadata_ChainStatus FLAC__metadata_chain_status(FLAC__Metadata_C
  */
 FLAC_API FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const char *filename);
 
+/** Read all metadata from a FLAC stream into the chain via I/O callbacks.
+ *
+ * \param chain    A pointer to an existing chain.
+ * \param handle   The I/O handle of the FLAC stream to read.  The
+ *                 handle will be closed after the metadata is read.
+ * \param callbacks
+ *                 A set of callbacks to use for I/O.  The mandatory
+ *                 callbacks are \a read, \a seek, \a tell, and
+ *                 \a close.
+ * \assert
+ *    \code chain != NULL \endcode
+ * \retval FLAC__bool
+ *    \c true if a valid list of metadata blocks was read from
+ *    \a handle, else \c false.  On failure, check the status with
+ *    FLAC__metadata_chain_status().
+ */
+FLAC_API FLAC__bool FLAC__metadata_chain_read_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks);
+
 /** Write all metadata out to the FLAC file.  This function tries to be as
  *  efficient as possible; how the metadata is actually written is shown by
  *  the following:
index f00af24..19bf015 100644 (file)
@@ -740,7 +740,7 @@ typedef struct FLAC__Metadata_Node {
 } FLAC__Metadata_Node;
 
 struct FLAC__Metadata_Chain {
-       char *filename;
+       char *filename; /* will be NULL if using callbacks */
        FLAC__Metadata_Node *head;
        FLAC__Metadata_Node *tail;
        unsigned nodes;
@@ -772,7 +772,8 @@ FLAC_API const char * const FLAC__Metadata_ChainStatusString[] = {
        "FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR",
        "FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR",
        "FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR",
-       "FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR"
+       "FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR",
+       "FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS"
 };
 
 
@@ -789,6 +790,35 @@ static void node_delete_(FLAC__Metadata_Node *node)
        free(node);
 }
 
+static void chain_init_(FLAC__Metadata_Chain *chain)
+{
+       FLAC__ASSERT(0 != chain);
+
+       chain->filename = 0;
+       chain->head = chain->tail = 0;
+       chain->nodes = 0;
+       chain->status = FLAC__METADATA_CHAIN_STATUS_OK;
+       chain->initial_length = 0;
+}
+
+static void chain_clear_(FLAC__Metadata_Chain *chain)
+{
+       FLAC__Metadata_Node *node, *next;
+
+       FLAC__ASSERT(0 != chain);
+
+       for(node = chain->head; node; ) {
+               next = node->next;
+               node_delete_(node);
+               node = next;
+       }
+
+       if(0 != chain->filename)
+               free(chain->filename);
+
+       chain_init_(chain);
+}
+
 static void chain_append_node_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node)
 {
        FLAC__ASSERT(0 != chain);
@@ -1003,31 +1033,17 @@ FLAC_API FLAC__Metadata_Chain *FLAC__metadata_chain_new()
 {
        FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)calloc(1, sizeof(FLAC__Metadata_Chain));
 
-       if(0 != chain) {
-               chain->filename = 0;
-               chain->head = chain->tail = 0;
-               chain->nodes = 0;
-               chain->status = FLAC__METADATA_CHAIN_STATUS_OK;
-               chain->initial_length = 0;
-       }
+       if(0 != chain)
+               chain_init_(chain);
 
        return chain;
 }
 
 FLAC_API void FLAC__metadata_chain_delete(FLAC__Metadata_Chain *chain)
 {
-       FLAC__Metadata_Node *node, *next;
-
        FLAC__ASSERT(0 != chain);
 
-       for(node = chain->head; node; ) {
-               next = node->next;
-               node_delete_(node);
-               node = next;
-       }
-
-       if(0 != chain->filename)
-               free(chain->filename);
+       chain_clear_(chain);
 
        free(chain);
 }
@@ -1050,6 +1066,8 @@ FLAC_API FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const
        FLAC__ASSERT(0 != chain);
        FLAC__ASSERT(0 != filename);
 
+       chain_clear_(chain);
+
        if(0 == (chain->filename = strdup(filename))) {
                chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
                return false;
@@ -1063,6 +1081,27 @@ FLAC_API FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const
        if(!chain_read_cb_(chain, file, (FLAC__IOCallback_Read)fread, fseek_wrapper_, ftell_wrapper_, (FLAC__IOCallback_Close)fclose))
                return false; /* chain->status is already set by chain_read_cb_ */
 
+       /* chain_read_cb_() closes the file handle */
+
+       return true;
+}
+
+FLAC_API FLAC__bool FLAC__metadata_chain_read_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks)
+{
+       FILE *file;
+
+       FLAC__ASSERT(0 != chain);
+
+       chain_clear_(chain);
+
+       if (0 == callbacks.read || 0 == callbacks.seek || 0 == callbacks.tell || 0 == callbacks.close) {
+               chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS;
+               return false;
+       }
+
+       if(!chain_read_cb_(chain, handle, callbacks.read, callbacks.seek, callbacks.tell, callbacks.close))
+               return false; /* chain->status is already set by chain_read_cb_ */
+
        return true;
 }