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