feat: implement LittleFSHandler and FSGuard for improved file management

This commit is contained in:
GW_MC
2026-01-30 15:23:44 +08:00
parent b6c4477c46
commit 2a5088bec3
7 changed files with 821 additions and 85 deletions

95
main/io/fs_handler.h Normal file
View File

@@ -0,0 +1,95 @@
#pragma once
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "esp_littlefs.h"
#include "esp_err.h"
#include <string>
#include <vector>
#include <map>
#include <memory>
#include "esp_log.h"
#include <semaphore_guard.h>
// Forward declaration
class LittleFSHandler;
class FSGuard {
public:
FSGuard(LittleFSHandler* fs_handler, const std::string& relative_path, const char* flags);
~FSGuard();
esp_err_t close();
FILE* get_file() {
return file_;
}
bool is_open() const {
return file_ != nullptr;
}
private:
LittleFSHandler* fs_handler_ = nullptr;
FILE* file_;
// prevent copying and moving
FSGuard(const FSGuard&) = delete;
FSGuard& operator=(const FSGuard&) = delete;
FSGuard(FSGuard&& other) = delete;
FSGuard& operator=(FSGuard&& other) = delete;
};
//LittleFSHandler interface
// All paths are relative to the mounted filesystem root
// Implementations should handle initialization of the filesystem, and mounting if necessary
// When destroyed, implementations should unmount the filesystem if necessary
// All paths are relative to the mounted filesystem root, e.g. if mounted at /littlefs, and file is /data.txt, the full path is /littlefs/data.txt
// File operations use standard C FILE* wrapped in FSGuard for RAII
class LittleFSHandler {
public:
LittleFSHandler();
~LittleFSHandler();
esp_err_t init(std::string base_path);
esp_err_t init(const esp_vfs_littlefs_conf_t& config);
std::string get_base_path() const;
std::string get_full_path(const std::string& relative_path) const;
// File operations
esp_err_t write_file(const std::string& relative_path, const uint8_t* data, size_t size, size_t& out_bytes_written);
esp_err_t write_file(FILE* file, const uint8_t* data, size_t size, size_t& out_bytes_written);
//
esp_err_t append_file(const std::string& relative_path, const uint8_t* data, size_t size, size_t& out_bytes_written);
esp_err_t append_file(FILE* file, const uint8_t* data, size_t size, size_t& out_bytes_written);
//
esp_err_t read_file(const std::string& relative_path, const size_t max_size, uint8_t* out_data, size_t& out_size);
esp_err_t read_file(FILE* file, const size_t max_size, uint8_t* out_data, size_t& out_size);
//
esp_err_t delete_file(const std::string& relative_path);
//
bool file_exists(const std::string& relative_path);
esp_err_t get_file_size(const std::string& relative_path, size_t& out_size);
// Directory operations
esp_err_t create_directory(const std::string& relative_path);
esp_err_t list_directory(const std::string& relative_path, std::vector<std::string>& out_entries);
protected:
esp_err_t open_file_(const std::string& relative_path, const char* flags, FILE*& out_file);
esp_err_t close_file_(FILE* file);
// uses standard C FILE* for file operations
esp_err_t write_if_different_(FILE* file, const uint8_t* data, size_t size);
esp_err_t write_if_different_(FILE* file, const uint8_t* data, size_t size, size_t& out_bytes_written);
friend class FSGuard;
private:
//
bool is_initialized_() const;
SemaphoreHandle_t fs_mutex_ = nullptr;
bool initialized_ = false;
std::string base_path_;
};