This reverts commit 136114890f24f6418c3b1672d8e378902ed4db02.
This commit is contained in:
		
							parent
							
								
									dcb49c540f
								
							
						
					
					
						commit
						a4b4802897
					
				@ -19,8 +19,7 @@ struct File {
 | 
				
			|||||||
    FileType type;
 | 
					    FileType type;
 | 
				
			||||||
    FS_Error error_id; /**< Standard API error from FS_Error enum */
 | 
					    FS_Error error_id; /**< Standard API error from FS_Error enum */
 | 
				
			||||||
    int32_t internal_error_id; /**< Internal API error value */
 | 
					    int32_t internal_error_id; /**< Internal API error value */
 | 
				
			||||||
    void* storage; /**< Storage API pointer */
 | 
					    void* storage;
 | 
				
			||||||
    void* sort_data; /**< Sorted file list for directory */
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** File api structure
 | 
					/** File api structure
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,4 @@
 | 
				
			|||||||
#include "storage_processing.h"
 | 
					#include "storage_processing.h"
 | 
				
			||||||
#include "storage_sorting.h"
 | 
					 | 
				
			||||||
#include <m-list.h>
 | 
					#include <m-list.h>
 | 
				
			||||||
#include <m-dict.h>
 | 
					#include <m-dict.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -101,7 +100,7 @@ static FS_Error storage_get_data(Storage* app, FuriString* path, StorageData** s
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/******************* File Functions *******************/
 | 
					/******************* File Functions *******************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool storage_process_file_open(
 | 
					bool storage_process_file_open(
 | 
				
			||||||
    Storage* app,
 | 
					    Storage* app,
 | 
				
			||||||
    File* file,
 | 
					    File* file,
 | 
				
			||||||
    FuriString* path,
 | 
					    FuriString* path,
 | 
				
			||||||
@ -128,7 +127,7 @@ static bool storage_process_file_open(
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool storage_process_file_close(Storage* app, File* file) {
 | 
					bool storage_process_file_close(Storage* app, File* file) {
 | 
				
			||||||
    bool ret = false;
 | 
					    bool ret = false;
 | 
				
			||||||
    StorageData* storage = get_storage_by_file(file, app->storage);
 | 
					    StorageData* storage = get_storage_by_file(file, app->storage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -261,149 +260,9 @@ static bool storage_process_file_eof(Storage* app, File* file) {
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*************** Sorting Dir Functions ***************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static bool storage_process_dir_rewind_internal(StorageData* storage, File* file);
 | 
					 | 
				
			||||||
static bool storage_process_dir_read_internal(
 | 
					 | 
				
			||||||
    StorageData* storage,
 | 
					 | 
				
			||||||
    File* file,
 | 
					 | 
				
			||||||
    FileInfo* fileinfo,
 | 
					 | 
				
			||||||
    char* name,
 | 
					 | 
				
			||||||
    const uint16_t name_length);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int storage_sorted_file_record_compare(const void* sorted_a, const void* sorted_b) {
 | 
					 | 
				
			||||||
    SortedFileRecord* a = (SortedFileRecord*)sorted_a;
 | 
					 | 
				
			||||||
    SortedFileRecord* b = (SortedFileRecord*)sorted_b;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(a->info.flags & FSF_DIRECTORY && !(b->info.flags & FSF_DIRECTORY))
 | 
					 | 
				
			||||||
        return -1;
 | 
					 | 
				
			||||||
    else if(!(a->info.flags & FSF_DIRECTORY) && b->info.flags & FSF_DIRECTORY)
 | 
					 | 
				
			||||||
        return 1;
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        return furi_string_cmpi(a->name, b->name);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static bool storage_sorted_dir_read_next(
 | 
					 | 
				
			||||||
    SortedDir* dir,
 | 
					 | 
				
			||||||
    FileInfo* fileinfo,
 | 
					 | 
				
			||||||
    char* name,
 | 
					 | 
				
			||||||
    const uint16_t name_length) {
 | 
					 | 
				
			||||||
    bool ret = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(dir->index < dir->count) {
 | 
					 | 
				
			||||||
        SortedFileRecord* sorted = &dir->sorted[dir->index];
 | 
					 | 
				
			||||||
        if(fileinfo) {
 | 
					 | 
				
			||||||
            *fileinfo = sorted->info;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if(name) {
 | 
					 | 
				
			||||||
            strncpy(name, furi_string_get_cstr(sorted->name), name_length);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        dir->index++;
 | 
					 | 
				
			||||||
        ret = true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void storage_sorted_dir_rewind(SortedDir* dir) {
 | 
					 | 
				
			||||||
    dir->index = 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static bool storage_sorted_dir_prepare(SortedDir* dir, StorageData* storage, File* file) {
 | 
					 | 
				
			||||||
    bool ret = true;
 | 
					 | 
				
			||||||
    dir->count = 0;
 | 
					 | 
				
			||||||
    dir->index = 0;
 | 
					 | 
				
			||||||
    FileInfo info;
 | 
					 | 
				
			||||||
    char name[SORTING_MAX_NAME_LENGTH + 1] = {0};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    furi_check(!dir->sorted);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    while(storage_process_dir_read_internal(storage, file, &info, name, SORTING_MAX_NAME_LENGTH)) {
 | 
					 | 
				
			||||||
        if(memmgr_get_free_heap() < SORTING_MIN_FREE_MEMORY) {
 | 
					 | 
				
			||||||
            ret = false;
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(dir->count == 0) { //-V547
 | 
					 | 
				
			||||||
            dir->sorted = malloc(sizeof(SortedFileRecord));
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            // Our realloc actually mallocs a new block and copies the data over,
 | 
					 | 
				
			||||||
            // so we need to check if we have enough memory for the new block
 | 
					 | 
				
			||||||
            size_t size = sizeof(SortedFileRecord) * (dir->count + 1);
 | 
					 | 
				
			||||||
            if(memmgr_heap_get_max_free_block() >= size) {
 | 
					 | 
				
			||||||
                dir->sorted =
 | 
					 | 
				
			||||||
                    realloc(dir->sorted, sizeof(SortedFileRecord) * (dir->count + 1)); //-V701
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                ret = false;
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        dir->sorted[dir->count].name = furi_string_alloc_set(name);
 | 
					 | 
				
			||||||
        dir->sorted[dir->count].info = info;
 | 
					 | 
				
			||||||
        dir->count++;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void storage_sorted_dir_sort(SortedDir* dir) {
 | 
					 | 
				
			||||||
    qsort(dir->sorted, dir->count, sizeof(SortedFileRecord), storage_sorted_file_record_compare);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void storage_sorted_dir_clear_data(SortedDir* dir) {
 | 
					 | 
				
			||||||
    if(dir->sorted != NULL) {
 | 
					 | 
				
			||||||
        for(size_t i = 0; i < dir->count; i++) {
 | 
					 | 
				
			||||||
            furi_string_free(dir->sorted[i].name);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        free(dir->sorted);
 | 
					 | 
				
			||||||
        dir->sorted = NULL;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void storage_file_remove_sort_data(File* file) {
 | 
					 | 
				
			||||||
    if(file->sort_data != NULL) {
 | 
					 | 
				
			||||||
        storage_sorted_dir_clear_data(file->sort_data);
 | 
					 | 
				
			||||||
        free(file->sort_data);
 | 
					 | 
				
			||||||
        file->sort_data = NULL;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void storage_file_add_sort_data(File* file, StorageData* storage) {
 | 
					 | 
				
			||||||
    file->sort_data = malloc(sizeof(SortedDir));
 | 
					 | 
				
			||||||
    if(storage_sorted_dir_prepare(file->sort_data, storage, file)) {
 | 
					 | 
				
			||||||
        storage_sorted_dir_sort(file->sort_data);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        storage_file_remove_sort_data(file);
 | 
					 | 
				
			||||||
        storage_process_dir_rewind_internal(storage, file);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static bool storage_file_has_sort_data(File* file) {
 | 
					 | 
				
			||||||
    return file->sort_data != NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/******************* Dir Functions *******************/
 | 
					/******************* Dir Functions *******************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool storage_process_dir_read_internal(
 | 
					bool storage_process_dir_open(Storage* app, File* file, FuriString* path) {
 | 
				
			||||||
    StorageData* storage,
 | 
					 | 
				
			||||||
    File* file,
 | 
					 | 
				
			||||||
    FileInfo* fileinfo,
 | 
					 | 
				
			||||||
    char* name,
 | 
					 | 
				
			||||||
    const uint16_t name_length) {
 | 
					 | 
				
			||||||
    bool ret = false;
 | 
					 | 
				
			||||||
    FS_CALL(storage, dir.read(storage, file, fileinfo, name, name_length));
 | 
					 | 
				
			||||||
    return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static bool storage_process_dir_rewind_internal(StorageData* storage, File* file) {
 | 
					 | 
				
			||||||
    bool ret = false;
 | 
					 | 
				
			||||||
    FS_CALL(storage, dir.rewind(storage, file));
 | 
					 | 
				
			||||||
    return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static bool storage_process_dir_open(Storage* app, File* file, FuriString* path) {
 | 
					 | 
				
			||||||
    bool ret = false;
 | 
					    bool ret = false;
 | 
				
			||||||
    StorageData* storage;
 | 
					    StorageData* storage;
 | 
				
			||||||
    file->error_id = storage_get_data(app, path, &storage);
 | 
					    file->error_id = storage_get_data(app, path, &storage);
 | 
				
			||||||
@ -414,17 +273,13 @@ static bool storage_process_dir_open(Storage* app, File* file, FuriString* path)
 | 
				
			|||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            storage_push_storage_file(file, path, storage);
 | 
					            storage_push_storage_file(file, path, storage);
 | 
				
			||||||
            FS_CALL(storage, dir.open(storage, file, cstr_path_without_vfs_prefix(path)));
 | 
					            FS_CALL(storage, dir.open(storage, file, cstr_path_without_vfs_prefix(path)));
 | 
				
			||||||
 | 
					 | 
				
			||||||
            if(file->error_id == FSE_OK) {
 | 
					 | 
				
			||||||
                storage_file_add_sort_data(file, storage);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool storage_process_dir_close(Storage* app, File* file) {
 | 
					bool storage_process_dir_close(Storage* app, File* file) {
 | 
				
			||||||
    bool ret = false;
 | 
					    bool ret = false;
 | 
				
			||||||
    StorageData* storage = get_storage_by_file(file, app->storage);
 | 
					    StorageData* storage = get_storage_by_file(file, app->storage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -432,7 +287,6 @@ static bool storage_process_dir_close(Storage* app, File* file) {
 | 
				
			|||||||
        file->error_id = FSE_INVALID_PARAMETER;
 | 
					        file->error_id = FSE_INVALID_PARAMETER;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        FS_CALL(storage, dir.close(storage, file));
 | 
					        FS_CALL(storage, dir.close(storage, file));
 | 
				
			||||||
        storage_file_remove_sort_data(file);
 | 
					 | 
				
			||||||
        storage_pop_storage_file(file, storage);
 | 
					        storage_pop_storage_file(file, storage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        StorageEvent event = {.type = StorageEventTypeDirClose};
 | 
					        StorageEvent event = {.type = StorageEventTypeDirClose};
 | 
				
			||||||
@ -442,7 +296,7 @@ static bool storage_process_dir_close(Storage* app, File* file) {
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool storage_process_dir_read(
 | 
					bool storage_process_dir_read(
 | 
				
			||||||
    Storage* app,
 | 
					    Storage* app,
 | 
				
			||||||
    File* file,
 | 
					    File* file,
 | 
				
			||||||
    FileInfo* fileinfo,
 | 
					    FileInfo* fileinfo,
 | 
				
			||||||
@ -454,34 +308,20 @@ static bool storage_process_dir_read(
 | 
				
			|||||||
    if(storage == NULL) {
 | 
					    if(storage == NULL) {
 | 
				
			||||||
        file->error_id = FSE_INVALID_PARAMETER;
 | 
					        file->error_id = FSE_INVALID_PARAMETER;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        if(storage_file_has_sort_data(file)) {
 | 
					        FS_CALL(storage, dir.read(storage, file, fileinfo, name, name_length));
 | 
				
			||||||
            ret = storage_sorted_dir_read_next(file->sort_data, fileinfo, name, name_length);
 | 
					 | 
				
			||||||
            if(ret) {
 | 
					 | 
				
			||||||
                file->error_id = FSE_OK;
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                file->error_id = FSE_NOT_EXIST;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            ret = storage_process_dir_read_internal(storage, file, fileinfo, name, name_length);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool storage_process_dir_rewind(Storage* app, File* file) {
 | 
					bool storage_process_dir_rewind(Storage* app, File* file) {
 | 
				
			||||||
    bool ret = false;
 | 
					    bool ret = false;
 | 
				
			||||||
    StorageData* storage = get_storage_by_file(file, app->storage);
 | 
					    StorageData* storage = get_storage_by_file(file, app->storage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(storage == NULL) {
 | 
					    if(storage == NULL) {
 | 
				
			||||||
        file->error_id = FSE_INVALID_PARAMETER;
 | 
					        file->error_id = FSE_INVALID_PARAMETER;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        if(storage_file_has_sort_data(file)) {
 | 
					        FS_CALL(storage, dir.rewind(storage, file));
 | 
				
			||||||
            storage_sorted_dir_rewind(file->sort_data);
 | 
					 | 
				
			||||||
            ret = true;
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            ret = storage_process_dir_rewind_internal(storage, file);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
@ -621,7 +461,7 @@ static FS_Error storage_process_sd_status(Storage* app) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/******************** Aliases processing *******************/
 | 
					/******************** Aliases processing *******************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void storage_process_alias(
 | 
					void storage_process_alias(
 | 
				
			||||||
    Storage* app,
 | 
					    Storage* app,
 | 
				
			||||||
    FuriString* path,
 | 
					    FuriString* path,
 | 
				
			||||||
    FuriThreadId thread_id,
 | 
					    FuriThreadId thread_id,
 | 
				
			||||||
@ -665,7 +505,7 @@ static void storage_process_alias(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/****************** API calls processing ******************/
 | 
					/****************** API calls processing ******************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void storage_process_message_internal(Storage* app, StorageMessage* message) {
 | 
					void storage_process_message_internal(Storage* app, StorageMessage* message) {
 | 
				
			||||||
    FuriString* path = NULL;
 | 
					    FuriString* path = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch(message->command) {
 | 
					    switch(message->command) {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,22 +0,0 @@
 | 
				
			|||||||
#pragma once
 | 
					 | 
				
			||||||
#include <furi.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define SORTING_MAX_NAME_LENGTH 255
 | 
					 | 
				
			||||||
#define SORTING_MIN_FREE_MEMORY (1024 * 40)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief Sorted file record, holds file name and info
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
    FuriString* name;
 | 
					 | 
				
			||||||
    FileInfo info;
 | 
					 | 
				
			||||||
} SortedFileRecord;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief Sorted directory, holds sorted file records, count and current index
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
    SortedFileRecord* sorted;
 | 
					 | 
				
			||||||
    size_t count;
 | 
					 | 
				
			||||||
    size_t index;
 | 
					 | 
				
			||||||
} SortedDir;
 | 
					 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user