📄 metadata_iterators.c
字号:
chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; return false; } if(!copy_remaining_bytes_from_file_cb_(handle, read_cb, eof_cb, temp_handle, temp_write_cb, &status)) { chain->status = get_equivalent_status_(status); return false; } return true;}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_init_(chain); return chain;}FLAC_API void FLAC__metadata_chain_delete(FLAC__Metadata_Chain *chain){ FLAC__ASSERT(0 != chain); chain_clear_(chain); free(chain);}FLAC_API FLAC__Metadata_ChainStatus FLAC__metadata_chain_status(FLAC__Metadata_Chain *chain){ FLAC__Metadata_ChainStatus status; FLAC__ASSERT(0 != chain); status = chain->status; chain->status = FLAC__METADATA_CHAIN_STATUS_OK; return status;}FLAC_API FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const char *filename){ FILE *file; FLAC__bool ret; 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; } if(0 == (file = fopen(filename, "rb"))) { chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE; return false; } /* chain_read_cb_() sets chain->status for us */ ret = chain_read_cb_(chain, file, (FLAC__IOCallback_Read)fread, fseek_wrapper_, ftell_wrapper_); fclose(file); return ret;}FLAC_API FLAC__bool FLAC__metadata_chain_read_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks){ FLAC__ASSERT(0 != chain); chain_clear_(chain); if (0 == callbacks.read || 0 == callbacks.seek || 0 == callbacks.tell) { chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS; return false; } /* rewind */ if(0 != callbacks.seek(handle, 0, SEEK_SET)) { chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; return false; } if(!chain_read_cb_(chain, handle, callbacks.read, callbacks.seek, callbacks.tell)) return false; /* chain->status is already set by chain_read_cb_ */ return true;}FLAC_API FLAC__bool FLAC__metadata_chain_check_if_tempfile_needed(FLAC__Metadata_Chain *chain, FLAC__bool use_padding){ /* This does all the same checks that are in chain_prepare_for_write_() * but doesn't actually alter the chain. Make sure to update the logic * here if chain_prepare_for_write_() changes. */ const unsigned current_length = chain_calculate_length_(chain); FLAC__ASSERT(0 != chain); if(use_padding) { /* if the metadata shrank and the last block is padding, we just extend the last padding block */ if(current_length < chain->initial_length && chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) return false; /* if the metadata shrank more than 4 bytes then there's room to add another padding block */ else if(current_length + FLAC__STREAM_METADATA_HEADER_LENGTH <= chain->initial_length) return false; /* if the metadata grew but the last block is padding, try cutting the padding to restore the original length so we don't have to rewrite the whole file */ else if(current_length > chain->initial_length) { const unsigned delta = current_length - chain->initial_length; if(chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) { /* if the delta is exactly the size of the last padding block, remove the padding block */ if(chain->tail->data->length + FLAC__STREAM_METADATA_HEADER_LENGTH == delta) return false; /* if there is at least 'delta' bytes of padding, trim the padding down */ else if(chain->tail->data->length >= delta) return false; } } } return (current_length != chain->initial_length);}FLAC_API FLAC__bool FLAC__metadata_chain_write(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__bool preserve_file_stats){ const char *tempfile_path_prefix = 0; unsigned current_length; FLAC__ASSERT(0 != chain); if (0 == chain->filename) { chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH; return false; } current_length = chain_prepare_for_write_(chain, use_padding); /* a return value of 0 means there was an error; chain->status is already set */ if (0 == current_length) return false; if(current_length == chain->initial_length) { if(!chain_rewrite_metadata_in_place_(chain)) return false; } else { if(!chain_rewrite_file_(chain, tempfile_path_prefix)) return false; /* recompute lengths and offsets */ { const FLAC__Metadata_Node *node; chain->initial_length = current_length; chain->last_offset = chain->first_offset; for(node = chain->head; node; node = node->next) chain->last_offset += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length); } } return true;}FLAC_API FLAC__bool FLAC__metadata_chain_write_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks){ unsigned current_length; FLAC__ASSERT(0 != chain); if (0 != chain->filename) { chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH; return false; } if (0 == callbacks.write || 0 == callbacks.seek) { chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS; return false; } if (FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) { chain->status = FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL; return false; } current_length = chain_prepare_for_write_(chain, use_padding); /* a return value of 0 means there was an error; chain->status is already set */ if (0 == current_length) return false; FLAC__ASSERT(current_length == chain->initial_length); return chain_rewrite_metadata_in_place_cb_(chain, handle, callbacks.write, callbacks.seek);}FLAC_API FLAC__bool FLAC__metadata_chain_write_with_callbacks_and_tempfile(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks, FLAC__IOHandle temp_handle, FLAC__IOCallbacks temp_callbacks){ unsigned current_length; FLAC__ASSERT(0 != chain); if (0 != chain->filename) { chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH; return false; } if (0 == callbacks.read || 0 == callbacks.seek || 0 == callbacks.eof) { chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS; return false; } if (0 == temp_callbacks.write) { chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS; return false; } if (!FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) { chain->status = FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL; return false; } current_length = chain_prepare_for_write_(chain, use_padding); /* a return value of 0 means there was an error; chain->status is already set */ if (0 == current_length) return false; FLAC__ASSERT(current_length != chain->initial_length); /* rewind */ if(0 != callbacks.seek(handle, 0, SEEK_SET)) { chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; return false; } if(!chain_rewrite_file_cb_(chain, handle, callbacks.read, callbacks.seek, callbacks.eof, temp_handle, temp_callbacks.write)) return false; /* recompute lengths and offsets */ { const FLAC__Metadata_Node *node; chain->initial_length = current_length; chain->last_offset = chain->first_offset; for(node = chain->head; node; node = node->next) chain->last_offset += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length); } return true;}FLAC_API void FLAC__metadata_chain_merge_padding(FLAC__Metadata_Chain *chain){ FLAC__Metadata_Node *node; FLAC__ASSERT(0 != chain); for(node = chain->head; node; ) { if(!chain_merge_adjacent_padding_(chain, node)) node = node->next; }}FLAC_API void FLAC__metadata_chain_sort_padding(FLAC__Metadata_Chain *chain){ FLAC__Metadata_Node *node, *save; unsigned i; FLAC__ASSERT(0 != chain); /* * Don't try and be too smart... this simple algo is good enough for * the small number of nodes that we deal with. */ for(i = 0, node = chain->head; i < chain->nodes; i++) { if(node->data->type == FLAC__METADATA_TYPE_PADDING) { save = node->next; chain_remove_node_(chain, node); chain_append_node_(chain, node); node = save; } else { node = node->next; } } FLAC__metadata_chain_merge_padding(chain);}FLAC_API FLAC__Metadata_Iterator *FLAC__metadata_iterator_new(){ FLAC__Metadata_Iterator *iterator = (FLAC__Metadata_Iterator*)calloc(1, sizeof(FLAC__Metadata_Iterator)); /* calloc() implies: iterator->current = 0; iterator->chain = 0; */ return iterator;}FLAC_API void FLAC__metadata_iterator_delete(FLAC__Metadata_Iterator *iterator){ FLAC__ASSERT(0 != iterator); free(iterator);}FLAC_API void FLAC__metadata_iterator_init(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Chain *chain){ FLAC__ASSERT(0 != iterator); FLAC__ASSERT(0 != chain); FLAC__ASSERT(0 != chain->head); iterator->chain = chain; iterator->current = chain->head;}FLAC_API FLAC__bool FLAC__metadata_iterator_next(FLAC__Metadata_Iterator *iterator){ FLAC__ASSERT(0 != iterator); if(0 == iterator->current || 0 == iterator->current->next) return false; iterator->current = iterator->current->next; return true;}FLAC_API FLAC__bool FLAC__metadata_iterator_prev(FLAC__Metadata_Iterator *iterator){ FLAC__ASSERT(0 != iterator); if(0 == iterator->current || 0 == iterator->current->prev) return false; iterator->current = iterator->current->prev; return true;}FLAC_API FLAC__MetadataType FLAC__metadata_iterator_get_block_type(const FLAC__Metadata_Iterator *iterator){ FLAC__ASSERT(0 != iterator); FLAC__ASSERT(0 != iterator->current); FLAC__ASSERT(0 != iterator->current->data); return iterator->current->data->type;}FLAC_API FLAC__StreamMetadata *FLAC__metadata_iterator_get_block(FLAC__Metadata_Iterator *iterator){ FLAC__ASSERT(0 != iterator); FLAC__ASSERT(0 != iterator->current); return iterator->current->data;}FLAC_API FLAC__bool FLAC__metadata_iterator_set_block(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block){ FLAC__ASSERT(0 != iterator); FLAC__ASSERT(0 != block); return FLAC__metadata_iterator_delete_block(iterator, false) && FLAC__metadata_iterator_insert_block_after(iterator, block);}FLAC_API FLAC__bool FLAC__metadata_iterator_delete_block(FLAC__Metadata_Iterator *iterator, FLAC__bool replace_with_padding){ FLAC__Metadata_Node *save; FLAC__ASSERT(0 != iterator); FLAC__ASSERT(0 != iterator->current); if(0 == iterator->current->prev) { FLAC__ASSERT(iterator->current->data->type == FLAC__METADATA_TYPE_STREAMINFO); return false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -