From b6d5c2760e90739ea845a774e2c34a0d8a0d2694 Mon Sep 17 00:00:00 2001 From: Vladislav Nepogodin Date: Wed, 3 Jul 2024 23:50:15 +0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=91=B7=20gucc:=20rewrite=20pacmanconf=20t?= =?UTF-8?q?o=20reuse=20file=20content?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit don't make extra memory allocations: - don't allocate vector of strings to find locations - don't convert that vector of strings into new string previously: ``` heaptrack stats: allocations: 69 leaked allocations: 0 temporary allocations: 4 ``` after: ``` heaptrack stats: allocations: 32 leaked allocations: 0 temporary allocations: 5 ``` --- gucc/src/pacmanconf_repo.cpp | 36 ++++++++++++++++++++-------------- gucc/tests/unit-pacmanconf.cpp | 4 ++-- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/gucc/src/pacmanconf_repo.cpp b/gucc/src/pacmanconf_repo.cpp index 22943d4..1e55c97 100644 --- a/gucc/src/pacmanconf_repo.cpp +++ b/gucc/src/pacmanconf_repo.cpp @@ -1,5 +1,6 @@ #include "gucc/pacmanconf_repo.hpp" #include "gucc/file_utils.hpp" +#include "gucc/string_utils.hpp" #include // for ofstream #include // for string @@ -17,9 +18,9 @@ #pragma GCC diagnostic ignored "-Wold-style-cast" #endif +#include #include #include -#include #include #if defined(__clang__) @@ -31,33 +32,38 @@ namespace gucc::detail::pacmanconf { bool push_repos_front(std::string_view file_path, std::string_view value) noexcept { - using StringVec = std::vector; auto&& file_content = file_utils::read_whole_file(file_path); if (file_content.empty()) { spdlog::error("[PACMANCONFREPO] '{}' error occurred!", file_path); return false; } - auto&& content_lines = file_content | ranges::views::split('\n') | ranges::to>(); - for (std::size_t i = 1; i < content_lines.size(); ++i) { - const std::string_view current_line{content_lines[i - 1]}; - if (current_line.empty() || current_line.starts_with('#') || !current_line.starts_with('[') || current_line.starts_with("[options]")) { - continue; - } - auto&& to_be_inserted = value | ranges::views::split('\n') | ranges::to>(); - to_be_inserted.emplace_back("\n"); - content_lines.insert(content_lines.begin() + static_cast(i - 1), - std::move_iterator(to_be_inserted.begin()), std::move_iterator(to_be_inserted.end())); - break; + auto file_split_view = utils::make_split_view(file_content); + // Find the insertion point (using ranges for iteration) + auto insertion_point_it = ranges::find_if( + file_split_view, + [](auto&& rng) { + auto&& line = std::string_view(&*rng.begin(), static_cast(ranges::distance(rng))); + return !line.empty() && !line.starts_with('#') && line.starts_with('[') && !line.starts_with("[options]"); + }); + + // Handle case where insertion point is not found + if (insertion_point_it == ranges::end(file_split_view)) { + // No suitable insertion point found + spdlog::error("[PACMANCONFREPO] Could not find a suitable insertion point in {}", file_path); + return false; } + auto line = *insertion_point_it; + auto pos = file_content.find(line); + file_content.insert(pos - 1, std::string{'\n'} + std::string{value} + std::string{'\n'}); + std::ofstream pacmanconf_file{file_path.data()}; if (!pacmanconf_file.is_open()) { spdlog::error("[PACMANCONFREPO] '{}' open failed: {}", file_path, std::strerror(errno)); return false; } - std::string&& result = content_lines | ranges::views::join('\n') | ranges::to(); - pacmanconf_file << result; + pacmanconf_file << file_content; return true; } diff --git a/gucc/tests/unit-pacmanconf.cpp b/gucc/tests/unit-pacmanconf.cpp index ca7fb13..bc20d39 100644 --- a/gucc/tests/unit-pacmanconf.cpp +++ b/gucc/tests/unit-pacmanconf.cpp @@ -98,7 +98,6 @@ ParallelDownloads = 10 [cachyos] Include = /etc/pacman.d/cachyos-mirrorlist - [core] Include = /etc/pacman.d/mirrorlist @@ -115,7 +114,8 @@ Include = /etc/pacman.d/mirrorlist #Include = /etc/pacman.d/mirrorlist [multilib] -Include = /etc/pacman.d/mirrorlist)"; +Include = /etc/pacman.d/mirrorlist +)"; int main() { using namespace gucc;