From 4d99d22e10a3cb2a421da1618c127128816613c9 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Tue, 26 Sep 2023 13:36:07 +1000 Subject: [PATCH] std::string -> std::pmr::string in psram --- src/app_console/app_console.cpp | 49 ++++++++------- src/audio/fatfs_audio_input.cpp | 9 +-- src/audio/include/audio_events.hpp | 2 +- src/audio/include/fatfs_audio_input.hpp | 8 +-- src/codecs/CMakeLists.txt | 2 +- src/codecs/include/codec.hpp | 4 +- src/codecs/opus.cpp | 2 +- src/codecs/vorbis.cpp | 2 +- src/database/CMakeLists.txt | 2 +- src/database/database.cpp | 74 ++++++++++++----------- src/database/file_gatherer.cpp | 22 ++++--- src/database/include/database.hpp | 22 +++---- src/database/include/file_gatherer.hpp | 8 +-- src/database/include/index.hpp | 10 +-- src/database/include/records.hpp | 8 +-- src/database/include/tag_parser.hpp | 18 +++--- src/database/include/track.hpp | 29 ++++----- src/database/index.cpp | 10 +-- src/database/records.cpp | 36 ++++++----- src/database/tag_parser.cpp | 38 ++++++------ src/database/test/test_database.cpp | 12 ++-- src/database/test/test_records.cpp | 4 +- src/database/track.cpp | 20 +++--- src/dev_console/CMakeLists.txt | 2 +- src/dev_console/console.cpp | 6 +- src/drivers/bluetooth.cpp | 12 ++-- src/drivers/include/bluetooth_types.hpp | 4 +- src/drivers/include/fatfs_audio_input.hpp | 2 +- src/drivers/storage.cpp | 3 +- src/drivers/test/test_storage.cpp | 8 +-- src/memory/include/memory_resource.hpp | 3 +- src/tasks/CMakeLists.txt | 2 +- src/tasks/tasks.cpp | 18 +++--- src/tasks/tasks.hpp | 4 +- src/ui/include/modal_confirm.hpp | 2 +- src/ui/include/modal_progress.hpp | 2 +- src/ui/include/screen.hpp | 2 +- src/ui/include/screen_onboarding.hpp | 2 +- src/ui/include/screen_playing.hpp | 3 +- src/ui/include/screen_track_browser.hpp | 2 +- src/ui/include/widget_top_bar.hpp | 4 +- src/ui/modal_confirm.cpp | 4 +- src/ui/modal_progress.cpp | 2 +- src/ui/screen.cpp | 2 +- src/ui/screen_onboarding.cpp | 5 +- src/ui/screen_playing.cpp | 2 +- src/ui/screen_settings.cpp | 6 +- src/ui/screen_track_browser.cpp | 2 +- src/ui/ui_fsm.cpp | 2 +- 49 files changed, 272 insertions(+), 225 deletions(-) diff --git a/src/app_console/app_console.cpp b/src/app_console/app_console.cpp index 74d33727..67cf57d7 100644 --- a/src/app_console/app_console.cpp +++ b/src/app_console/app_console.cpp @@ -35,6 +35,7 @@ #include "freertos/FreeRTOSConfig_arch.h" #include "freertos/projdefs.h" #include "index.hpp" +#include "memory_resource.hpp" #include "service_locator.hpp" #include "track.hpp" @@ -49,7 +50,7 @@ int CmdListDir(int argc, char** argv) { return 1; } - std::string path; + std::pmr::string path; if (argc > 1) { std::ostringstream builder; builder << argv[1]; @@ -102,13 +103,13 @@ void RegisterListDir() { } int CmdPlayFile(int argc, char** argv) { - static const std::string usage = "usage: play [file or id]"; + static const std::pmr::string usage = "usage: play [file or id]"; if (argc < 2) { std::cout << usage << std::endl; return 1; } - std::string path_or_id = argv[1]; + std::pmr::string path_or_id = argv[1]; bool is_id = true; for (const auto& it : path_or_id) { if (!std::isdigit(it)) { @@ -121,13 +122,15 @@ int CmdPlayFile(int argc, char** argv) { database::TrackId id = std::atoi(argv[1]); AppConsole::sServices->track_queue().AddLast(id); } else { - std::ostringstream path; - path << '/' << argv[1]; + std::pmr::string path{&memory::kSpiRamResource}; + path += '/'; + path += argv[1]; for (int i = 2; i < argc; i++) { - path << ' ' << argv[i]; + path += ' '; + path += argv[i]; } - events::Audio().Dispatch(audio::PlayFile{.filename = path.str()}); + events::Audio().Dispatch(audio::PlayFile{.filename = path}); } return 0; @@ -143,7 +146,7 @@ void RegisterPlayFile() { } int CmdDbInit(int argc, char** argv) { - static const std::string usage = "usage: db_init"; + static const std::pmr::string usage = "usage: db_init"; if (argc != 1) { std::cout << usage << std::endl; return 1; @@ -170,7 +173,7 @@ void RegisterDbInit() { } int CmdDbTracks(int argc, char** argv) { - static const std::string usage = "usage: db_tracks"; + static const std::pmr::string usage = "usage: db_tracks"; if (argc != 1) { std::cout << usage << std::endl; return 1; @@ -211,7 +214,7 @@ void RegisterDbTracks() { int CmdDbIndex(int argc, char** argv) { std::cout << std::endl; vTaskDelay(1); - static const std::string usage = "usage: db_index [id] [choices ...]"; + static const std::pmr::string usage = "usage: db_index [id] [choices ...]"; auto db = AppConsole::sServices->database().lock(); if (!db) { @@ -292,7 +295,7 @@ void RegisterDbIndex() { } int CmdDbDump(int argc, char** argv) { - static const std::string usage = "usage: db_dump"; + static const std::pmr::string usage = "usage: db_dump"; if (argc != 1) { std::cout << usage << std::endl; return 1; @@ -306,14 +309,14 @@ int CmdDbDump(int argc, char** argv) { std::cout << "=== BEGIN DUMP ===" << std::endl; - std::unique_ptr> res(db->GetDump(5).get()); + std::unique_ptr> res(db->GetDump(5).get()); while (true) { - for (std::string s : res->values()) { + for (const std::pmr::string& s : res->values()) { std::cout << s << std::endl; } if (res->next_page()) { auto continuation = res->next_page().value(); - res.reset(db->GetPage(&continuation).get()); + res.reset(db->GetPage(&continuation).get()); } else { break; } @@ -340,7 +343,7 @@ int CmdTasks(int argc, char** argv) { return 1; } - static const std::string usage = "usage: tasks"; + static const std::pmr::string usage = "usage: tasks"; if (argc != 1) { std::cout << usage << std::endl; return 1; @@ -362,7 +365,7 @@ int CmdTasks(int argc, char** argv) { size_t end_num_tasks = uxTaskGetSystemState(end_status, num_tasks, &end_elapsed_ticks); - std::vector> info_strings; + std::vector> info_strings; for (int i = 0; i < start_num_tasks; i++) { int k = -1; for (int j = 0; j < end_num_tasks; j++) { @@ -383,7 +386,7 @@ int CmdTasks(int argc, char** argv) { auto depth = uxTaskGetStackHighWaterMark2(start_status[i].xHandle); float depth_kib = static_cast(depth) / 1024.0f; - std::ostringstream str; + std::ostringstream str{}; str << start_status[i].pcTaskName; if (str.str().size() < 8) { str << "\t\t"; @@ -410,7 +413,7 @@ int CmdTasks(int argc, char** argv) { str << std::fixed << std::setprecision(1) << (time_percent * 100); str << "%"; - info_strings.push_back({run_time, str.str()}); + info_strings.push_back({run_time, std::pmr::string{str.str()}}); } } @@ -444,7 +447,7 @@ void RegisterTasks() { } int CmdHeaps(int argc, char** argv) { - static const std::string usage = "usage: heaps"; + static const std::pmr::string usage = "usage: heaps"; if (argc != 1) { std::cout << usage << std::endl; return 1; @@ -484,7 +487,7 @@ static heap_trace_record_t* sTraceRecords = nullptr; static bool sIsTracking = false; int CmdAllocs(int argc, char** argv) { - static const std::string usage = "usage: allocs"; + static const std::pmr::string usage = "usage: allocs"; if (argc != 1) { std::cout << usage << std::endl; return 1; @@ -521,7 +524,7 @@ void RegisterAllocs() { #endif int CmdBtList(int argc, char** argv) { - static const std::string usage = "usage: bt_list "; + static const std::pmr::string usage = "usage: bt_list "; if (argc > 2) { std::cout << usage << std::endl; return 1; @@ -563,13 +566,13 @@ void RegisterBtList() { } int CmdSamd(int argc, char** argv) { - static const std::string usage = "usage: samd [flash|charge|off]"; + static const std::pmr::string usage = "usage: samd [flash|charge|off]"; if (argc != 2) { std::cout << usage << std::endl; return 1; } - std::string cmd{argv[1]}; + std::pmr::string cmd{argv[1]}; if (cmd == "flash") { std::cout << "resetting samd..." << std::endl; vTaskDelay(pdMS_TO_TICKS(5)); diff --git a/src/audio/fatfs_audio_input.cpp b/src/audio/fatfs_audio_input.cpp index 6b032632..f71f0463 100644 --- a/src/audio/fatfs_audio_input.cpp +++ b/src/audio/fatfs_audio_input.cpp @@ -52,16 +52,17 @@ FatfsAudioInput::~FatfsAudioInput() { vSemaphoreDelete(has_new_stream_); } -auto FatfsAudioInput::SetPath(std::future> fut) +auto FatfsAudioInput::SetPath(std::future> fut) -> void { std::lock_guard guard{new_stream_mutex_}; pending_path_.reset( - new database::FutureFetcher>(std::move(fut))); + new database::FutureFetcher>( + std::move(fut))); xSemaphoreGive(has_new_stream_); } -auto FatfsAudioInput::SetPath(const std::string& path) -> void { +auto FatfsAudioInput::SetPath(const std::pmr::string& path) -> void { std::lock_guard guard{new_stream_mutex_}; if (OpenFile(path)) { xSemaphoreGive(has_new_stream_); @@ -114,7 +115,7 @@ auto FatfsAudioInput::NextStream() -> std::shared_ptr { } } -auto FatfsAudioInput::OpenFile(const std::string& path) -> bool { +auto FatfsAudioInput::OpenFile(const std::pmr::string& path) -> bool { ESP_LOGI(kTag, "opening file %s", path.c_str()); database::TrackTags tags; diff --git a/src/audio/include/audio_events.hpp b/src/audio/include/audio_events.hpp index 5af419ab..6b986462 100644 --- a/src/audio/include/audio_events.hpp +++ b/src/audio/include/audio_events.hpp @@ -31,7 +31,7 @@ struct QueueUpdate : tinyfsm::Event { }; struct PlayFile : tinyfsm::Event { - std::string filename; + std::pmr::string filename; }; struct VolumeChanged : tinyfsm::Event {}; diff --git a/src/audio/include/fatfs_audio_input.hpp b/src/audio/include/fatfs_audio_input.hpp index b67d29dc..b7b1d18e 100644 --- a/src/audio/include/fatfs_audio_input.hpp +++ b/src/audio/include/fatfs_audio_input.hpp @@ -37,8 +37,8 @@ class FatfsAudioInput : public IAudioSource { * Immediately cease reading any current source, and begin reading from the * given file path. */ - auto SetPath(std::future>) -> void; - auto SetPath(const std::string&) -> void; + auto SetPath(std::future>) -> void; + auto SetPath(const std::pmr::string&) -> void; auto SetPath() -> void; auto HasNewStream() -> bool override; @@ -48,7 +48,7 @@ class FatfsAudioInput : public IAudioSource { FatfsAudioInput& operator=(const FatfsAudioInput&) = delete; private: - auto OpenFile(const std::string& path) -> bool; + auto OpenFile(const std::pmr::string& path) -> bool; auto ContainerToStreamType(database::Container) -> std::optional; @@ -60,7 +60,7 @@ class FatfsAudioInput : public IAudioSource { SemaphoreHandle_t has_new_stream_; - std::unique_ptr>> + std::unique_ptr>> pending_path_; }; diff --git a/src/codecs/CMakeLists.txt b/src/codecs/CMakeLists.txt index 2d98198b..748e1440 100644 --- a/src/codecs/CMakeLists.txt +++ b/src/codecs/CMakeLists.txt @@ -6,6 +6,6 @@ idf_component_register( SRCS "codec.cpp" "mad.cpp" "foxenflac.cpp" "opus.cpp" "vorbis.cpp" "source_buffer.cpp" INCLUDE_DIRS "include" - REQUIRES "result" "span" "libmad" "libfoxenflac" "tremor" "opusfile") + REQUIRES "result" "span" "libmad" "libfoxenflac" "tremor" "opusfile" "memory") target_compile_options("${COMPONENT_LIB}" PRIVATE ${EXTRA_WARNINGS}) diff --git a/src/codecs/include/codec.hpp b/src/codecs/include/codec.hpp index 2f95389c..67358d54 100644 --- a/src/codecs/include/codec.hpp +++ b/src/codecs/include/codec.hpp @@ -21,6 +21,8 @@ #include "span.hpp" #include "types.hpp" +#include "memory_resource.hpp" + namespace codecs { /* @@ -69,7 +71,7 @@ class ICodec { kInternalError, }; - static auto ErrorString(Error err) -> std::string { + static auto ErrorString(Error err) -> std::pmr::string { switch (err) { case Error::kOutOfInput: return "out of input"; diff --git a/src/codecs/opus.cpp b/src/codecs/opus.cpp index 6e9512b1..448e9eb4 100644 --- a/src/codecs/opus.cpp +++ b/src/codecs/opus.cpp @@ -86,7 +86,7 @@ auto XiphOpusDecoder::OpenStream(std::shared_ptr input) opus_ = op_open_callbacks(input.get(), &kCallbacks, nullptr, 0, &res); if (res < 0) { - std::string err; + std::pmr::string err; switch (res) { case OP_EREAD: err = "OP_EREAD"; diff --git a/src/codecs/vorbis.cpp b/src/codecs/vorbis.cpp index 750ac9a8..f553bb42 100644 --- a/src/codecs/vorbis.cpp +++ b/src/codecs/vorbis.cpp @@ -88,7 +88,7 @@ auto TremorVorbisDecoder::OpenStream(std::shared_ptr input) -> cpp::result { int res = ov_open_callbacks(input.get(), &vorbis_, NULL, 0, kCallbacks); if (res < 0) { - std::string err; + std::pmr::string err; switch (res) { case OV_EREAD: err = "OV_EREAD"; diff --git a/src/database/CMakeLists.txt b/src/database/CMakeLists.txt index 008757f8..dffc3a26 100644 --- a/src/database/CMakeLists.txt +++ b/src/database/CMakeLists.txt @@ -7,7 +7,7 @@ idf_component_register( "file_gatherer.cpp" "tag_parser.cpp" "index.cpp" INCLUDE_DIRS "include" REQUIRES "result" "span" "esp_psram" "fatfs" "libtags" "komihash" "cbor" - "tasks" "shared_string" "util" "tinyfsm" "events" "opusfile") + "tasks" "memory" "util" "tinyfsm" "events" "opusfile") target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS}) diff --git a/src/database/database.cpp b/src/database/database.cpp index d73ce771..fd0e50c1 100644 --- a/src/database/database.cpp +++ b/src/database/database.cpp @@ -31,6 +31,7 @@ #include "env_esp.hpp" #include "event_queue.hpp" #include "file_gatherer.hpp" +#include "memory_resource.hpp" #include "records.hpp" #include "result.hpp" #include "tag_parser.hpp" @@ -195,7 +196,7 @@ auto Database::Update() -> std::future { events::Ui().Dispatch(event::UpdateProgress{ .stage = event::UpdateProgress::Stage::kScanningForNewTracks, }); - file_gatherer_.FindFiles("", [&](const std::string& path) { + file_gatherer_.FindFiles("", [&](const std::pmr::string& path) { TrackTags tags; if (!tag_parser_.ReadAndParseTags(path, &tags) || tags.encoding() == Container::kUnsupported) { @@ -252,9 +253,9 @@ auto Database::Update() -> std::future { } auto Database::GetTrackPath(TrackId id) - -> std::future> { - return worker_task_->Dispatch>( - [=, this]() -> std::optional { + -> std::future> { + return worker_task_->Dispatch>( + [=, this]() -> std::optional { auto track_data = dbGetTrackData(id); if (track_data) { return track_data->filepath(); @@ -362,14 +363,14 @@ auto Database::GetTracks(std::size_t page_size) -> std::future*> { } auto Database::GetDump(std::size_t page_size) - -> std::future*> { - return worker_task_->Dispatch*>( - [=, this]() -> Result* { - Continuation c{.prefix = "", - .start_key = "", - .forward = true, - .was_prev_forward = true, - .page_size = page_size}; + -> std::future*> { + return worker_task_->Dispatch*>( + [=, this]() -> Result* { + Continuation c{.prefix = "", + .start_key = "", + .forward = true, + .was_prev_forward = true, + .page_size = page_size}; return dbGetPage(c); }); } @@ -385,8 +386,9 @@ template auto Database::GetPage(Continuation* c) -> std::future*>; template auto Database::GetPage(Continuation* c) -> std::future*>; -template auto Database::GetPage(Continuation* c) - -> std::future*>; +template auto Database::GetPage( + Continuation* c) + -> std::future*>; auto Database::dbMintNewTrackId() -> TrackId { TrackId next_id = 1; @@ -466,7 +468,7 @@ auto Database::dbGetPage(const Continuation& c) -> Result* { // Work out our starting point. Sometimes this will already done. std::unique_ptr it{ db_->NewIterator(leveldb::ReadOptions{})}; - it->Seek(c.start_key); + it->Seek({c.start_key.data(), c.start_key.size()}); // Fix off-by-one if we just changed direction. if (c.forward != c.was_prev_forward) { @@ -478,10 +480,10 @@ auto Database::dbGetPage(const Continuation& c) -> Result* { } // Grab results. - std::optional first_key; + std::optional first_key; std::vector records; while (records.size() < c.page_size && it->Valid()) { - if (!it->key().starts_with(c.prefix)) { + if (!it->key().starts_with({c.prefix.data(), c.prefix.size()})) { break; } if (!first_key) { @@ -498,7 +500,8 @@ auto Database::dbGetPage(const Continuation& c) -> Result* { } } - if (!it->Valid() || !it->key().starts_with(c.prefix)) { + if (!it->Valid() || + !it->key().starts_with({c.prefix.data(), c.prefix.size()})) { it.reset(); } @@ -512,7 +515,8 @@ auto Database::dbGetPage(const Continuation& c) -> Result* { if (c.forward) { if (it != nullptr) { // We were going forward, and now we want the next page. - std::string key = it->key().ToString(); + std::pmr::string key{it->key().data(), it->key().size(), + &memory::kSpiRamResource}; next_page = Continuation{ .prefix = c.prefix, .start_key = key, @@ -549,7 +553,8 @@ auto Database::dbGetPage(const Continuation& c) -> Result* { } else { if (it != nullptr) { // We were going backwards, and we still want to go backwards. - std::string key = it->key().ToString(); + std::pmr::string key{it->key().data(), it->key().size(), + &memory::kSpiRamResource}; prev_page = Continuation{ .prefix = c.prefix, .start_key = key, @@ -566,8 +571,8 @@ auto Database::dbGetPage(const Continuation& c) -> Result* { template auto Database::dbGetPage(const Continuation& c) -> Result*; -template auto Database::dbGetPage( - const Continuation& c) -> Result*; +template auto Database::dbGetPage( + const Continuation& c) -> Result*; template <> auto Database::ParseRecord(const leveldb::Slice& key, @@ -578,7 +583,7 @@ auto Database::ParseRecord(const leveldb::Slice& key, return {}; } - std::optional title; + std::optional title; if (!val.empty()) { title = val.ToString(); } @@ -602,43 +607,42 @@ auto Database::ParseRecord(const leveldb::Slice& key, } template <> -auto Database::ParseRecord(const leveldb::Slice& key, - const leveldb::Slice& val) - -> std::optional { +auto Database::ParseRecord(const leveldb::Slice& key, + const leveldb::Slice& val) + -> std::optional { std::ostringstream stream; stream << "key: "; if (key.size() < 3 || key.data()[1] != '\0') { stream << key.ToString().c_str(); } else { - std::string str = key.ToString(); - for (size_t i = 0; i < str.size(); i++) { + for (size_t i = 0; i < key.size(); i++) { if (i == 0) { - stream << str[i]; + stream << key.data()[i]; } else if (i == 1) { stream << " / 0x"; } else { stream << std::hex << std::setfill('0') << std::setw(2) - << static_cast(str[i]); + << static_cast(key.data()[i]); } } } if (!val.empty()) { stream << "\tval: 0x"; - std::string str = val.ToString(); for (int i = 0; i < val.size(); i++) { stream << std::hex << std::setfill('0') << std::setw(2) - << static_cast(str[i]); + << static_cast(val.data()[i]); } } - return stream.str(); + std::pmr::string res{stream.str(), &memory::kSpiRamResource}; + return res; } IndexRecord::IndexRecord(const IndexKey& key, - std::optional title, + std::optional title, std::optional track) : key_(key), override_text_(title), track_(track) {} -auto IndexRecord::text() const -> std::optional { +auto IndexRecord::text() const -> std::optional { if (override_text_) { return override_text_; } diff --git a/src/database/file_gatherer.cpp b/src/database/file_gatherer.cpp index 2d17a925..d8c80b0d 100644 --- a/src/database/file_gatherer.cpp +++ b/src/database/file_gatherer.cpp @@ -13,18 +13,20 @@ #include "ff.h" +#include "memory_resource.hpp" + namespace database { static_assert(sizeof(TCHAR) == sizeof(char), "TCHAR must be CHAR"); -auto FileGathererImpl::FindFiles(const std::string& root, - std::function cb) - -> void { - std::deque to_explore; +auto FileGathererImpl::FindFiles( + const std::pmr::string& root, + std::function cb) -> void { + std::pmr::deque to_explore(&memory::kSpiRamResource); to_explore.push_back(root); while (!to_explore.empty()) { - std::string next_path_str = to_explore.front(); + std::pmr::string next_path_str = to_explore.front(); const TCHAR* next_path = static_cast(next_path_str.c_str()); FF_DIR dir; @@ -44,16 +46,18 @@ auto FileGathererImpl::FindFiles(const std::string& root, // System or hidden file. Ignore it and move on. continue; } else { - std::stringstream full_path; - full_path << next_path_str << "/" << info.fname; + std::pmr::string full_path{&memory::kSpiRamResource}; + full_path += next_path_str; + full_path += "/"; + full_path += info.fname; if (info.fattrib & AM_DIR) { // This is a directory. Add it to the explore queue. - to_explore.push_back(full_path.str()); + to_explore.push_back(full_path); } else { // This is a file! Let the callback know about it. // std::invoke(cb, full_path.str(), info); - std::invoke(cb, full_path.str()); + std::invoke(cb, full_path); } } } diff --git a/src/database/include/database.hpp b/src/database/include/database.hpp index 00704a5f..98540f41 100644 --- a/src/database/include/database.hpp +++ b/src/database/include/database.hpp @@ -22,9 +22,9 @@ #include "leveldb/iterator.h" #include "leveldb/options.h" #include "leveldb/slice.h" +#include "memory_resource.hpp" #include "records.hpp" #include "result.hpp" -#include "shared_string.h" #include "tag_parser.hpp" #include "tasks.hpp" #include "track.hpp" @@ -33,8 +33,8 @@ namespace database { template struct Continuation { - std::string prefix; - std::string start_key; + std::pmr::string prefix; + std::pmr::string start_key; bool forward; bool was_prev_forward; size_t page_size; @@ -70,17 +70,17 @@ class Result { class IndexRecord { public: explicit IndexRecord(const IndexKey&, - std::optional, + std::optional, std::optional); - auto text() const -> std::optional; + auto text() const -> std::optional; auto track() const -> std::optional; auto Expand(std::size_t) const -> std::optional>; private: IndexKey key_; - std::optional override_text_; + std::optional override_text_; std::optional track_; }; @@ -100,7 +100,7 @@ class Database { auto Update() -> std::future; - auto GetTrackPath(TrackId id) -> std::future>; + auto GetTrackPath(TrackId id) -> std::future>; auto GetTrack(TrackId id) -> std::future>; @@ -115,7 +115,7 @@ class Database { auto GetTracksByIndex(const IndexInfo& index, std::size_t page_size) -> std::future*>; auto GetTracks(std::size_t page_size) -> std::future*>; - auto GetDump(std::size_t page_size) -> std::future*>; + auto GetDump(std::size_t page_size) -> std::future*>; template auto GetPage(Continuation* c) -> std::future*>; @@ -167,8 +167,8 @@ auto Database::ParseRecord(const leveldb::Slice& key, const leveldb::Slice& val) -> std::optional; template <> -auto Database::ParseRecord(const leveldb::Slice& key, - const leveldb::Slice& val) - -> std::optional; +auto Database::ParseRecord(const leveldb::Slice& key, + const leveldb::Slice& val) + -> std::optional; } // namespace database diff --git a/src/database/include/file_gatherer.hpp b/src/database/include/file_gatherer.hpp index ff0a6ac2..133cf81a 100644 --- a/src/database/include/file_gatherer.hpp +++ b/src/database/include/file_gatherer.hpp @@ -19,15 +19,15 @@ class IFileGatherer { public: virtual ~IFileGatherer(){}; - virtual auto FindFiles(const std::string& root, - std::function cb) + virtual auto FindFiles(const std::pmr::string& root, + std::function cb) -> void = 0; }; class FileGathererImpl : public IFileGatherer { public: - virtual auto FindFiles(const std::string& root, - std::function cb) + virtual auto FindFiles(const std::pmr::string& root, + std::function cb) -> void override; }; diff --git a/src/database/include/index.hpp b/src/database/include/index.hpp index 17b40f5b..838eff31 100644 --- a/src/database/include/index.hpp +++ b/src/database/include/index.hpp @@ -17,7 +17,7 @@ #include "leveldb/slice.h" #include "leveldb/write_batch.h" -#include "shared_string.h" +#include "memory_resource.hpp" #include "track.hpp" namespace database { @@ -29,7 +29,7 @@ struct IndexInfo { IndexId id; // Localised, user-friendly description of this index. e.g. "Albums by Artist" // or "All Tracks". - std::string name; + std::pmr::string name; // Specifier for how this index breaks down the database. std::vector components; }; @@ -51,7 +51,7 @@ struct IndexKey { // The filterable / selectable item that this key represents. "Jacqueline" for // kArtist, "My Cool Album" for kAlbum, etc. - std::optional item; + std::optional item; // If this is a leaf component, the track id for this record. // This could reasonably be the value for a record, but we keep it as a part // of the key to help with disambiguation. @@ -59,8 +59,8 @@ struct IndexKey { }; auto Index(const IndexInfo&, const Track&, leveldb::WriteBatch*) -> bool; -auto ExpandHeader(const IndexKey::Header&, const std::optional&) - -> IndexKey::Header; +auto ExpandHeader(const IndexKey::Header&, + const std::optional&) -> IndexKey::Header; // Predefined indexes // TODO(jacqueline): Make these defined at runtime! :) diff --git a/src/database/include/records.hpp b/src/database/include/records.hpp index 58f29b20..b144dece 100644 --- a/src/database/include/records.hpp +++ b/src/database/include/records.hpp @@ -16,7 +16,7 @@ #include "leveldb/slice.h" #include "index.hpp" -#include "shared_string.h" +#include "memory_resource.hpp" #include "track.hpp" namespace database { @@ -28,10 +28,10 @@ namespace database { */ class OwningSlice { public: - std::string data; + std::pmr::string data; leveldb::Slice slice; - explicit OwningSlice(std::string d); + explicit OwningSlice(std::pmr::string d); }; /* @@ -88,6 +88,6 @@ auto TrackIdToBytes(TrackId id) -> OwningSlice; * Converts a track id encoded via TrackIdToBytes back into a TrackId. May * return nullopt if parsing fails. */ -auto BytesToTrackId(const std::string& bytes) -> std::optional; +auto BytesToTrackId(cpp::span bytes) -> std::optional; } // namespace database diff --git a/src/database/include/tag_parser.hpp b/src/database/include/tag_parser.hpp index 85721357..d77967d8 100644 --- a/src/database/include/tag_parser.hpp +++ b/src/database/include/tag_parser.hpp @@ -16,24 +16,24 @@ namespace database { class ITagParser { public: virtual ~ITagParser() {} - virtual auto ReadAndParseTags(const std::string& path, TrackTags* out) + virtual auto ReadAndParseTags(const std::pmr::string& path, TrackTags* out) -> bool = 0; }; class GenericTagParser : public ITagParser { public: - auto ReadAndParseTags(const std::string& path, TrackTags* out) + auto ReadAndParseTags(const std::pmr::string& path, TrackTags* out) -> bool override; }; class TagParserImpl : public ITagParser { public: TagParserImpl(); - auto ReadAndParseTags(const std::string& path, TrackTags* out) + auto ReadAndParseTags(const std::pmr::string& path, TrackTags* out) -> bool override; private: - std::map> extension_to_parser_; + std::map> extension_to_parser_; GenericTagParser generic_parser_; /* @@ -41,16 +41,16 @@ class TagParserImpl : public ITagParser { * cache should be slightly larger than any page sizes in the UI. */ std::mutex cache_mutex_; - util::LruCache<16, std::string, TrackTags> cache_; + util::LruCache<16, std::pmr::string, TrackTags> cache_; - // We could also consider keeping caches of artist name -> shared_string and - // similar. This hasn't been done yet, as this isn't a common workload in any - // of our UI. + // We could also consider keeping caches of artist name -> std::pmr::string + // and similar. This hasn't been done yet, as this isn't a common workload in + // any of our UI. }; class OpusTagParser : public ITagParser { public: - auto ReadAndParseTags(const std::string& path, TrackTags* out) + auto ReadAndParseTags(const std::pmr::string& path, TrackTags* out) -> bool override; }; diff --git a/src/database/include/track.hpp b/src/database/include/track.hpp index 41f552d2..1c11ddea 100644 --- a/src/database/include/track.hpp +++ b/src/database/include/track.hpp @@ -16,7 +16,7 @@ #include #include "leveldb/db.h" -#include "shared_string.h" +#include "memory_resource.hpp" #include "span.hpp" namespace database { @@ -64,7 +64,8 @@ class TrackTags { auto encoding() const -> Container { return encoding_; }; auto encoding(Container e) -> void { encoding_ = e; }; - TrackTags() : encoding_(Container::kUnsupported) {} + TrackTags() + : encoding_(Container::kUnsupported), tags_(&memory::kSpiRamResource) {} std::optional channels; std::optional sample_rate; @@ -72,9 +73,9 @@ class TrackTags { std::optional duration; - auto set(const Tag& key, const std::string& val) -> void; - auto at(const Tag& key) const -> std::optional; - auto operator[](const Tag& key) const -> std::optional; + auto set(const Tag& key, const std::pmr::string& val) -> void; + auto at(const Tag& key) const -> std::optional; + auto operator[](const Tag& key) const -> std::optional; /* * Returns a hash of the 'identifying' tags of this track. That is, a hash @@ -90,7 +91,7 @@ class TrackTags { private: Container encoding_; - std::unordered_map tags_; + std::pmr::unordered_map tags_; }; /* @@ -113,33 +114,33 @@ class TrackTags { class TrackData { private: const TrackId id_; - const std::string filepath_; + const std::pmr::string filepath_; const uint64_t tags_hash_; const uint32_t play_count_; const bool is_tombstoned_; public: /* Constructor used when adding new tracks to the database. */ - TrackData(TrackId id, const std::string& path, uint64_t hash) + TrackData(TrackId id, const std::pmr::string& path, uint64_t hash) : id_(id), - filepath_(path), + filepath_(path, &memory::kSpiRamResource), tags_hash_(hash), play_count_(0), is_tombstoned_(false) {} TrackData(TrackId id, - const std::string& path, + const std::pmr::string& path, uint64_t hash, uint32_t play_count, bool is_tombstoned) : id_(id), - filepath_(path), + filepath_(path, &memory::kSpiRamResource), tags_hash_(hash), play_count_(play_count), is_tombstoned_(is_tombstoned) {} auto id() const -> TrackId { return id_; } - auto filepath() const -> std::string { return filepath_; } + auto filepath() const -> std::pmr::string { return filepath_; } auto play_count() const -> uint32_t { return play_count_; } auto tags_hash() const -> uint64_t { return tags_hash_; } auto is_tombstoned() const -> bool { return is_tombstoned_; } @@ -156,7 +157,7 @@ class TrackData { * Clears the tombstone bit of this track, and updates the path to reflect its * new location. */ - auto Exhume(const std::string& new_path) const -> TrackData; + auto Exhume(const std::pmr::string& new_path) const -> TrackData; bool operator==(const TrackData&) const = default; }; @@ -178,7 +179,7 @@ class Track { auto data() const -> const TrackData& { return data_; } auto tags() const -> const TrackTags& { return tags_; } - auto TitleOrFilename() const -> shared_string; + auto TitleOrFilename() const -> std::pmr::string; bool operator==(const Track&) const = default; Track operator=(const Track& other) const { return Track(other); } diff --git a/src/database/index.cpp b/src/database/index.cpp index 9d77e530..79939aaa 100644 --- a/src/database/index.cpp +++ b/src/database/index.cpp @@ -41,7 +41,7 @@ const IndexInfo kAllAlbums{ }; static auto missing_component_text(const Track& track, Tag tag) - -> std::optional { + -> std::optional { switch (tag) { case Tag::kArtist: return "Unknown Artist"; @@ -76,9 +76,9 @@ auto Index(const IndexInfo& info, const Track& t, leveldb::WriteBatch* batch) for (std::uint8_t i = 0; i < info.components.size(); i++) { // Fill in the text for this depth. auto text = t.tags().at(info.components.at(i)); - std::string value; + std::pmr::string value; if (text) { - std::string orig = *text; + std::pmr::string orig = *text; key.item = col.transform(&orig[0], &orig[0] + orig.size()); value = *text; } else { @@ -94,7 +94,7 @@ auto Index(const IndexInfo& info, const Track& t, leveldb::WriteBatch* batch) } auto encoded = EncodeIndexKey(key); - batch->Put(encoded.slice, value); + batch->Put(encoded.slice, {value.data(), value.size()}); // If there are more components after this, then we need to finish by // narrowing the header with the current title. @@ -106,7 +106,7 @@ auto Index(const IndexInfo& info, const Track& t, leveldb::WriteBatch* batch) } auto ExpandHeader(const IndexKey::Header& header, - const std::optional& component) + const std::optional& component) -> IndexKey::Header { IndexKey::Header ret{header}; ret.depth++; diff --git a/src/database/records.cpp b/src/database/records.cpp index 0d28ca28..f493500c 100644 --- a/src/database/records.cpp +++ b/src/database/records.cpp @@ -8,7 +8,9 @@ #include +#include #include +#include #include #include #include @@ -18,7 +20,7 @@ #include "index.hpp" #include "komihash.h" -#include "shared_string.h" +#include "memory_resource.hpp" #include "track.hpp" // As LevelDB is a key-value store, each record in the database consists of a @@ -47,6 +49,11 @@ static const char kHashPrefix = 'H'; static const char kIndexPrefix = 'I'; static const char kFieldSeparator = '\0'; +using ostringstream = + std::basic_ostringstream, + std::pmr::polymorphic_allocator>; + /* * Helper function for allocating an appropriately-sized byte buffer, then * encoding data into it. @@ -78,7 +85,8 @@ auto cbor_encode(uint8_t** out_buf, T fn) -> std::size_t { return buf_size; } -OwningSlice::OwningSlice(std::string d) : data(d), slice(data) {} +OwningSlice::OwningSlice(std::pmr::string d) + : data(d), slice(data.data(), data.size()) {} /* 'D/' */ auto EncodeDataPrefix() -> OwningSlice { @@ -88,7 +96,7 @@ auto EncodeDataPrefix() -> OwningSlice { /* 'D/ 0xACAB' */ auto EncodeDataKey(const TrackId& id) -> OwningSlice { - std::ostringstream output; + ostringstream output; output.put(kDataPrefix).put(kFieldSeparator); output << TrackIdToBytes(id).data; return OwningSlice(output.str()); @@ -136,7 +144,7 @@ auto EncodeDataValue(const TrackData& track) -> OwningSlice { return; } }); - std::string as_str(reinterpret_cast(buf), buf_len); + std::pmr::string as_str(reinterpret_cast(buf), buf_len); delete buf; return OwningSlice(as_str); } @@ -174,7 +182,7 @@ auto ParseDataValue(const leveldb::Slice& slice) -> std::optional { if (err != CborNoError || !cbor_value_is_unsigned_integer(&val)) { return {}; } - std::string path(raw_path, len); + std::pmr::string path(raw_path, len); delete raw_path; err = cbor_value_get_uint64(&val, &raw_int); @@ -208,7 +216,7 @@ auto ParseDataValue(const leveldb::Slice& slice) -> std::optional { /* 'H/ 0xBEEF' */ auto EncodeHashKey(const uint64_t& hash) -> OwningSlice { - std::ostringstream output; + ostringstream output; output.put(kHashPrefix).put(kFieldSeparator); uint8_t buf[16]; @@ -222,7 +230,7 @@ auto EncodeHashKey(const uint64_t& hash) -> OwningSlice { } auto ParseHashValue(const leveldb::Slice& slice) -> std::optional { - return BytesToTrackId(slice.ToString()); + return BytesToTrackId({slice.data(), slice.size()}); } auto EncodeHashValue(TrackId id) -> OwningSlice { @@ -235,7 +243,7 @@ auto EncodeAllIndexesPrefix() -> OwningSlice { return OwningSlice({data, 2}); } -auto AppendIndexHeader(const IndexKey::Header& header, std::ostringstream* out) +auto AppendIndexHeader(const IndexKey::Header& header, ostringstream* out) -> void { *out << kIndexPrefix << kFieldSeparator; @@ -270,13 +278,13 @@ auto AppendIndexHeader(const IndexKey::Header& header, std::ostringstream* out) return; } }); - std::string encoded{reinterpret_cast(buf), buf_len}; + std::pmr::string encoded{reinterpret_cast(buf), buf_len}; delete buf; *out << encoded << kFieldSeparator; } auto EncodeIndexPrefix(const IndexKey::Header& header) -> OwningSlice { - std::ostringstream out; + ostringstream out; AppendIndexHeader(header, &out); return OwningSlice(out.str()); } @@ -296,7 +304,7 @@ auto EncodeIndexPrefix(const IndexKey::Header& header) -> OwningSlice { * id for now, but could reasonably be something like 'release year' as well. */ auto EncodeIndexKey(const IndexKey& key) -> OwningSlice { - std::ostringstream out; + ostringstream out; // Construct the header. AppendIndexHeader(key.header, &out); @@ -319,7 +327,7 @@ auto ParseIndexKey(const leveldb::Slice& slice) -> std::optional { IndexKey result{}; auto prefix = EncodeAllIndexesPrefix(); - if (!slice.starts_with(prefix.data)) { + if (!slice.starts_with(prefix.slice)) { return {}; } @@ -409,11 +417,11 @@ auto TrackIdToBytes(TrackId id) -> OwningSlice { cbor_encoder_init(&enc, buf, sizeof(buf), 0); cbor_encode_uint(&enc, id); std::size_t len = cbor_encoder_get_buffer_size(&enc, buf); - std::string as_str(reinterpret_cast(buf), len); + std::pmr::string as_str(reinterpret_cast(buf), len); return OwningSlice(as_str); } -auto BytesToTrackId(const std::string& bytes) -> std::optional { +auto BytesToTrackId(cpp::span bytes) -> std::optional { CborParser parser; CborValue val; cbor_parser_init(reinterpret_cast(bytes.data()), bytes.size(), diff --git a/src/database/tag_parser.cpp b/src/database/tag_parser.cpp index a4aaf0f5..8912690b 100644 --- a/src/database/tag_parser.cpp +++ b/src/database/tag_parser.cpp @@ -6,14 +6,17 @@ #include "tag_parser.hpp" -#include -#include #include -#include #include #include #include + +#include "esp_log.h" +#include "ff.h" #include "opusfile.h" +#include "tags.h" + +#include "memory_resource.hpp" namespace database { @@ -25,13 +28,14 @@ const static std::array, 5> kVorbisIdToTag = {{ {"GENRE", Tag::kGenre}, }}; -static auto convert_track_number(int number) -> std::string { +static auto convert_track_number(int number) -> std::pmr::string { std::ostringstream oss; oss << std::setw(4) << std::setfill('0') << number; - return oss.str(); + return std::pmr::string(oss.str()); } -static auto convert_track_number(const std::string& raw) -> std::string { +static auto convert_track_number(const std::pmr::string& raw) + -> std::pmr::string { uint32_t as_int = std::atoi(raw.c_str()); return convert_track_number(as_int); } @@ -106,7 +110,7 @@ static void tag(Tagctx* ctx, if (!tag) { return; } - std::string value{v}; + std::pmr::string value{v, &memory::kSpiRamResource}; if (value.empty()) { return; } @@ -126,8 +130,8 @@ TagParserImpl::TagParserImpl() { extension_to_parser_["opus"] = std::make_unique(); } -auto TagParserImpl::ReadAndParseTags(const std::string& path, TrackTags* out) - -> bool { +auto TagParserImpl::ReadAndParseTags(const std::pmr::string& path, + TrackTags* out) -> bool { { std::lock_guard lock{cache_mutex_}; std::optional cached = cache_.Get(path); @@ -139,8 +143,8 @@ auto TagParserImpl::ReadAndParseTags(const std::string& path, TrackTags* out) ITagParser* parser = &generic_parser_; auto dot_pos = path.find_last_of("."); - if (dot_pos != std::string::npos && path.size() - dot_pos > 1) { - std::string extension = path.substr(dot_pos + 1); + if (dot_pos != std::pmr::string::npos && path.size() - dot_pos > 1) { + std::pmr::string extension = path.substr(dot_pos + 1); std::transform(extension.begin(), extension.end(), extension.begin(), [](unsigned char c) { return std::tolower(c); }); if (extension_to_parser_.contains(extension)) { @@ -157,7 +161,7 @@ auto TagParserImpl::ReadAndParseTags(const std::string& path, TrackTags* out) // start. if (!out->at(Tag::kAlbumTrack)) { auto slash_pos = path.find_last_of("/"); - if (slash_pos != std::string::npos && path.size() - slash_pos > 1) { + if (slash_pos != std::pmr::string::npos && path.size() - slash_pos > 1) { out->set(Tag::kAlbumTrack, path.substr(slash_pos + 1)); } } @@ -175,8 +179,8 @@ auto TagParserImpl::ReadAndParseTags(const std::string& path, TrackTags* out) return true; } -auto GenericTagParser::ReadAndParseTags(const std::string& path, TrackTags* out) - -> bool { +auto GenericTagParser::ReadAndParseTags(const std::pmr::string& path, + TrackTags* out) -> bool { libtags::Aux aux; aux.tags = out; if (f_stat(path.c_str(), &aux.info) != FR_OK || @@ -239,9 +243,9 @@ auto GenericTagParser::ReadAndParseTags(const std::string& path, TrackTags* out) return true; } -auto OpusTagParser::ReadAndParseTags(const std::string& path, TrackTags* out) - -> bool { - std::string vfs_path = "/sdcard" + path; +auto OpusTagParser::ReadAndParseTags(const std::pmr::string& path, + TrackTags* out) -> bool { + std::pmr::string vfs_path = "/sdcard" + path; int err; OggOpusFile* f = op_test_file(vfs_path.c_str(), &err); if (f == NULL) { diff --git a/src/database/test/test_database.cpp b/src/database/test/test_database.cpp index 1ce364d9..6aec9bfb 100644 --- a/src/database/test/test_database.cpp +++ b/src/database/test/test_database.cpp @@ -26,23 +26,25 @@ namespace database { class TestBackends : public IFileGatherer, public ITagParser { public: - std::map tracks; + std::map tracks; - auto MakeTrack(const std::string& path, const std::string& title) -> void { + auto MakeTrack(const std::pmr::string& path, const std::pmr::string& title) + -> void { TrackTags tags; tags.encoding = Encoding::kMp3; tags.title = title; tracks[path] = tags; } - auto FindFiles(const std::string& root, - std::function cb) -> void override { + auto FindFiles(const std::pmr::string& root, + std::function cb) + -> void override { for (auto keyval : tracks) { std::invoke(cb, keyval.first); } } - auto ReadAndParseTags(const std::string& path, TrackTags* out) + auto ReadAndParseTags(const std::pmr::string& path, TrackTags* out) -> bool override { if (tracks.contains(path)) { *out = tracks.at(path); diff --git a/src/database/test/test_records.cpp b/src/database/test/test_records.cpp index 5729003e..2f59489c 100644 --- a/src/database/test/test_records.cpp +++ b/src/database/test/test_records.cpp @@ -12,10 +12,10 @@ #include "catch2/catch.hpp" -std::string ToHex(const std::string& s) { +std::pmr::string ToHex(const std::pmr::string& s) { std::ostringstream ret; - for (std::string::size_type i = 0; i < s.length(); ++i) + for (std::pmr::string::size_type i = 0; i < s.length(); ++i) ret << std::hex << std::setfill('0') << std::setw(2) << std::uppercase << (int)s[i]; diff --git a/src/database/track.cpp b/src/database/track.cpp index fa65261e..a3c7dc99 100644 --- a/src/database/track.cpp +++ b/src/database/track.cpp @@ -7,15 +7,16 @@ #include "track.hpp" #include -#include "shared_string.h" + +#include "memory_resource.hpp" namespace database { -auto TrackTags::set(const Tag& key, const std::string& val) -> void { +auto TrackTags::set(const Tag& key, const std::pmr::string& val) -> void { tags_[key] = val; } -auto TrackTags::at(const Tag& key) const -> std::optional { +auto TrackTags::at(const Tag& key) const -> std::optional { if (tags_.contains(key)) { return tags_.at(key); } @@ -23,12 +24,13 @@ auto TrackTags::at(const Tag& key) const -> std::optional { } auto TrackTags::operator[](const Tag& key) const - -> std::optional { + -> std::optional { return at(key); } -/* Helper function to update a komihash stream with a std::string. */ -auto HashString(komihash_stream_t* stream, const std::string& str) -> void { +/* Helper function to update a komihash stream with a std::pmr::string. */ +auto HashString(komihash_stream_t* stream, const std::pmr::string& str) + -> void { komihash_stream_update(stream, str.c_str(), str.length()); } @@ -58,7 +60,7 @@ auto TrackData::Entomb() const -> TrackData { return TrackData(id_, filepath_, tags_hash_, play_count_, true); } -auto TrackData::Exhume(const std::string& new_path) const -> TrackData { +auto TrackData::Exhume(const std::pmr::string& new_path) const -> TrackData { return TrackData(id_, new_path, tags_hash_, play_count_, false); } @@ -68,13 +70,13 @@ void swap(Track& first, Track& second) { second = temp; } -auto Track::TitleOrFilename() const -> shared_string { +auto Track::TitleOrFilename() const -> std::pmr::string { auto title = tags().at(Tag::kTitle); if (title) { return *title; } auto start = data().filepath().find_last_of('/'); - if (start == std::string::npos) { + if (start == std::pmr::string::npos) { return data().filepath(); } return data().filepath().substr(start); diff --git a/src/dev_console/CMakeLists.txt b/src/dev_console/CMakeLists.txt index 74911e66..5555bf61 100644 --- a/src/dev_console/CMakeLists.txt +++ b/src/dev_console/CMakeLists.txt @@ -5,5 +5,5 @@ idf_component_register( SRCS "console.cpp" INCLUDE_DIRS "include" - REQUIRES "console") + REQUIRES "console" "memory") target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS}) diff --git a/src/dev_console/console.cpp b/src/dev_console/console.cpp index 66fb6bf6..f2b1efea 100644 --- a/src/dev_console/console.cpp +++ b/src/dev_console/console.cpp @@ -16,16 +16,18 @@ #include "esp_log.h" #include "esp_system.h" +#include "memory_resource.hpp" + namespace console { int CmdLogLevel(int argc, char** argv) { - static const std::string usage = + static const std::pmr::string usage = "usage: loglevel [VERBOSE,DEBUG,INFO,WARN,ERROR,NONE]"; if (argc != 2) { std::cout << usage << std::endl; return 1; } - std::string level_str = argv[1]; + std::pmr::string level_str = argv[1]; std::transform(level_str.begin(), level_str.end(), level_str.begin(), [](unsigned char c) { return std::toupper(c); }); diff --git a/src/drivers/bluetooth.cpp b/src/drivers/bluetooth.cpp index 924cdf42..1d9d57df 100644 --- a/src/drivers/bluetooth.cpp +++ b/src/drivers/bluetooth.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "bluetooth_types.hpp" #include "esp_a2dp_api.h" @@ -21,6 +22,7 @@ #include "esp_wifi.h" #include "esp_wifi_types.h" #include "freertos/portmacro.h" +#include "memory_resource.hpp" #include "nvs.hpp" #include "tinyfsm/include/tinyfsm.hpp" @@ -108,13 +110,13 @@ auto Bluetooth::SetEventHandler(std::function cb) bluetooth::BluetoothState::event_handler(cb); } -auto DeviceName() -> std::string { +auto DeviceName() -> std::pmr::string { uint8_t mac[8]{0}; esp_efuse_mac_get_default(mac); std::ostringstream name; name << "TANGARA " << std::hex << static_cast(mac[0]) << static_cast(mac[1]); - return name.str(); + return std::pmr::string{name.str(), &memory::kSpiRamResource}; } namespace bluetooth { @@ -212,7 +214,7 @@ void Disabled::react(const events::Enable&) { esp_bt_gap_set_security_param(param_type, &iocap, sizeof(uint8_t)); // Set a reasonable name for the device. - std::string name = DeviceName(); + std::pmr::string name = DeviceName(); esp_bt_dev_set_device_name(name.c_str()); // Initialise GAP. This controls advertising our device, and scanning for @@ -307,8 +309,8 @@ auto Scanning::OnDeviceDiscovered(esp_bt_gap_cb_param_t* param) -> void { return; } - device.name = - std::string{reinterpret_cast(name), static_cast(length)}; + device.name = std::pmr::string{reinterpret_cast(name), + static_cast(length)}; bool is_preferred = false; { diff --git a/src/drivers/include/bluetooth_types.hpp b/src/drivers/include/bluetooth_types.hpp index 12ed5cb3..7e26f0d7 100644 --- a/src/drivers/include/bluetooth_types.hpp +++ b/src/drivers/include/bluetooth_types.hpp @@ -4,6 +4,8 @@ #include #include +#include "memory_resource.hpp" + namespace drivers { namespace bluetooth { @@ -11,7 +13,7 @@ typedef std::array mac_addr_t; struct Device { mac_addr_t address; - std::string name; + std::pmr::string name; uint32_t class_of_device; int8_t signal_strength; }; diff --git a/src/drivers/include/fatfs_audio_input.hpp b/src/drivers/include/fatfs_audio_input.hpp index e1f62811..705f6e7d 100644 --- a/src/drivers/include/fatfs_audio_input.hpp +++ b/src/drivers/include/fatfs_audio_input.hpp @@ -39,7 +39,7 @@ class FatfsAudioInput { std::shared_ptr storage_; RingbufHandle_t output_; - std::string path_; + std::pmr::string path_; }; } // namespace drivers diff --git a/src/drivers/storage.cpp b/src/drivers/storage.cpp index 6acb6870..0492b5dc 100644 --- a/src/drivers/storage.cpp +++ b/src/drivers/storage.cpp @@ -24,6 +24,7 @@ #include "sdmmc_cmd.h" #include "gpios.hpp" +#include "memory_resource.hpp" static const char* kTag = "SDSTORAGE"; static const uint8_t kMaxOpenFiles = 8; @@ -74,7 +75,7 @@ auto SdStorage::Create(IGpios& gpio) -> cpp::result { // Mount right now, not on first operation. FRESULT ferr = f_mount(fs, "", 1); if (ferr != FR_OK) { - std::string err_str; + std::pmr::string err_str; switch (ferr) { case FR_DISK_ERR: err_str = "FR_DISK_ERR"; diff --git a/src/drivers/test/test_storage.cpp b/src/drivers/test/test_storage.cpp index c785fa01..062de3af 100644 --- a/src/drivers/test/test_storage.cpp +++ b/src/drivers/test/test_storage.cpp @@ -22,9 +22,9 @@ namespace drivers { -static const std::string kTestFilename = "test"; -static const std::string kTestFilePath = - std::string(kStoragePath) + "/" + kTestFilename; +static const std::pmr::string kTestFilename = "test"; +static const std::pmr::string kTestFilePath = + std::pmr::string(kStoragePath) + "/" + kTestFilename; TEST_CASE("sd card storage", "[integration]") { I2CFixture i2c; @@ -46,7 +46,7 @@ TEST_CASE("sd card storage", "[integration]") { std::ifstream test_file; test_file.open(kTestFilePath.c_str()); - std::string line; + std::pmr::string line; REQUIRE(std::getline(test_file, line)); REQUIRE(line == "hello here is some test"); diff --git a/src/memory/include/memory_resource.hpp b/src/memory/include/memory_resource.hpp index e1d12b2a..ed4b1a1c 100644 --- a/src/memory/include/memory_resource.hpp +++ b/src/memory/include/memory_resource.hpp @@ -34,7 +34,8 @@ class Resource : public std::pmr::memory_resource { std::size_t bytes, std::size_t alignment) override; - bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override; + bool do_is_equal( + const std::pmr::memory_resource& other) const noexcept override; }; extern Resource kSpiRamResource; diff --git a/src/tasks/CMakeLists.txt b/src/tasks/CMakeLists.txt index 473684b9..0fdacf78 100644 --- a/src/tasks/CMakeLists.txt +++ b/src/tasks/CMakeLists.txt @@ -1,5 +1,5 @@ # Copyright 2023 jacqueline # # SPDX-License-Identifier: GPL-3.0-only -idf_component_register(SRCS "tasks.cpp" INCLUDE_DIRS "." REQUIRES "span") +idf_component_register(SRCS "tasks.cpp" INCLUDE_DIRS "." REQUIRES "span" "memory") target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS}) diff --git a/src/tasks/tasks.cpp b/src/tasks/tasks.cpp index 8dc2f204..dfcead06 100644 --- a/src/tasks/tasks.cpp +++ b/src/tasks/tasks.cpp @@ -12,33 +12,35 @@ #include "freertos/FreeRTOS.h" #include "freertos/portmacro.h" +#include "memory_resource.hpp" + namespace tasks { template -auto Name() -> std::string; +auto Name() -> std::pmr::string; template <> -auto Name() -> std::string { +auto Name() -> std::pmr::string { return "ui"; } template <> -auto Name() -> std::string { +auto Name() -> std::pmr::string { return "audio_dec"; } template <> -auto Name() -> std::string { +auto Name() -> std::pmr::string { return "audio_conv"; } template <> -auto Name() -> std::string { +auto Name() -> std::pmr::string { return "db_fg"; } template <> -auto Name() -> std::string { +auto Name() -> std::pmr::string { return "db_bg"; } template <> -auto Name() -> std::string { +auto Name() -> std::pmr::string { return "nvs"; } @@ -185,7 +187,7 @@ auto Worker::Main(void* instance) { } } -Worker::Worker(const std::string& name, +Worker::Worker(const std::pmr::string& name, cpp::span stack, std::size_t queue_size, UBaseType_t priority) diff --git a/src/tasks/tasks.hpp b/src/tasks/tasks.hpp index 2e43b01a..b87c7fa2 100644 --- a/src/tasks/tasks.hpp +++ b/src/tasks/tasks.hpp @@ -45,7 +45,7 @@ enum class Type { }; template -auto Name() -> std::string; +auto Name() -> std::pmr::string; template auto AllocateStack() -> cpp::span; template @@ -76,7 +76,7 @@ auto StartPersistent(BaseType_t core, const std::function& fn) class Worker { private: - Worker(const std::string& name, + Worker(const std::pmr::string& name, cpp::span stack, std::size_t queue_size, UBaseType_t priority); diff --git a/src/ui/include/modal_confirm.hpp b/src/ui/include/modal_confirm.hpp index 4be6b68e..29d80041 100644 --- a/src/ui/include/modal_confirm.hpp +++ b/src/ui/include/modal_confirm.hpp @@ -19,7 +19,7 @@ namespace modals { class Confirm : public Modal { public: - Confirm(Screen*, const std::string& title, bool has_cancel); + Confirm(Screen*, const std::pmr::string& title, bool has_cancel); private: lv_obj_t* container_; diff --git a/src/ui/include/modal_progress.hpp b/src/ui/include/modal_progress.hpp index 96897029..f312d509 100644 --- a/src/ui/include/modal_progress.hpp +++ b/src/ui/include/modal_progress.hpp @@ -19,7 +19,7 @@ namespace modals { class Progress : public Modal { public: - Progress(Screen*, std::string title); + Progress(Screen*, std::pmr::string title); private: lv_obj_t* container_; diff --git a/src/ui/include/screen.hpp b/src/ui/include/screen.hpp index f93d17a5..76251a72 100644 --- a/src/ui/include/screen.hpp +++ b/src/ui/include/screen.hpp @@ -64,7 +64,7 @@ class Screen { class MenuScreen : public Screen { public: - MenuScreen(const std::string& title, bool show_back_button = true); + MenuScreen(const std::pmr::string& title, bool show_back_button = true); }; } // namespace ui diff --git a/src/ui/include/screen_onboarding.hpp b/src/ui/include/screen_onboarding.hpp index 81ce6d3a..0c3c61fb 100644 --- a/src/ui/include/screen_onboarding.hpp +++ b/src/ui/include/screen_onboarding.hpp @@ -18,7 +18,7 @@ namespace screens { class Onboarding : public Screen { public: - Onboarding(const std::string& title, bool show_prev, bool show_next); + Onboarding(const std::pmr::string& title, bool show_prev, bool show_next); private: lv_obj_t* window_; diff --git a/src/ui/include/screen_playing.hpp b/src/ui/include/screen_playing.hpp index f2998c88..2e29130c 100644 --- a/src/ui/include/screen_playing.hpp +++ b/src/ui/include/screen_playing.hpp @@ -45,7 +45,8 @@ class Playing : public Screen { private: auto control_button(lv_obj_t* parent, char* icon) -> lv_obj_t*; - auto next_up_label(lv_obj_t* parent, const std::string& text) -> lv_obj_t*; + auto next_up_label(lv_obj_t* parent, const std::pmr::string& text) + -> lv_obj_t*; auto BindTrack(const database::Track& track) -> void; auto ApplyNextUp(const std::vector& tracks) -> void; diff --git a/src/ui/include/screen_track_browser.hpp b/src/ui/include/screen_track_browser.hpp index 3d347158..fdeb3afe 100644 --- a/src/ui/include/screen_track_browser.hpp +++ b/src/ui/include/screen_track_browser.hpp @@ -23,7 +23,7 @@ class TrackBrowser : public Screen { public: TrackBrowser( std::weak_ptr db, - const std::string& title, + const std::pmr::string& title, std::future*>&& initial_page); ~TrackBrowser() {} diff --git a/src/ui/include/widget_top_bar.hpp b/src/ui/include/widget_top_bar.hpp index 87920338..1a2c826a 100644 --- a/src/ui/include/widget_top_bar.hpp +++ b/src/ui/include/widget_top_bar.hpp @@ -11,6 +11,8 @@ #include "lvgl.h" +#include "memory_resource.hpp" + namespace ui { namespace widgets { @@ -19,7 +21,7 @@ class TopBar { public: struct Configuration { bool show_back_button; - std::string title; + std::pmr::string title; }; enum class PlaybackState { diff --git a/src/ui/modal_confirm.cpp b/src/ui/modal_confirm.cpp index 14d56123..dfb1b1eb 100644 --- a/src/ui/modal_confirm.cpp +++ b/src/ui/modal_confirm.cpp @@ -37,7 +37,9 @@ static void button_confirm_cb(lv_event_t* e) { events::Ui().Dispatch(internal::ModalConfirmPressed{}); } -Confirm::Confirm(Screen* host, const std::string& title_text, bool has_cancel) +Confirm::Confirm(Screen* host, + const std::pmr::string& title_text, + bool has_cancel) : Modal(host) { lv_obj_set_layout(root_, LV_LAYOUT_FLEX); lv_obj_set_flex_flow(root_, LV_FLEX_FLOW_COLUMN); diff --git a/src/ui/modal_progress.cpp b/src/ui/modal_progress.cpp index f60b324a..1213de7e 100644 --- a/src/ui/modal_progress.cpp +++ b/src/ui/modal_progress.cpp @@ -28,7 +28,7 @@ namespace ui { namespace modals { -Progress::Progress(Screen* host, std::string title_text) : Modal(host) { +Progress::Progress(Screen* host, std::pmr::string title_text) : Modal(host) { lv_obj_set_layout(root_, LV_LAYOUT_FLEX); lv_obj_set_flex_flow(root_, LV_FLEX_FLOW_COLUMN); lv_obj_set_flex_align(root_, LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, diff --git a/src/ui/screen.cpp b/src/ui/screen.cpp index c9933042..48bffff7 100644 --- a/src/ui/screen.cpp +++ b/src/ui/screen.cpp @@ -57,7 +57,7 @@ auto Screen::CreateTopBar(lv_obj_t* parent, return top_bar_.get(); } -MenuScreen::MenuScreen(const std::string& title, bool show_back_button) +MenuScreen::MenuScreen(const std::pmr::string& title, bool show_back_button) : Screen() { lv_group_set_wrap(group_, false); diff --git a/src/ui/screen_onboarding.cpp b/src/ui/screen_onboarding.cpp index 15f610a7..f5ce004f 100644 --- a/src/ui/screen_onboarding.cpp +++ b/src/ui/screen_onboarding.cpp @@ -32,7 +32,7 @@ static void prev_btn_cb(lv_event_t* ev) { events::Ui().Dispatch(internal::OnboardingNavigate{.forwards = false}); } -Onboarding::Onboarding(const std::string& title, +Onboarding::Onboarding(const std::pmr::string& title, bool show_prev, bool show_next) { window_ = lv_win_create(root_, 18); @@ -68,7 +68,8 @@ LinkToManual::LinkToManual() : Onboarding("Welcome!", false, true) { lv_qrcode_update(qr, kManualUrl, sizeof(kManualUrl)); } -static void create_radio_button(lv_obj_t* parent, const std::string& text) { +static void create_radio_button(lv_obj_t* parent, + const std::pmr::string& text) { lv_obj_t* obj = lv_checkbox_create(parent); lv_checkbox_set_text(obj, text.c_str()); // TODO: radio styling diff --git a/src/ui/screen_playing.cpp b/src/ui/screen_playing.cpp index e0fff095..bd55924d 100644 --- a/src/ui/screen_playing.cpp +++ b/src/ui/screen_playing.cpp @@ -96,7 +96,7 @@ auto Playing::control_button(lv_obj_t* parent, char* icon) -> lv_obj_t* { return button; } -auto Playing::next_up_label(lv_obj_t* parent, const std::string& text) +auto Playing::next_up_label(lv_obj_t* parent, const std::pmr::string& text) -> lv_obj_t* { lv_obj_t* button = lv_list_add_btn(parent, NULL, text.c_str()); lv_label_set_long_mode(lv_obj_get_child(button, -1), LV_LABEL_LONG_DOT); diff --git a/src/ui/screen_settings.cpp b/src/ui/screen_settings.cpp index faeac865..63964da3 100644 --- a/src/ui/screen_settings.cpp +++ b/src/ui/screen_settings.cpp @@ -56,7 +56,7 @@ static void open_sub_menu_cb(lv_event_t* e) { static void sub_menu(lv_obj_t* list, lv_group_t* group, - const std::string& text, + const std::pmr::string& text, Page page) { lv_obj_t* item = lv_list_add_btn(list, NULL, text.c_str()); lv_group_add_obj(group, item); @@ -93,8 +93,8 @@ static auto settings_container(lv_obj_t* parent) -> lv_obj_t* { } static auto label_pair(lv_obj_t* parent, - const std::string& left, - const std::string& right) -> lv_obj_t* { + const std::pmr::string& left, + const std::pmr::string& right) -> lv_obj_t* { lv_obj_t* container = settings_container(parent); lv_obj_t* left_label = lv_label_create(container); lv_label_set_text(left_label, left.c_str()); diff --git a/src/ui/screen_track_browser.cpp b/src/ui/screen_track_browser.cpp index 67c47628..6cd92a04 100644 --- a/src/ui/screen_track_browser.cpp +++ b/src/ui/screen_track_browser.cpp @@ -60,7 +60,7 @@ static void item_select_cb(lv_event_t* ev) { TrackBrowser::TrackBrowser( std::weak_ptr db, - const std::string& title, + const std::pmr::string& title, std::future*>&& initial_page) : db_(db), list_(nullptr), diff --git a/src/ui/ui_fsm.cpp b/src/ui/ui_fsm.cpp index 18e9caf4..62fd46f1 100644 --- a/src/ui/ui_fsm.cpp +++ b/src/ui/ui_fsm.cpp @@ -297,7 +297,7 @@ void Browse::react(const internal::RecordSelected& ev) { return; } auto query = db->GetPage(&cont.value()); - std::string title = record.text().value_or("TODO"); + std::pmr::string title = record.text().value_or("TODO"); PushScreen(std::make_shared( sServices->database(), title, std::move(query))); }