/* Retrieves a specific entry from the array * * Uses the entry_compare_function to determine the similarity of the entries * The entry_compare_function should return LIBCDATA_BTREE_COMPARE_LESS, * LIBCDATA_BTREE_COMPARE_EQUAL, LIBCDATA_BTREE_COMPARE_GREATER if successful or -1 on error * * Returns 1 if successful, 0 if no such value or -1 on error */ int libcdata_array_get_entry_by_value( libcdata_array_t *array, intptr_t *entry, int (*entry_compare_function)( intptr_t *first_entry, intptr_t *second_entry, libcerror_error_t **error ), intptr_t **existing_entry, libcerror_error_t **error ) { libcdata_internal_array_t *internal_array = NULL; static char *function = "libcdata_array_get_entry_by_value"; int compare_result = 0; int entry_index = 0; int result = 0; if( array == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid array.", function ); return( -1 ); } internal_array = (libcdata_internal_array_t *) array; if( entry_compare_function == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid entry compare function.", function ); return( -1 ); } if( existing_entry == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid existing entry.", function ); return( -1 ); } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA ) if( libcthreads_read_write_lock_grab_for_read( internal_array->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for reading.", function ); return( -1 ); } #endif if( internal_array->entries != NULL ) { for( entry_index = 0; entry_index < internal_array->number_of_entries; entry_index++ ) { compare_result = entry_compare_function( entry, internal_array->entries[ entry_index ], error ); if( compare_result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to compare entry: %d.", function, entry_index ); result = -1; break; } else if( compare_result == LIBCDATA_COMPARE_EQUAL ) { *existing_entry = internal_array->entries[ entry_index ]; result = 1; break; } } } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA ) if( libcthreads_read_write_lock_release_for_read( internal_array->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for reading.", function ); return( -1 ); } #endif return( result ); }
/* Inserts an entry in the array * * Uses the entry_compare_function to determine the order of the entries * The entry_compare_function should return LIBCDATA_COMPARE_LESS, * LIBCDATA_COMPARE_EQUAL, LIBCDATA_COMPARE_GREATER if successful or -1 on error * * Duplicate entries are allowed by default and inserted after the last duplicate entry. * Only allowing unique entries can be enforced by setting the flag LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES * * Returns 1 if successful, 0 if the node already exists or -1 on error */ int libcdata_array_insert_entry( libcdata_array_t *array, int *entry_index, intptr_t *entry, int (*entry_compare_function)( intptr_t *first_entry, intptr_t *second_entry, libcerror_error_t **error ), uint8_t insert_flags, libcerror_error_t **error ) { libcdata_internal_array_t *internal_array = NULL; static char *function = "libcdata_tree_node_insert_node"; int compare_result = 0; int entry_iterator = 0; int result = 1; if( array == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid array.", function ); return( -1 ); } internal_array = (libcdata_internal_array_t *) array; if( entry_index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid entry index.", function ); return( -1 ); } if( entry_compare_function == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid entry compare function.", function ); return( -1 ); } if( ( insert_flags & ~( LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES ) ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported insert flags: 0x%02" PRIx8 ".", function, insert_flags ); return( -1 ); } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA ) if( libcthreads_read_write_lock_grab_for_write( internal_array->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to grab read/write lock for writing.", function ); return( -1 ); } #endif if( internal_array->entries != NULL ) { for( entry_iterator = 0; entry_iterator < internal_array->number_of_entries; entry_iterator++ ) { compare_result = entry_compare_function( entry, internal_array->entries[ entry_iterator ], error ); if( compare_result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to compare entry: %d.", function, entry_iterator ); goto on_error; } else if( compare_result == LIBCDATA_COMPARE_EQUAL ) { if( ( insert_flags & LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES ) != 0 ) { result = 0; break; } } else if( compare_result == LIBCDATA_COMPARE_LESS ) { result = 1; break; } else if( compare_result != LIBCDATA_COMPARE_GREATER ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported entry compare function return value: %d.", function, compare_result ); goto on_error; } } } if( result != 0 ) { if( ( internal_array->entries != NULL ) && ( compare_result == LIBCDATA_COMPARE_LESS ) ) { *entry_index = entry_iterator; if( libcdata_internal_array_resize( internal_array, internal_array->number_of_entries + 1, NULL, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED, "%s: unable to resize array.", function ); goto on_error; } for( entry_iterator = internal_array->number_of_entries - 1; entry_iterator > *entry_index; entry_iterator-- ) { internal_array->entries[ entry_iterator ] = internal_array->entries[ entry_iterator - 1 ]; } internal_array->entries[ *entry_index ] = entry; } else { *entry_index = internal_array->number_of_entries; if( libcdata_internal_array_resize( internal_array, internal_array->number_of_entries + 1, NULL, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED, "%s: unable to resize array.", function ); goto on_error; } if( internal_array->entries == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid array - missing entries.", function ); goto on_error; } internal_array->entries[ *entry_index ] = entry; } } #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA ) if( libcthreads_read_write_lock_release_for_write( internal_array->read_write_lock, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_SET_FAILED, "%s: unable to release read/write lock for writing.", function ); return( -1 ); } #endif return( result ); on_error: #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA ) libcthreads_read_write_lock_release_for_write( internal_array->read_write_lock, NULL ); #endif return( -1 ); }
/* Inserts an entry in the array * * Uses the entry_compare_function to determine the order of the entries * The entry_compare_function should return LIBODRAW_ARRAY_COMPARE_LESS, * LIBODRAW_ARRAY_COMPARE_EQUAL, LIBODRAW_ARRAY_COMPARE_GREATER if successful or -1 on error * * Duplicate entries are allowed by default and inserted after the last duplicate entry. * Only allowing unique entries can be enforced by setting the flag LIBODRAW_ARRAY_INSERT_FLAG_UNIQUE_ENTRIES * * Returns 1 if successful, 0 if the node already exists or -1 on error */ int libodraw_array_insert_entry( libodraw_array_t *array, int *entry_index, intptr_t *entry, int (*entry_compare_function)( intptr_t *first_entry, intptr_t *second_entry, libcerror_error_t **error ), uint8_t insert_flags, libcerror_error_t **error ) { static char *function = "libodraw_tree_node_insert_node"; int entry_iterator = 0; int result = -1; if( array == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid array.", function ); return( -1 ); } if( entry_index == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid entry index.", function ); return( -1 ); } if( entry_compare_function == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, "%s: invalid entry compare function.", function ); return( -1 ); } if( ( insert_flags & ~( LIBODRAW_ARRAY_INSERT_FLAG_UNIQUE_ENTRIES ) ) != 0 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported insert flags: 0x%02" PRIx8 ".", function, insert_flags ); return( -1 ); } if( array->entries != NULL ) { for( entry_iterator = 0; entry_iterator < array->number_of_entries; entry_iterator++ ) { result = entry_compare_function( entry, array->entries[ entry_iterator ], error ); if( result == -1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_GET_FAILED, "%s: unable to compare entry: %d.", function, entry_iterator ); return( -1 ); } else if( result == LIBODRAW_ARRAY_COMPARE_EQUAL ) { if( ( insert_flags & LIBODRAW_ARRAY_INSERT_FLAG_UNIQUE_ENTRIES ) != 0 ) { return( 0 ); } } else if( result == LIBODRAW_ARRAY_COMPARE_LESS ) { break; } else if( result != LIBODRAW_ARRAY_COMPARE_GREATER ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, "%s: unsupported entry compare function return value: %d.", function, result ); return( -1 ); } } } if( ( array->entries != NULL ) && ( result == LIBODRAW_ARRAY_COMPARE_LESS ) ) { *entry_index = entry_iterator; if( libodraw_array_resize( array, array->number_of_entries + 1, NULL, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED, "%s: unable to resize array.", function ); return( -1 ); } if( array->entries == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid array - missing entries.", function ); return( -1 ); } for( entry_iterator = array->number_of_entries - 1; entry_iterator > *entry_index; entry_iterator-- ) { array->entries[ entry_iterator ] = array->entries[ entry_iterator - 1 ]; } array->entries[ *entry_index ] = entry; } else { *entry_index = array->number_of_entries; if( libodraw_array_resize( array, array->number_of_entries + 1, NULL, error ) != 1 ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED, "%s: unable to resize array.", function ); return( -1 ); } if( array->entries == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_RUNTIME, LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, "%s: invalid array - missing entries.", function ); return( -1 ); } array->entries[ *entry_index ] = entry; } return( 1 ); }