From a48b5d30483ddcdc5f99cc1e4268f8c92bdb94ea Mon Sep 17 00:00:00 2001 From: Andrew D Smith Date: Mon, 31 Aug 2026 19:07:22 -0700 Subject: [PATCH 01/29] src/quality_score.hcpp: renaming the to_string function because the adl was doing strange things --- src/quality_score.cpp | 3 ++- src/quality_score.hpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/quality_score.cpp b/src/quality_score.cpp index 37232283..d9e1ce88 100644 --- a/src/quality_score.cpp +++ b/src/quality_score.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -70,7 +71,7 @@ adjust_fastq_qual_encoding(std::vector &qual_by_pos, } [[nodiscard]] auto -to_string(const falco::encoding e) -> std::string { +encoding_to_string(const falco::encoding e) -> std::string { const auto u = std::to_underlying(e); assert(u < std::size(falco::format_labels)); return falco::format_labels[u]; // NOLINT(*-pro-bounds-constant-array-index) diff --git a/src/quality_score.hpp b/src/quality_score.hpp index 19db4874..5da3656c 100644 --- a/src/quality_score.hpp +++ b/src/quality_score.hpp @@ -52,7 +52,7 @@ using qual_array = std::array; } // namespace falco [[nodiscard]] auto -to_string(const falco::encoding e) -> std::string; +encoding_to_string(const falco::encoding e) -> std::string; [[nodiscard]] auto get_quality_score_offset(const falco::encoding e) -> std::int64_t; From 3697635d57d4e82e2c0a26035f239599d964022e Mon Sep 17 00:00:00 2001 From: Andrew D Smith Date: Mon, 31 Aug 2026 19:08:13 -0700 Subject: [PATCH 02/29] .cppcheck_suppress: ignoring fmt and ignoring constStatement which seems broken now --- .cppcheck_suppress | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.cppcheck_suppress b/.cppcheck_suppress index 21451291..fc804705 100644 --- a/.cppcheck_suppress +++ b/.cppcheck_suppress @@ -35,9 +35,12 @@ missingInclude *:*CLI11.hpp *:*json.hpp *:*boost_unordered.hpp +*:fmt/*.h # Problem caused by external files toomanyconfigs # More problems caused by external files -- with too many ifdefs normalCheckLevelMaxBranches # This seems not to work with the designs used here duplInheritedMember +# Seems like iterator variables for std::views disagree with this +constStatement From 6633d46e57a74edec3ccc756c70f68a15fbe31c2 Mon Sep 17 00:00:00 2001 From: Andrew D Smith Date: Mon, 31 Aug 2026 19:08:40 -0700 Subject: [PATCH 03/29] src/samrec.cpp: adding missing include --- src/samrec.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/samrec.cpp b/src/samrec.cpp index 7368fde6..14ff8a96 100644 --- a/src/samrec.cpp +++ b/src/samrec.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #ifdef BAM_FREVERSE From c256b3956baeb66d5ba0f1ac82cd79f952094a96 Mon Sep 17 00:00:00 2001 From: Andrew D Smith Date: Mon, 31 Aug 2026 19:11:11 -0700 Subject: [PATCH 04/29] src/tile_processor.cpp: renaming variables to avoid shadowing --- src/tile_processor.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/tile_processor.cpp b/src/tile_processor.cpp index 11a46541..fb3e9ed2 100644 --- a/src/tile_processor.cpp +++ b/src/tile_processor.cpp @@ -14,9 +14,6 @@ #include #include -#define FMT_HEADER_ONLY -#include "fmt/format.h" - #include #include #include @@ -28,6 +25,7 @@ #include #include #include +#include // for std::get #include #include @@ -170,18 +168,19 @@ tile_processor::add_and_consume( const auto pair_plus = [](const auto &a, const auto &b) { return std::pair{a.first + b.first, a.second + b.second}; }; - for (auto &[tile_id, rhs_qual] : rhs.quals) { - const auto quals_itr = quals.find(tile_id); + for (auto &[rhs_tile_id, rhs_qual] : rhs.quals) { + const auto quals_itr = quals.find(rhs_tile_id); if (quals_itr != std::end(quals)) { - auto &qual = quals_itr->second; - if (std::size(rhs_qual) > std::size(qual)) - std::swap(rhs_qual, qual); - std::ranges::transform(qual, rhs_qual, std::begin(qual), pair_plus); + auto &curr_qual = quals_itr->second; + if (std::size(rhs_qual) > std::size(curr_qual)) + std::swap(rhs_qual, curr_qual); + std::ranges::transform(curr_qual, rhs_qual, std::begin(curr_qual), + pair_plus); rhs_qual.clear(); rhs_qual.shrink_to_fit(); } else - quals.emplace(tile_id, std::move(rhs_qual)); + quals.emplace(rhs_tile_id, std::move(rhs_qual)); } rhs.release(); } From 7e962a2a66193c7f663e6a4b03fb5dd4b9988c5c Mon Sep 17 00:00:00 2001 From: Andrew D Smith Date: Mon, 31 Aug 2026 19:11:37 -0700 Subject: [PATCH 05/29] src/bam_file.hcpp: headers and formatting for new clang-tidy --- src/bam_file.cpp | 6 ++++-- src/bam_file.hpp | 9 ++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/bam_file.cpp b/src/bam_file.cpp index cd152bca..bee2257d 100644 --- a/src/bam_file.cpp +++ b/src/bam_file.cpp @@ -19,7 +19,9 @@ #include #include #include +#include #include +#include [[nodiscard]] auto estimate_n_reads_bam(const std::string &filename) @@ -63,8 +65,8 @@ estimate_n_reads_bam(const std::string &filename) } [[nodiscard]] auto -init_dups(const std::string &filename, - const std::uint64_t n_unique) -> dups_map_t { +init_dups(const std::string &filename, const std::uint64_t n_unique) + -> dups_map_t { static constexpr auto complem = [](const auto x) { return "TNGNNNCNNNNNNNNNNNNA"[x - 'A']; }; diff --git a/src/bam_file.hpp b/src/bam_file.hpp index 606df5d9..93b52e41 100644 --- a/src/bam_file.hpp +++ b/src/bam_file.hpp @@ -62,7 +62,10 @@ class bam_file { ~bam_file() = default; // clang-format on - [[nodiscard]] operator bool() const { return !had_last_chunks; } + [[nodiscard]] + operator bool() const { + return !had_last_chunks; + } friend auto reset(bam_file &reads_file) -> void; @@ -121,8 +124,8 @@ estimate_n_reads_bam(const std::string &filename) -> std::tuple; [[nodiscard]] auto -init_dups(const std::string &filename, - const std::uint64_t n_unique) -> dups_map_t; +init_dups(const std::string &filename, const std::uint64_t n_unique) + -> dups_map_t; inline auto make_tasks(bam_file &reads_file, // From d9a4f4534ed441ddcfc2f485fd37b27fc6e829d6 Mon Sep 17 00:00:00 2001 From: Andrew D Smith Date: Mon, 31 Aug 2026 19:12:46 -0700 Subject: [PATCH 06/29] src/base_groups.hpp: removing nodiscard on void functions --- src/base_groups.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/base_groups.hpp b/src/base_groups.hpp index 75a561d5..2dcbc068 100644 --- a/src/base_groups.hpp +++ b/src/base_groups.hpp @@ -23,8 +23,8 @@ make_base_groups(const std::uint64_t n_bases, const std::uint64_t n_initial, const std::uint64_t n_groups_target) -> base_group_vec; [[nodiscard]] auto -get_default_base_groups(const std::uint64_t n_bases, - const bool make_groups) -> base_group_vec; +get_default_base_groups(const std::uint64_t n_bases, const bool make_groups) + -> base_group_vec; [[nodiscard]] auto make_group_tag(const base_group_t g) -> std::string; @@ -32,7 +32,7 @@ make_group_tag(const base_group_t g) -> std::string; [[nodiscard]] auto make_group_tag_quoted(const base_group_t g) -> std::string; -[[nodiscard]] auto +void apply_base_groups(const base_group_vec &groups, auto &rows) { assert(std::size(rows) <= groups.back().second); auto group_itr = std::cbegin(groups); @@ -50,7 +50,7 @@ apply_base_groups(const base_group_vec &groups, auto &rows) { rows.resize(current_row); } -[[nodiscard]] auto +void apply_base_groups(const base_group_vec &groups, auto &rows, const auto &adder) { assert(std::size(rows) <= groups.back().second); auto group_itr = std::cbegin(groups); From 4a8c6f0503a629d5324efaa8819166b4a1f3f3a4 Mon Sep 17 00:00:00 2001 From: Andrew D Smith Date: Mon, 31 Aug 2026 19:13:27 -0700 Subject: [PATCH 07/29] src/sam_file.cpp: adding includes and initializing cursor and last in ctor --- src/sam_file.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sam_file.cpp b/src/sam_file.cpp index f03293db..8fb4cedc 100644 --- a/src/sam_file.cpp +++ b/src/sam_file.cpp @@ -9,9 +9,11 @@ #include #include #include +#include #include #include #include +#include #include sam_file::sam_file(const std::string &filename, const std::int64_t buf_size) : @@ -22,6 +24,8 @@ sam_file::sam_file(const std::string &filename, const std::int64_t buf_size) : "failed to read file"); if (!skip_header()) std::runtime_error("failed to validated SAM file header: " + filename); + cursor = std::begin(buffer); + last = std::begin(buffer); } [[nodiscard]] auto From cd9127ea4f0b7f314758484f1adb2cc9891c8747 Mon Sep 17 00:00:00 2001 From: Andrew D Smith Date: Mon, 31 Aug 2026 19:13:49 -0700 Subject: [PATCH 08/29] src/kmer_counter.hcpp: removing the apply_groups function which isn't used --- src/kmer_counter.cpp | 8 ++++---- src/kmer_counter.hpp | 6 ++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/kmer_counter.cpp b/src/kmer_counter.cpp index 2fc57b84..8048a713 100644 --- a/src/kmer_counter.cpp +++ b/src/kmer_counter.cpp @@ -174,10 +174,10 @@ kmer_counter::decode_kmer(auto word, const auto n_bases) -> std::string { return r; } -auto -kmer_counter::apply_groups([[maybe_unused]] const run_mode &mode) -> void { - // ADS: !!! should we be computing the 'results' here? -} +// auto +// kmer_counter::apply_groups([[maybe_unused]] const run_mode &mode) -> void { +// // ADS: !!! should we be computing the 'results' here? +// } [[nodiscard]] auto get_grade_kmer(const std::vector &results) -> std::string { diff --git a/src/kmer_counter.hpp b/src/kmer_counter.hpp index 2013f255..2b5e5896 100644 --- a/src/kmer_counter.hpp +++ b/src/kmer_counter.hpp @@ -12,8 +12,6 @@ #include // IWYU pragma: keep #include -class run_mode; - struct kmer_result { // holds info for {kmer} x {position} to be sorted, filtered and output std::uint64_t kmer{}; @@ -83,8 +81,8 @@ struct kmer_counter { } } - auto - apply_groups(const run_mode &mode) -> void; + // auto + // apply_groups(const run_mode &mode) -> void; auto operator+=(const kmer_counter &rhs) -> const kmer_counter &; From a39a7c8b0a5e8261a6645c41c36b92d7e7b5ac60 Mon Sep 17 00:00:00 2001 From: Andrew D Smith Date: Mon, 31 Aug 2026 19:15:01 -0700 Subject: [PATCH 09/29] src/original_duplicates.cpp: changed loop to alg --- src/original_duplicates.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/original_duplicates.cpp b/src/original_duplicates.cpp index 8d9bc26c..fba205e5 100644 --- a/src/original_duplicates.cpp +++ b/src/original_duplicates.cpp @@ -17,6 +17,7 @@ #include #include #include +#include // for std::move #include [[nodiscard]] auto @@ -55,7 +56,7 @@ initialize_original_duplicates( std::ranges::for_each(workers, [](auto &w) { w.join(); }); std::vector ret; ret.reserve(n_files); - for (const auto &d : dups) - ret.emplace_back(d); + std::ranges::for_each(dups, + [&](auto &&d) { ret.emplace_back(std::move(d)); }); return ret; } From 5396c2e8ee8b9b96a5590f2c871dbbac38705acf Mon Sep 17 00:00:00 2001 From: Andrew D Smith Date: Mon, 31 Aug 2026 19:15:34 -0700 Subject: [PATCH 10/29] src/falco_utils.hcpp: fixing nodiscards and an include --- src/falco_utils.cpp | 1 + src/falco_utils.hpp | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/falco_utils.cpp b/src/falco_utils.cpp index f150925e..51525e24 100644 --- a/src/falco_utils.cpp +++ b/src/falco_utils.cpp @@ -2,6 +2,7 @@ #include "falco_utils.hpp" +#include #include #include #include diff --git a/src/falco_utils.hpp b/src/falco_utils.hpp index bd79a800..f8e75bd1 100644 --- a/src/falco_utils.hpp +++ b/src/falco_utils.hpp @@ -95,7 +95,7 @@ static constexpr std::int64_t gigabytes = 1024 * 1024 * 1024; static constexpr std::int64_t megabytes = 1024 * 1024; static constexpr std::int64_t kilobytes = 1024; -[[nodiscard]] inline auto +inline auto resize_gc_content(const std::uint32_t updated_length, std::vector &gc_content) { const auto prev_size = std::size(gc_content); @@ -340,8 +340,8 @@ five_quants(const auto &a) -> std::array { // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) [[nodiscard]] auto -size_to_units(const std::int64_t s, - const std::string &suffix = "iB") -> std::string; +size_to_units(const std::int64_t s, const std::string &suffix = "iB") + -> std::string; [[nodiscard]] inline auto get_max_size(const auto &x) { @@ -351,8 +351,8 @@ get_max_size(const auto &x) { } [[nodiscard]] inline auto -estimate_read_length_fastq_chunk(const auto &data, - const auto n) -> std::uint64_t { +estimate_read_length_fastq_chunk(const auto &data, const auto n) + -> std::uint64_t { static constexpr auto fastq_lines_per_read = 4; assert(n >= 1); const auto valid = [](const auto c) { From d39f1dfc6dcdfc62dcc6a9ed88a3457a2faec245 Mon Sep 17 00:00:00 2001 From: Andrew D Smith Date: Mon, 31 Aug 2026 19:16:19 -0700 Subject: [PATCH 11/29] src/falco_analyzer.cpp: adding an include for iwyu that seems wrong and moving n_tasks into a narrower scope --- src/falco_analyzer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/falco_analyzer.cpp b/src/falco_analyzer.cpp index 145a0ec1..85672b54 100644 --- a/src/falco_analyzer.cpp +++ b/src/falco_analyzer.cpp @@ -20,6 +20,7 @@ #include #include #include +#include // for std::get (iwyu fp) #include #include #include @@ -34,7 +35,6 @@ analyze(const std::uint32_t n_threads, const run_mode &mode, const std::int32_t n_files = static_cast(std::size(infos)); if (dups_init.empty()) dups_init.resize(n_files); - std::vector n_tasks(n_files); std::atomic_uint32_t n_active_files{static_cast(n_files)}; auto results = std::vector(n_threads, std::vector(n_files)); @@ -45,6 +45,7 @@ analyze(const std::uint32_t n_threads, const run_mode &mode, tq.push(file_id, std::monostate{}); { // scope to join jthreads + std::vector n_tasks(n_files); std::vector workers; for (const auto th_id : std::views::iota(0u, n_threads)) workers.emplace_back([&, n_threads, th_id] { From 8cc60aacf8324dce30f6be99869df0e222586474 Mon Sep 17 00:00:00 2001 From: Andrew D Smith Date: Mon, 31 Aug 2026 19:17:45 -0700 Subject: [PATCH 12/29] src/bgzf_reader.cpp: static analysis --- src/bgzf_reader.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/bgzf_reader.cpp b/src/bgzf_reader.cpp index 1805c5a4..767a14ac 100644 --- a/src/bgzf_reader.cpp +++ b/src/bgzf_reader.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,7 @@ get_unaligned_le32(const auto p) -> std::int32_t { get_isize(const auto data, const auto data_size) { static constexpr decltype(data_size) isize_size = 4; assert(data_size > isize_size); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) const auto data_isize = data + data_size - isize_size; return data_size < isize_size ? 0 : get_unaligned_le32(data_isize); } @@ -50,7 +52,8 @@ bgzf_reader::bgzf_reader(const std::string &filename, next_in{inbuf.get()}, // end_in{inbuf.get()}, // next_out{outbuf.get()}, // - end_out{outbuf.get() + buf_size} // + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + end_out{outbuf.get() + buf_size} // {} [[nodiscard]] auto From 646cd9c5fb67ee45f0e06c031706dc98163699fb Mon Sep 17 00:00:00 2001 From: Andrew D Smith Date: Mon, 31 Aug 2026 19:20:42 -0700 Subject: [PATCH 13/29] src/falco_grade.hcpp: making a member function get_tile static and removing always true condition for has_empty_reads --- src/falco_grade.cpp | 12 ++++++------ src/falco_grade.hpp | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/falco_grade.cpp b/src/falco_grade.cpp index 94796fd5..8f1a8274 100644 --- a/src/falco_grade.cpp +++ b/src/falco_grade.cpp @@ -61,7 +61,7 @@ file_grades::grade(const std::string &label) const -> std::string { } [[nodiscard]] auto -file_grades::get_title(const std::string &name) const -> std::string { +file_grades::get_title(const std::string &name) -> std::string { const auto itr = std::ranges::find(section_names, name); if (itr == std::cend(section_names)) throw std::runtime_error(std::format("bad section name: {}", name)); @@ -106,8 +106,8 @@ grader_set::get_grader(const std::string &label) -> const grader & { } [[nodiscard]] auto -grader_set::get_grade(const std::string &label, - const double value) -> std::string { +grader_set::get_grade(const std::string &label, const double value) + -> std::string { return get_grader(label).identify_grade(value); } @@ -129,7 +129,7 @@ get_grade_sequence_length(const std::vector &lengths) static constexpr auto label = "sequence_length"; if (lengths.empty()) return grader_set::get_grade(label, 0.0); - const bool has_empty_reads = std::size(lengths) > 0 && lengths[0] > 0; + const bool has_empty_reads = lengths[0] > 0; if (has_empty_reads) return "fail"; const auto n_lengths = @@ -153,8 +153,8 @@ single_delta(const auto a, const auto b, const auto tot) { } [[nodiscard]] static auto -get_grade_sequence_impl(const std::vector &nucs, - auto &&delta) -> std::string { +get_grade_sequence_impl(const std::vector &nucs, auto &&delta) + -> std::string { static constexpr auto label = "sequence"; if (nucs.empty()) return grader_set::get_grade(label, 0.0); diff --git a/src/falco_grade.hpp b/src/falco_grade.hpp index 903a596e..6de99820 100644 --- a/src/falco_grade.hpp +++ b/src/falco_grade.hpp @@ -83,8 +83,8 @@ struct file_grades { [[nodiscard]] auto grade(const std::string &name) const -> std::string; - [[nodiscard]] auto - get_title(const std::string &name) const -> std::string; + [[nodiscard]] static auto + get_title(const std::string &name) -> std::string; [[nodiscard]] auto to_string(const std::string &infile_path) const -> std::string; From e79f931ca62bc708adb77d09ca1ba08b2ae1bfd1 Mon Sep 17 00:00:00 2001 From: Andrew D Smith Date: Mon, 31 Aug 2026 20:38:09 -0700 Subject: [PATCH 14/29] src/adapter_set.cpp: iterating using itr = next(itr) for now when cleaning lines from config file --- src/adapter_set.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/adapter_set.cpp b/src/adapter_set.cpp index bf94c70b..20b44a8f 100644 --- a/src/adapter_set.cpp +++ b/src/adapter_set.cpp @@ -39,7 +39,8 @@ load_adapters(const std::string &filename) { // ADS: need to make sure this can't fail line.remove_suffix(std::size(line) - to_keep_suffix - 1); std::string cleaned_line; - for (auto itr = std::cbegin(line); itr != std::cend(line); ++itr) + for (auto itr = std::cbegin(line); itr != std::cend(line); + itr = std::next(itr)) if (!std::isblank(*itr) || (std::next(itr) != std::cend(line) && *itr != *std::next(itr))) cleaned_line += *itr; From 0f5e4950cf7c0a924b730894df129807bf78475b Mon Sep 17 00:00:00 2001 From: Andrew D Smith Date: Mon, 31 Aug 2026 20:39:13 -0700 Subject: [PATCH 15/29] src/html.cpp: headers and nolint on optin.cplusplus.UninitObj --- src/html.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/html.cpp b/src/html.cpp index 6c699219..6a116300 100644 --- a/src/html.cpp +++ b/src/html.cpp @@ -23,12 +23,13 @@ #include #include #include -#include +#include // for tile_processor::tiles_centered_t #include #include #include #include #include +#include // for std::get probably in fmt #include [[nodiscard]] auto @@ -368,7 +369,7 @@ basic_stats_html(const file_info &info, const std::uint64_t n_reads, html_module_fmt, grade, label, title, grade, fmt::format(table_fmt, fmt::arg("filename_stem", info.name), fmt::arg("file_type", info.description), - fmt::arg("encoding", to_string(info.encoding)), + fmt::arg("encoding", encoding_to_string(info.encoding)), fmt::arg("n_reads", n_reads), fmt::arg("lengths_label", lengths_label), fmt::arg("mean_length", as_frac(total_nucs, n_reads)), @@ -378,8 +379,8 @@ basic_stats_html(const file_info &info, const std::uint64_t n_reads, [[nodiscard]] auto tile_html(const tile_processor::tiles_centered_t ¢ered, - const std::vector &groups, - const file_grades &grades) -> std::string { + const std::vector &groups, const file_grades &grades) + -> std::string { static constexpr auto label = "tile"; static constexpr auto n_quants = 20.0; // ADS: ??? (-10: red, 0: light blue, +10: dark blue) @@ -438,8 +439,8 @@ yaxis: {{title: "tile", type: "category"}}, } [[nodiscard]] auto -kmer_html(const std::vector &results, - const file_grades &grades) -> std::string { +kmer_html(const std::vector &results, const file_grades &grades) + -> std::string { static constexpr auto label = "kmer"; static constexpr auto plot_format = R"(