📄 metadata_iterators.c
字号:
return iterator->type;}FLAC_API FLAC__StreamMetadata *FLAC__metadata_simple_iterator_get_block(FLAC__Metadata_SimpleIterator *iterator){ FLAC__StreamMetadata *block = FLAC__metadata_object_new(iterator->type); FLAC__ASSERT(0 != iterator); FLAC__ASSERT(0 != iterator->file); if(0 != block) { block->is_last = iterator->is_last; block->length = iterator->length; if(!read_metadata_block_data_(iterator, block)) { FLAC__metadata_object_delete(block); return 0; } /* back up to the beginning of the block data to stay consistent */ if(0 != fseek(iterator->file, iterator->offset[iterator->depth] + FLAC__STREAM_METADATA_HEADER_LENGTH, SEEK_SET)) { iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; FLAC__metadata_object_delete(block); return 0; } } else iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; return block;}FLAC_API FLAC__bool FLAC__metadata_simple_iterator_set_block(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool use_padding){ FLAC__ASSERT_DECLARATION(long debug_target_offset = iterator->offset[iterator->depth];) FLAC__bool ret; FLAC__ASSERT(0 != iterator); FLAC__ASSERT(0 != iterator->file); FLAC__ASSERT(0 != block); if(!iterator->is_writable) { iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE; return false; } if(iterator->type == FLAC__METADATA_TYPE_STREAMINFO || block->type == FLAC__METADATA_TYPE_STREAMINFO) { if(iterator->type != block->type) { iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT; return false; } } block->is_last = iterator->is_last; if(iterator->length == block->length) return write_metadata_block_stationary_(iterator, block); else if(iterator->length > block->length) { if(use_padding && iterator->length >= FLAC__STREAM_METADATA_HEADER_LENGTH + block->length) { ret = write_metadata_block_stationary_with_padding_(iterator, block, iterator->length - FLAC__STREAM_METADATA_HEADER_LENGTH - block->length, block->is_last); FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset); FLAC__ASSERT(!ret || ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH); return ret; } else { ret = rewrite_whole_file_(iterator, block, /*append=*/false); FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset); FLAC__ASSERT(!ret || ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH); return ret; } } else /* iterator->length < block->length */ { unsigned padding_leftover = 0; FLAC__bool padding_is_last = false; if(use_padding) { /* first see if we can even use padding */ if(iterator->is_last) { use_padding = false; } else { const unsigned extra_padding_bytes_required = block->length - iterator->length; simple_iterator_push_(iterator); if(!FLAC__metadata_simple_iterator_next(iterator)) { (void)simple_iterator_pop_(iterator); return false; } if(iterator->type != FLAC__METADATA_TYPE_PADDING) { use_padding = false; } else { if(FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length == extra_padding_bytes_required) { padding_leftover = 0; block->is_last = iterator->is_last; } else if(iterator->length < extra_padding_bytes_required) use_padding = false; else { padding_leftover = FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length - extra_padding_bytes_required; padding_is_last = iterator->is_last; block->is_last = false; } } if(!simple_iterator_pop_(iterator)) return false; } } if(use_padding) { if(padding_leftover == 0) { ret = write_metadata_block_stationary_(iterator, block); FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset); FLAC__ASSERT(!ret || ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH); return ret; } else { FLAC__ASSERT(padding_leftover >= FLAC__STREAM_METADATA_HEADER_LENGTH); ret = write_metadata_block_stationary_with_padding_(iterator, block, padding_leftover - FLAC__STREAM_METADATA_HEADER_LENGTH, padding_is_last); FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset); FLAC__ASSERT(!ret || ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH); return ret; } } else { ret = rewrite_whole_file_(iterator, block, /*append=*/false); FLAC__ASSERT(!ret || iterator->offset[iterator->depth] == debug_target_offset); FLAC__ASSERT(!ret || ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH); return ret; } }}FLAC_API FLAC__bool FLAC__metadata_simple_iterator_insert_block_after(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool use_padding){ unsigned padding_leftover = 0; FLAC__bool padding_is_last = false; FLAC__ASSERT_DECLARATION(long debug_target_offset = iterator->offset[iterator->depth] + FLAC__STREAM_METADATA_HEADER_LENGTH + iterator->length;) FLAC__bool ret; FLAC__ASSERT(0 != iterator); FLAC__ASSERT(0 != iterator->file); FLAC__ASSERT(0 != block); if(!iterator->is_writable) return false; if(block->type == FLAC__METADATA_TYPE_STREAMINFO) { iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT; return false; } block->is_last = iterator->is_last; if(use_padding) { /* first see if we can even use padding */ if(iterator->is_last) { use_padding = false; } else { simple_iterator_push_(iterator); if(!FLAC__metadata_simple_iterator_next(iterator)) { (void)simple_iterator_pop_(iterator); return false; } if(iterator->type != FLAC__METADATA_TYPE_PADDING) { use_padding = false; } else { if(iterator->length == block->length) { padding_leftover = 0; block->is_last = iterator->is_last; } else if(iterator->length < FLAC__STREAM_METADATA_HEADER_LENGTH + block->length) use_padding = false; else { padding_leftover = iterator->length - block->length; padding_is_last = iterator->is_last; block->is_last = false; } } if(!simple_iterator_pop_(iterator)) return false; } } if(use_padding) { /* move to the next block, which is suitable padding */ if(!FLAC__metadata_simple_iterator_next(iterator)) return false; if(padding_leftover == 0) { ret = write_metadata_block_stationary_(iterator, block); FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset); FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH); return ret; } else { FLAC__ASSERT(padding_leftover >= FLAC__STREAM_METADATA_HEADER_LENGTH); ret = write_metadata_block_stationary_with_padding_(iterator, block, padding_leftover - FLAC__STREAM_METADATA_HEADER_LENGTH, padding_is_last); FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset); FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH); return ret; } } else { ret = rewrite_whole_file_(iterator, block, /*append=*/true); FLAC__ASSERT(iterator->offset[iterator->depth] == debug_target_offset); FLAC__ASSERT(ftell(iterator->file) == debug_target_offset + (long)FLAC__STREAM_METADATA_HEADER_LENGTH); return ret; }}FLAC_API FLAC__bool FLAC__metadata_simple_iterator_delete_block(FLAC__Metadata_SimpleIterator *iterator, FLAC__bool use_padding){ FLAC__ASSERT_DECLARATION(long debug_target_offset = iterator->offset[iterator->depth];) FLAC__bool ret; if(iterator->type == FLAC__METADATA_TYPE_STREAMINFO) { iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT; return false; } if(use_padding) { FLAC__StreamMetadata *padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING); if(0 == padding) { iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; return false; } padding->length = iterator->length; if(!FLAC__metadata_simple_iterator_set_block(iterator, padding, false)) { FLAC__metadata_object_delete(padding); return false; } FLAC__metadata_object_delete(padding); if(!FLAC__metadata_simple_iterator_prev(iterator)) return false; FLAC__ASSERT(iterator->offset[iterator->depth] + (long)FLAC__STREAM_METADATA_HEADER_LENGTH + (long)iterator->length == debug_target_offset); FLAC__ASSERT(ftell(iterator->file) + (long)iterator->length == debug_target_offset); return true; } else { ret = rewrite_whole_file_(iterator, 0, /*append=*/false); FLAC__ASSERT(iterator->offset[iterator->depth] + (long)FLAC__STREAM_METADATA_HEADER_LENGTH + (long)iterator->length == debug_target_offset); FLAC__ASSERT(ftell(iterator->file) + (long)iterator->length == debug_target_offset); return ret; }}/**************************************************************************** * * Level 2 implementation * ***************************************************************************/typedef struct FLAC__Metadata_Node { FLAC__StreamMetadata *data; struct FLAC__Metadata_Node *prev, *next;} FLAC__Metadata_Node;struct FLAC__Metadata_Chain { char *filename; /* will be NULL if using callbacks */ FLAC__Metadata_Node *head; FLAC__Metadata_Node *tail; unsigned nodes; FLAC__Metadata_ChainStatus status; long first_offset, last_offset; /*@@@ 2G limit */ /* * This is the length of the chain initially read from the FLAC file. * it is used to compare against the current length to decide whether * or not the whole file has to be rewritten. */ unsigned initial_length; /*@@@ 4G limit */};struct FLAC__Metadata_Iterator { FLAC__Metadata_Chain *chain; FLAC__Metadata_Node *current;};FLAC_API const char * const FLAC__Metadata_ChainStatusString[] = { "FLAC__METADATA_CHAIN_STATUS_OK", "FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT", "FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE", "FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE", "FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE", "FLAC__METADATA_CHAIN_STATUS_BAD_METADATA", "FLAC__METADATA_CHAIN_STATUS_READ_ERROR", "FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR", "FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR", "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_INVALID_CALLBACKS", "FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH", "FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL"};static FLAC__Metadata_Node *node_new_(){ return (FLAC__Metadata_Node*)calloc(1, sizeof(FLAC__Metadata_Node));}static void node_delete_(FLAC__Metadata_Node *node){ FLAC__ASSERT(0 != node); if(0 != node->data) FLAC__metadata_object_delete(node->data); 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); FLAC__ASSERT(0 != node); FLAC__ASSERT(0 != node->data); node->next = node->prev = 0; node->data->is_last = true; if(0 != chain->tail) chain->tail->data->is_last = false; if(0 == chain->head) chain->head = node; else { FLAC__ASSERT(0 != chain->tail); chain->tail->next = node; node->prev = chain->tail; } chain->tail = node; chain->nodes++;}static void chain_remove_node_(FLAC__Metadata_Chain *chain, FLAC__Metadata_Node *node){ FLAC__ASSERT(0 != chain); FLAC__ASSERT(0 != node); if(node == chain->head) chain->head = node->next; else node->prev->next = node->next; if(node == chain->tail) chain->tail = node->prev;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -