M*LIB: non-inlined strings, FuriString primitive (#1795)

* Quicksave 1
* Header stage complete
* Source stage complete
* Lint & merge fixes
* Includes
* Documentation step 1
* FBT: output free size considering BT STACK
* Documentation step 2
* py lint
* Fix music player plugin
* unit test stage 1: string allocator, mem, getters, setters, appends, compare, search.
* unit test: string equality
* unit test: string replace
* unit test: string start_with, end_with
* unit test: string trim
* unit test: utf-8
* Rename
* Revert fw_size changes
* Simplify CLI backspace handling
* Simplify CLI character insert
* Merge fixes
* Furi: correct filenaming and spelling
* Bt: remove furi string include

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
Sergey Gavrilov
2022-10-06 01:15:23 +10:00
committed by GitHub
parent 0f9ea925d3
commit 4bf29827f8
370 changed files with 5597 additions and 3963 deletions

View File

@@ -2,7 +2,6 @@
#include <core/common_defines.h>
#include <core/log.h>
#include "loader/loader.h"
#include "m-string.h"
#include <stdint.h>
#include <toolbox/dir_walk.h>
#include <toolbox/path.h>
@@ -28,25 +27,26 @@ bool storage_move_to_sd_perform(void) {
dir_walk_set_recursive(dir_walk, false);
dir_walk_set_filter_cb(dir_walk, storage_move_to_sd_check_entry, NULL);
string_t path_src, path_dst;
FuriString *path_src, *path_dst;
string_init(path_dst);
string_init(path_src);
path_dst = furi_string_alloc();
path_src = furi_string_alloc();
if(dir_walk_open(dir_walk, STORAGE_INT_PATH_PREFIX)) {
while(dir_walk_read(dir_walk, path_src, NULL) == DirWalkOK) {
string_set(path_dst, path_src);
string_replace_at(
furi_string_set(path_dst, path_src);
furi_string_replace_at(
path_dst, 0, strlen(STORAGE_INT_PATH_PREFIX), STORAGE_EXT_PATH_PREFIX);
storage_common_merge(storage, string_get_cstr(path_src), string_get_cstr(path_dst));
storage_simply_remove_recursive(storage, string_get_cstr(path_src));
storage_common_merge(
storage, furi_string_get_cstr(path_src), furi_string_get_cstr(path_dst));
storage_simply_remove_recursive(storage, furi_string_get_cstr(path_src));
}
}
dir_walk_free(dir_walk);
string_clear(path_dst);
string_clear(path_src);
furi_string_free(path_dst);
furi_string_free(path_src);
furi_record_close(RECORD_STORAGE);
@@ -62,8 +62,8 @@ static bool storage_move_to_sd_check(void) {
dir_walk_set_recursive(dir_walk, false);
dir_walk_set_filter_cb(dir_walk, storage_move_to_sd_check_entry, NULL);
string_t name;
string_init(name);
FuriString* name;
name = furi_string_alloc();
if(dir_walk_open(dir_walk, STORAGE_INT_PATH_PREFIX)) {
// if at least 1 entry is present, we should migrate
@@ -71,7 +71,7 @@ static bool storage_move_to_sd_check(void) {
}
dir_walk_free(dir_walk);
string_clear(name);
furi_string_free(name);
furi_record_close(RECORD_STORAGE);

View File

@@ -1,7 +1,6 @@
#include <furi.h>
#include <furi_hal.h>
#include <m-string.h>
#include <cli/cli.h>
#include <storage/storage.h>
#include <loader/loader.h>
@@ -12,16 +11,16 @@
#include <update_util/lfs_backup.h>
#include <update_util/update_operation.h>
typedef void (*cmd_handler)(string_t args);
typedef void (*cmd_handler)(FuriString* args);
typedef struct {
const char* command;
const cmd_handler handler;
} CliSubcommand;
static void updater_cli_install(string_t manifest_path) {
printf("Verifying update package at '%s'\r\n", string_get_cstr(manifest_path));
static void updater_cli_install(FuriString* manifest_path) {
printf("Verifying update package at '%s'\r\n", furi_string_get_cstr(manifest_path));
UpdatePrepareResult result = update_operation_prepare(string_get_cstr(manifest_path));
UpdatePrepareResult result = update_operation_prepare(furi_string_get_cstr(manifest_path));
if(result != UpdatePrepareResultOK) {
printf(
"Error: %s. Stopping update.\r\n",
@@ -33,23 +32,23 @@ static void updater_cli_install(string_t manifest_path) {
furi_hal_power_reset();
}
static void updater_cli_backup(string_t args) {
printf("Backup /int to '%s'\r\n", string_get_cstr(args));
static void updater_cli_backup(FuriString* args) {
printf("Backup /int to '%s'\r\n", furi_string_get_cstr(args));
Storage* storage = furi_record_open(RECORD_STORAGE);
bool success = lfs_backup_create(storage, string_get_cstr(args));
bool success = lfs_backup_create(storage, furi_string_get_cstr(args));
furi_record_close(RECORD_STORAGE);
printf("Result: %s\r\n", success ? "OK" : "FAIL");
}
static void updater_cli_restore(string_t args) {
printf("Restore /int from '%s'\r\n", string_get_cstr(args));
static void updater_cli_restore(FuriString* args) {
printf("Restore /int from '%s'\r\n", furi_string_get_cstr(args));
Storage* storage = furi_record_open(RECORD_STORAGE);
bool success = lfs_backup_unpack(storage, string_get_cstr(args));
bool success = lfs_backup_unpack(storage, furi_string_get_cstr(args));
furi_record_close(RECORD_STORAGE);
printf("Result: %s\r\n", success ? "OK" : "FAIL");
}
static void updater_cli_help(string_t args) {
static void updater_cli_help(FuriString* args) {
UNUSED(args);
printf("Commands:\r\n"
"\tinstall /ext/path/to/update.fuf - verify & apply update package\r\n"
@@ -64,25 +63,25 @@ static const CliSubcommand update_cli_subcommands[] = {
{.command = "help", .handler = updater_cli_help},
};
static void updater_cli_ep(Cli* cli, string_t args, void* context) {
static void updater_cli_ep(Cli* cli, FuriString* args, void* context) {
UNUSED(cli);
UNUSED(context);
string_t subcommand;
string_init(subcommand);
if(!args_read_string_and_trim(args, subcommand) || string_empty_p(args)) {
FuriString* subcommand;
subcommand = furi_string_alloc();
if(!args_read_string_and_trim(args, subcommand) || furi_string_empty(args)) {
updater_cli_help(args);
string_clear(subcommand);
furi_string_free(subcommand);
return;
}
for(size_t idx = 0; idx < COUNT_OF(update_cli_subcommands); ++idx) {
const CliSubcommand* subcmd_def = &update_cli_subcommands[idx];
if(string_cmp_str(subcommand, subcmd_def->command) == 0) {
string_clear(subcommand);
if(furi_string_cmp_str(subcommand, subcmd_def->command) == 0) {
furi_string_free(subcommand);
subcmd_def->handler(args);
return;
}
}
string_clear(subcommand);
furi_string_free(subcommand);
updater_cli_help(args);
}

View File

@@ -25,7 +25,7 @@ void updater_scene_loadcfg_on_enter(void* context) {
malloc(sizeof(UpdaterManifestProcessingState));
pending_upd->manifest = update_manifest_alloc();
if(update_manifest_init(pending_upd->manifest, string_get_cstr(updater->startup_arg))) {
if(update_manifest_init(pending_upd->manifest, furi_string_get_cstr(updater->startup_arg))) {
widget_add_string_element(
updater->widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, "Update");
@@ -37,7 +37,7 @@ void updater_scene_loadcfg_on_enter(void* context) {
32,
AlignCenter,
AlignCenter,
string_get_cstr(pending_upd->manifest->version),
furi_string_get_cstr(pending_upd->manifest->version),
true);
widget_add_button_element(
@@ -72,7 +72,7 @@ bool updater_scene_loadcfg_on_event(void* context, SceneManagerEvent event) {
switch(event.event) {
case UpdaterCustomEventStartUpdate:
updater->preparation_result =
update_operation_prepare(string_get_cstr(updater->startup_arg));
update_operation_prepare(furi_string_get_cstr(updater->startup_arg));
if(updater->preparation_result == UpdatePrepareResultOK) {
furi_hal_power_reset();
} else {
@@ -99,7 +99,7 @@ void updater_scene_loadcfg_on_exit(void* context) {
if(updater->pending_update) {
update_manifest_free(updater->pending_update->manifest);
string_clear(updater->pending_update->message);
furi_string_free(updater->pending_update->message);
}
widget_reset(updater->widget);

View File

@@ -35,10 +35,10 @@ static void
Updater* updater_alloc(const char* arg) {
Updater* updater = malloc(sizeof(Updater));
if(arg && strlen(arg)) {
string_init_set_str(updater->startup_arg, arg);
string_replace_str(updater->startup_arg, ANY_PATH(""), EXT_PATH(""));
updater->startup_arg = furi_string_alloc_set(arg);
furi_string_replace(updater->startup_arg, ANY_PATH(""), EXT_PATH(""));
} else {
string_init(updater->startup_arg);
updater->startup_arg = furi_string_alloc();
}
updater->storage = furi_record_open(RECORD_STORAGE);
@@ -94,7 +94,7 @@ Updater* updater_alloc(const char* arg) {
void updater_free(Updater* updater) {
furi_assert(updater);
string_clear(updater->startup_arg);
furi_string_free(updater->startup_arg);
if(updater->update_task) {
update_task_set_progress_cb(updater->update_task, NULL, NULL);
update_task_free(updater->update_task);

View File

@@ -35,7 +35,7 @@ typedef enum {
typedef struct UpdaterManifestProcessingState {
UpdateManifest* manifest;
string_t message;
FuriString* message;
bool ready_to_be_applied;
} UpdaterManifestProcessingState;
@@ -54,7 +54,7 @@ typedef struct {
UpdateTask* update_task;
Widget* widget;
string_t startup_arg;
FuriString* startup_arg;
int32_t idle_ticks;
} Updater;

View File

@@ -69,19 +69,19 @@ static const UpdateTaskStageGroupMap update_task_stage_progress[] = {
static UpdateTaskStageGroup update_task_get_task_groups(UpdateTask* update_task) {
UpdateTaskStageGroup ret = UpdateTaskStageGroupPreUpdate | UpdateTaskStageGroupPostUpdate;
UpdateManifest* manifest = update_task->manifest;
if(!string_empty_p(manifest->radio_image)) {
if(!furi_string_empty(manifest->radio_image)) {
ret |= UpdateTaskStageGroupRadio;
}
if(update_manifest_has_obdata(manifest)) {
ret |= UpdateTaskStageGroupOptionBytes;
}
if(!string_empty_p(manifest->firmware_dfu_image)) {
if(!furi_string_empty(manifest->firmware_dfu_image)) {
ret |= UpdateTaskStageGroupFirmware;
}
if(!string_empty_p(manifest->resource_bundle)) {
if(!furi_string_empty(manifest->resource_bundle)) {
ret |= UpdateTaskStageGroupResources;
}
if(!string_empty_p(manifest->splash_file)) {
if(!furi_string_empty(manifest->splash_file)) {
ret |= UpdateTaskStageGroupSplashscreen;
}
return ret;
@@ -109,14 +109,14 @@ void update_task_set_progress(UpdateTask* update_task, UpdateTaskStage stage, ui
}
/* Build error message with code "[stage_idx-stage_percent]" */
if(stage >= UpdateTaskStageError) {
string_printf(
furi_string_printf(
update_task->state.status,
"%s #[%d-%d]",
update_task_stage_descr[stage],
update_task->state.stage,
update_task->state.stage_progress);
} else {
string_set_str(update_task->state.status, update_task_stage_descr[stage]);
furi_string_set(update_task->state.status, update_task_stage_descr[stage]);
}
/* Store stage update */
update_task->state.stage = stage;
@@ -149,7 +149,7 @@ void update_task_set_progress(UpdateTask* update_task, UpdateTaskStage stage, ui
if(update_task->status_change_cb) {
(update_task->status_change_cb)(
string_get_cstr(update_task->state.status),
furi_string_get_cstr(update_task->state.status),
adapted_progress,
update_stage_is_error(update_task->state.stage),
update_task->status_change_cb_state);
@@ -165,26 +165,26 @@ static void update_task_close_file(UpdateTask* update_task) {
storage_file_close(update_task->file);
}
static bool update_task_check_file_exists(UpdateTask* update_task, string_t filename) {
static bool update_task_check_file_exists(UpdateTask* update_task, FuriString* filename) {
furi_assert(update_task);
string_t tmp_path;
string_init_set(tmp_path, update_task->update_path);
path_append(tmp_path, string_get_cstr(filename));
bool exists = storage_file_exists(update_task->storage, string_get_cstr(tmp_path));
string_clear(tmp_path);
FuriString* tmp_path;
tmp_path = furi_string_alloc_set(update_task->update_path);
path_append(tmp_path, furi_string_get_cstr(filename));
bool exists = storage_file_exists(update_task->storage, furi_string_get_cstr(tmp_path));
furi_string_free(tmp_path);
return exists;
}
bool update_task_open_file(UpdateTask* update_task, string_t filename) {
bool update_task_open_file(UpdateTask* update_task, FuriString* filename) {
furi_assert(update_task);
update_task_close_file(update_task);
string_t tmp_path;
string_init_set(tmp_path, update_task->update_path);
path_append(tmp_path, string_get_cstr(filename));
FuriString* tmp_path;
tmp_path = furi_string_alloc_set(update_task->update_path);
path_append(tmp_path, furi_string_get_cstr(filename));
bool open_success = storage_file_open(
update_task->file, string_get_cstr(tmp_path), FSAM_READ, FSOM_OPEN_EXISTING);
string_clear(tmp_path);
update_task->file, furi_string_get_cstr(tmp_path), FSAM_READ, FSOM_OPEN_EXISTING);
furi_string_free(tmp_path);
return open_success;
}
@@ -207,14 +207,14 @@ UpdateTask* update_task_alloc() {
update_task->state.stage = UpdateTaskStageProgress;
update_task->state.stage_progress = 0;
update_task->state.overall_progress = 0;
string_init(update_task->state.status);
update_task->state.status = furi_string_alloc();
update_task->manifest = update_manifest_alloc();
update_task->storage = furi_record_open(RECORD_STORAGE);
update_task->file = storage_file_alloc(update_task->storage);
update_task->status_change_cb = NULL;
update_task->boot_mode = furi_hal_rtc_get_boot_mode();
string_init(update_task->update_path);
update_task->update_path = furi_string_alloc();
FuriThread* thread = update_task->thread = furi_thread_alloc();
@@ -246,7 +246,7 @@ void update_task_free(UpdateTask* update_task) {
update_manifest_free(update_task->manifest);
furi_record_close(RECORD_STORAGE);
string_clear(update_task->update_path);
furi_string_free(update_task->update_path);
free(update_task);
}
@@ -261,8 +261,8 @@ bool update_task_parse_manifest(UpdateTask* update_task) {
update_task_set_progress(update_task, UpdateTaskStageReadManifest, 0);
bool result = false;
string_t manifest_path;
string_init(manifest_path);
FuriString* manifest_path;
manifest_path = furi_string_alloc();
do {
update_task_set_progress(update_task, UpdateTaskStageProgress, 13);
@@ -276,11 +276,11 @@ bool update_task_parse_manifest(UpdateTask* update_task) {
break;
}
path_extract_dirname(string_get_cstr(manifest_path), update_task->update_path);
path_extract_dirname(furi_string_get_cstr(manifest_path), update_task->update_path);
update_task_set_progress(update_task, UpdateTaskStageProgress, 30);
UpdateManifest* manifest = update_task->manifest;
if(!update_manifest_init(manifest, string_get_cstr(manifest_path))) {
if(!update_manifest_init(manifest, furi_string_get_cstr(manifest_path))) {
break;
}
@@ -320,7 +320,7 @@ bool update_task_parse_manifest(UpdateTask* update_task) {
result = true;
} while(false);
string_clear(manifest_path);
furi_string_free(manifest_path);
return result;
}

View File

@@ -8,7 +8,6 @@ extern "C" {
#include <stdint.h>
#include <stdbool.h>
#include <m-string.h>
#define UPDATE_DELAY_OPERATION_OK 10
#define UPDATE_DELAY_OPERATION_ERROR INT_MAX
@@ -59,7 +58,7 @@ typedef enum {
typedef struct {
UpdateTaskStage stage;
uint8_t overall_progress, stage_progress;
string_t status;
FuriString* status;
UpdateTaskStageGroup groups;
uint32_t total_progress_points;
uint32_t completed_stages_points;

View File

@@ -8,7 +8,7 @@
typedef struct UpdateTask {
UpdateTaskState state;
string_t update_path;
FuriString* update_path;
UpdateManifest* manifest;
FuriThread* thread;
Storage* storage;
@@ -20,7 +20,7 @@ typedef struct UpdateTask {
void update_task_set_progress(UpdateTask* update_task, UpdateTaskStage stage, uint8_t progress);
bool update_task_parse_manifest(UpdateTask* update_task);
bool update_task_open_file(UpdateTask* update_task, string_t filename);
bool update_task_open_file(UpdateTask* update_task, FuriString* filename);
int32_t update_task_worker_flash_writer(void* context);
int32_t update_task_worker_backup_restore(void* context);

View File

@@ -22,19 +22,22 @@
static bool update_task_pre_update(UpdateTask* update_task) {
bool success = false;
string_t backup_file_path;
string_init(backup_file_path);
FuriString* backup_file_path;
backup_file_path = furi_string_alloc();
path_concat(
string_get_cstr(update_task->update_path), LFS_BACKUP_DEFAULT_FILENAME, backup_file_path);
furi_string_get_cstr(update_task->update_path),
LFS_BACKUP_DEFAULT_FILENAME,
backup_file_path);
update_task_set_progress(update_task, UpdateTaskStageLfsBackup, 0);
/* to avoid bootloops */
furi_hal_rtc_set_boot_mode(FuriHalRtcBootModeNormal);
if((success = lfs_backup_create(update_task->storage, string_get_cstr(backup_file_path)))) {
if((success =
lfs_backup_create(update_task->storage, furi_string_get_cstr(backup_file_path)))) {
furi_hal_rtc_set_boot_mode(FuriHalRtcBootModeUpdate);
}
string_clear(backup_file_path);
furi_string_free(backup_file_path);
return success;
}
@@ -79,12 +82,12 @@ static void
/* For this stage, first 30% of progress = cleanup */
(n_processed_files++ * 30) / (n_approx_file_entries + 1));
string_t file_path;
string_init(file_path);
path_concat(STORAGE_EXT_PATH_PREFIX, string_get_cstr(entry_ptr->name), file_path);
FURI_LOG_D(TAG, "Removing %s", string_get_cstr(file_path));
storage_simply_remove(update_task->storage, string_get_cstr(file_path));
string_clear(file_path);
FuriString* file_path = furi_string_alloc();
path_concat(
STORAGE_EXT_PATH_PREFIX, furi_string_get_cstr(entry_ptr->name), file_path);
FURI_LOG_D(TAG, "Removing %s", furi_string_get_cstr(file_path));
storage_simply_remove(update_task->storage, furi_string_get_cstr(file_path));
furi_string_free(file_path);
}
}
} while(false);
@@ -94,17 +97,19 @@ static void
static bool update_task_post_update(UpdateTask* update_task) {
bool success = false;
string_t file_path;
string_init(file_path);
FuriString* file_path;
file_path = furi_string_alloc();
TarArchive* archive = tar_archive_alloc(update_task->storage);
do {
path_concat(
string_get_cstr(update_task->update_path), LFS_BACKUP_DEFAULT_FILENAME, file_path);
furi_string_get_cstr(update_task->update_path),
LFS_BACKUP_DEFAULT_FILENAME,
file_path);
update_task_set_progress(update_task, UpdateTaskStageLfsRestore, 0);
CHECK_RESULT(lfs_backup_unpack(update_task->storage, string_get_cstr(file_path)));
CHECK_RESULT(lfs_backup_unpack(update_task->storage, furi_string_get_cstr(file_path)));
if(update_task->state.groups & UpdateTaskStageGroupResources) {
TarUnpackProgress progress = {
@@ -115,13 +120,13 @@ static bool update_task_post_update(UpdateTask* update_task) {
update_task_set_progress(update_task, UpdateTaskStageResourcesUpdate, 0);
path_concat(
string_get_cstr(update_task->update_path),
string_get_cstr(update_task->manifest->resource_bundle),
furi_string_get_cstr(update_task->update_path),
furi_string_get_cstr(update_task->manifest->resource_bundle),
file_path);
tar_archive_set_file_callback(archive, update_task_resource_unpack_cb, &progress);
CHECK_RESULT(
tar_archive_open(archive, string_get_cstr(file_path), TAR_OPEN_MODE_READ));
tar_archive_open(archive, furi_string_get_cstr(file_path), TAR_OPEN_MODE_READ));
progress.total_files = tar_archive_get_entries_count(archive);
if(progress.total_files > 0) {
@@ -133,23 +138,23 @@ static bool update_task_post_update(UpdateTask* update_task) {
if(update_task->state.groups & UpdateTaskStageGroupSplashscreen) {
update_task_set_progress(update_task, UpdateTaskStageSplashscreenInstall, 0);
string_t tmp_path;
string_init_set(tmp_path, update_task->update_path);
path_append(tmp_path, string_get_cstr(update_task->manifest->splash_file));
FuriString* tmp_path;
tmp_path = furi_string_alloc_set(update_task->update_path);
path_append(tmp_path, furi_string_get_cstr(update_task->manifest->splash_file));
if(storage_common_copy(
update_task->storage,
string_get_cstr(tmp_path),
furi_string_get_cstr(tmp_path),
INT_PATH(SLIDESHOW_FILE_NAME)) != FSE_OK) {
// actually, not critical
}
string_clear(tmp_path);
furi_string_free(tmp_path);
update_task_set_progress(update_task, UpdateTaskStageSplashscreenInstall, 100);
}
success = true;
} while(false);
tar_archive_free(archive);
string_clear(file_path);
furi_string_free(file_path);
return success;
}

View File

@@ -18,7 +18,7 @@ struct UpdaterMainView {
static const uint8_t PROGRESS_RENDER_STEP = 1; /* percent, to limit rendering rate */
typedef struct {
string_t status;
FuriString* status;
uint8_t progress, rendered_progress;
bool failed;
} UpdaterProgressModel;
@@ -32,8 +32,8 @@ void updater_main_model_set_state(
main_view->view, (UpdaterProgressModel * model) {
model->failed = failed;
model->progress = progress;
if(string_cmp_str(model->status, message)) {
string_set(model->status, message);
if(furi_string_cmp_str(model->status, message)) {
furi_string_set(model->status, message);
model->rendered_progress = progress;
return true;
}
@@ -80,7 +80,7 @@ static void updater_main_draw_callback(Canvas* canvas, void* _model) {
canvas_draw_str_aligned(canvas, 42, 16, AlignLeft, AlignTop, "Update Failed!");
canvas_set_font(canvas, FontSecondary);
canvas_draw_str_aligned(
canvas, 42, 32, AlignLeft, AlignTop, string_get_cstr(model->status));
canvas, 42, 32, AlignLeft, AlignTop, furi_string_get_cstr(model->status));
canvas_draw_icon(canvas, 7, 16, &I_Warning_30x23);
canvas_draw_str_aligned(
@@ -91,7 +91,7 @@ static void updater_main_draw_callback(Canvas* canvas, void* _model) {
canvas_draw_str_aligned(canvas, 55, 14, AlignLeft, AlignTop, "UPDATING");
canvas_set_font(canvas, FontSecondary);
canvas_draw_str_aligned(
canvas, 64, 51, AlignCenter, AlignTop, string_get_cstr(model->status));
canvas, 64, 51, AlignCenter, AlignTop, furi_string_get_cstr(model->status));
canvas_draw_icon(canvas, 4, 5, &I_Updating_32x40);
elements_progress_bar(canvas, 42, 29, 80, (float)model->progress / 100);
}
@@ -105,7 +105,7 @@ UpdaterMainView* updater_main_alloc() {
with_view_model(
main_view->view, (UpdaterProgressModel * model) {
string_init_set(model->status, "Waiting for SD card");
model->status = furi_string_alloc_set("Waiting for SD card");
return true;
});
@@ -120,7 +120,7 @@ void updater_main_free(UpdaterMainView* main_view) {
furi_assert(main_view);
with_view_model(
main_view->view, (UpdaterProgressModel * model) {
string_clear(model->status);
furi_string_free(model->status);
return false;
});
view_free(main_view->view);