Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions src/issues.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,6 @@ struct issue {
bool has_resolution; // 'true' if 'text' contains a proposed resolution
};

struct order_by_issue_number {
bool operator()(issue const & x, issue const & y) const noexcept { return x.num < y.num; }
bool operator()(issue const & x, int y) const noexcept { return x.num < y; }
bool operator()(int x, issue const & y) const noexcept { return x < y.num; }
};

auto parse_issue_from_file(std::string file_contents, std::string const & filename, lwg::metadata & meta) -> issue;
// Seems appropriate constructor behavior.
//
Expand Down
9 changes: 4 additions & 5 deletions src/list_issues.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ auto read_file_into_string(fs::path const & filename) -> std::string {

auto is_issue_xml_file(fs::directory_entry const & e) {
if (e.is_regular_file()) {
fs::path f = e.path().filename();
return f.string().starts_with("issue") && f.extension() == ".xml";
auto f = e.path().filename().string();
return f.starts_with("issue") && f.ends_with(".xml");
}
return false;
}
Expand All @@ -82,9 +82,8 @@ void filter_issues(fs::path const & issues_path, lwg::metadata & meta, std::func
}
}
// Write the sorted issue numbers to stdout.
std::sort(nums.begin(), nums.end());
for (auto num : nums)
std::cout << num << '\n';
std::ranges::sort(nums);
std::ranges::copy(nums, std::ostream_iterator<int>(std::cout, "\n"));
}

// ============================================================================================================
Expand Down
93 changes: 42 additions & 51 deletions src/lists.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ auto read_file_into_string(fs::path const & filename) -> std::string {

auto is_issue_xml_file(fs::directory_entry const & e) {
if (e.is_regular_file()) {
fs::path f = e.path().filename();
return f.string().starts_with("issue") && f.extension() == ".xml";
auto f = e.path().filename().string();
return f.starts_with("issue") && f.ends_with(".xml");
}
return false;
}
Expand All @@ -95,7 +95,7 @@ auto read_issues(fs::path const & issues_path, lwg::metadata & meta) -> std::vec
}


auto read_issues_from_toc(std::string const & s) -> std::vector<std::tuple<int, std::string> > {
auto read_issues_from_toc(std::string const & s) -> std::vector<std::tuple<int, std::string>> {
// parse all issues from the specified stream, 'is'.
// Throws 'runtime_error' if *any* parse step fails
//
Expand Down Expand Up @@ -126,7 +126,7 @@ auto read_issues_from_toc(std::string const & s) -> std::vector<std::tuple<int,
};

// Read all issues in table
std::vector<std::tuple<int, std::string> > issues;
std::vector<std::tuple<int, std::string>> issues;
for(;;) {
i = s.find("<tr>", i+4);
if (i == std::string::npos) {
Expand Down Expand Up @@ -231,8 +231,7 @@ std::string paper_title_attr(std::string paper_number, lwg::metadata& meta) {
}

void format_issue_as_html(lwg::issue & is,
std::vector<lwg::issue>::iterator first_issue,
std::vector<lwg::issue>::iterator last_issue,
std::span<lwg::issue> issues,
lwg::metadata & meta) {

auto& section_db = meta.section_db;
Expand Down Expand Up @@ -289,7 +288,6 @@ void format_issue_as_html(lwg::issue & is,
return std::isalpha(c) || c == '/' || c == '!';
};


// Reformat the issue text for the specified 'is' as valid HTML, replacing all the issue-list
// specific XML markup as appropriate:
// tag replacement
Expand All @@ -310,7 +308,7 @@ void format_issue_as_html(lwg::issue & is,
// (unknown) section is discovered, it will be inserted into the supplied
// section index, 'section_db'.
//
// The behavior is undefined unless the issues in the supplied vector range are sorted by issue-number.
// The behavior is undefined unless the issues in the supplied span are sorted by issue-number.
//
// Essentially, this function is a tiny xml-parser driven by a stack of open tags, that pops as tags
// are closed.
Expand Down Expand Up @@ -411,8 +409,8 @@ void format_issue_as_html(lwg::issue & is,
}
}

auto n = std::lower_bound(first_issue, last_issue, num, lwg::order_by_issue_number{});
if (n == last_issue or n->num != num) {
auto n = std::ranges::lower_bound(issues, num, {}, &lwg::issue::num);
if (n == issues.end() or n->num != num) {
fail("Could not find issue " + r + " for <iref>", context);
}

Expand Down Expand Up @@ -489,17 +487,17 @@ void format_issue_as_html(lwg::issue & is,
}


void prepare_issues(std::vector<lwg::issue> & issues, lwg::metadata & meta) {
void prepare_issues(std::span<lwg::issue> issues, lwg::metadata & meta) {
// Initially sort the issues by issue number, so each issue can be correctly 'format'ted
sort(issues.begin(), issues.end(), lwg::order_by_issue_number{});
std::ranges::sort(issues, {}, &lwg::issue::num);

// Then we format the issues, which should be the last time we need to touch the issues themselves
// We may turn this into a two-stage process, analysing duplicates and then applying the links
// This will allow us to better express constness when the issues are used purely for reference.
// Currently, the 'format' function takes a reference-to-non-const-vector-of-issues purely to
// Currently, the 'format' function takes a span of non-const-issues purely to
// mark up information related to duplicates, so processing duplicates in a separate pass may
// clarify the code.
for (auto & i : issues) { format_issue_as_html(i, issues.begin(), issues.end(), meta); }
for (auto & i : issues) { format_issue_as_html(i, issues, meta); }

// Issues will be routinely re-sorted in later code, but contents should be fixed after formatting.
// This suggests we may want to be storing some kind of issue handle in the functions that keep
Expand All @@ -509,17 +507,16 @@ void prepare_issues(std::vector<lwg::issue> & issues, lwg::metadata & meta) {

// ============================================================================================================

auto prepare_issues_for_diff_report(std::vector<lwg::issue> const & issues) -> std::vector<std::tuple<int, std::string> > {
std::vector<std::tuple<int, std::string> > result;
std::transform( issues.begin(), issues.end(), back_inserter(result),
#if 1
[](lwg::issue const & iss) { return std::make_tuple(iss.num, iss.stat); }
auto prepare_issues_for_diff_report(std::vector<lwg::issue> const & issues) -> std::vector<std::tuple<int, std::string>> {
auto make_tuple = [](lwg::issue const & iss) { return std::make_tuple(iss.num, iss.stat); };
#ifdef __cpp_lib_ranges_to_container
return std::ranges::to<std::vector>(issues | std::views::transform(make_tuple));
#else
// This form does not work because tuple constructors are explicit
[](lwg::issue const & iss) -> std::tuple<int, std::string> { return {iss.num, iss.stat}; }
#endif
);
std::vector<std::tuple<int, std::string>> result;
result.reserve(issues.size());
std::ranges::transform(issues, back_inserter(result), make_tuple);
return result;
#endif
}

struct list_issues {
Expand All @@ -546,14 +543,14 @@ struct find_num {


struct discover_new_issues {
std::vector<std::tuple<int, std::string> > const & old_issues;
std::vector<std::tuple<int, std::string> > const & new_issues;
std::vector<std::tuple<int, std::string>> const & old_issues;
std::vector<std::tuple<int, std::string>> const & new_issues;
};


auto operator<<( std::ostream & out, discover_new_issues const & x) -> std::ostream & {
std::vector<std::tuple<int, std::string> > const & old_issues = x.old_issues;
std::vector<std::tuple<int, std::string> > const & new_issues = x.new_issues;
std::vector<std::tuple<int, std::string>> const & old_issues = x.old_issues;
std::vector<std::tuple<int, std::string>> const & new_issues = x.new_issues;

struct status_order {
// predicate for 'map'
Expand Down Expand Up @@ -591,14 +588,14 @@ auto operator<<( std::ostream & out, discover_new_issues const & x) -> std::ostr


struct discover_changed_issues {
std::vector<std::tuple<int, std::string> > const & old_issues;
std::vector<std::tuple<int, std::string> > const & new_issues;
std::vector<std::tuple<int, std::string>> const & old_issues;
std::vector<std::tuple<int, std::string>> const & new_issues;
};


auto operator << (std::ostream & out, discover_changed_issues x) -> std::ostream & {
std::vector<std::tuple<int, std::string> > const & old_issues = x.old_issues;
std::vector<std::tuple<int, std::string> > const & new_issues = x.new_issues;
std::vector<std::tuple<int, std::string>> const & old_issues = x.old_issues;
std::vector<std::tuple<int, std::string>> const & new_issues = x.new_issues;

struct status_transition_order {
using status_string = std::string;
Expand Down Expand Up @@ -639,10 +636,10 @@ auto operator << (std::ostream & out, discover_changed_issues x) -> std::ostream
}


void count_issues(std::vector<std::tuple<int, std::string> > const & issues, int & n_open, int & n_reassigned, int & n_closed) {
n_open = 0;
n_reassigned = 0;
n_closed = 0;
auto count_issues(std::span<const std::tuple<int, std::string>> issues) -> std::tuple<int, int, int> {
int n_open = 0;
int n_reassigned = 0;
int n_closed = 0;

for(auto const & elem : issues) {
if (lwg::is_assigned_to_another_group(std::get<1>(elem))) {
Expand All @@ -655,27 +652,21 @@ void count_issues(std::vector<std::tuple<int, std::string> > const & issues, int
++n_closed;
}
}
return {n_open, n_reassigned, n_closed};
}


struct write_summary {
std::vector<std::tuple<int, std::string> > const & old_issues;
std::vector<std::tuple<int, std::string> > const & new_issues;
std::vector<std::tuple<int, std::string>> const & old_issues;
std::vector<std::tuple<int, std::string>> const & new_issues;
};


auto operator << (std::ostream & out, write_summary const & x) -> std::ostream & {
std::vector<std::tuple<int, std::string> > const & old_issues = x.old_issues;
std::vector<std::tuple<int, std::string> > const & new_issues = x.new_issues;

int n_open_new = 0;
int n_open_old = 0;
int n_reassigned_new = 0;
int n_reassigned_old = 0;
int n_closed_new = 0;
int n_closed_old = 0;
count_issues(old_issues, n_open_old, n_reassigned_old, n_closed_old);
count_issues(new_issues, n_open_new, n_reassigned_new, n_closed_new);

auto [n_open_old, n_reassigned_old, n_closed_old] = count_issues(x.old_issues);
auto [n_open_new, n_reassigned_new, n_closed_new] = count_issues(x.new_issues);

auto write_change = [&out](int n_new, int n_old){
out << (n_new >= n_old ? "up by " : "down by ")
<< std::abs(n_new - n_old);
Expand Down Expand Up @@ -704,8 +695,8 @@ auto operator << (std::ostream & out, write_summary const & x) -> std::ostream &


void print_current_revisions( std::ostream & out
, std::vector<std::tuple<int, std::string> > const & old_issues
, std::vector<std::tuple<int, std::string> > const & new_issues
, std::vector<std::tuple<int, std::string>> const & old_issues
, std::vector<std::tuple<int, std::string>> const & new_issues
) {
out << "<ul>\n"
"<li><b>Summary:</b><ul>\n"
Expand Down Expand Up @@ -783,7 +774,7 @@ int main(int argc, char* argv[]) {


// issues must be sorted by number before making the mailing list documents
//sort(issues.begin(), issues.end(), order_by_issue_number{});
// std::ranges::sort(issues, {}, &lwg::issue::num);

// Collect a report on all issues that have changed status
// This will be added to the revision history of the 3 standard documents
Expand Down
6 changes: 3 additions & 3 deletions src/mailing_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

namespace {

void replace_all_irefs(std::vector<lwg::issue> const & issues, std::string & s) {
void replace_all_irefs(std::span<const lwg::issue> issues, std::string & s) {
// Replace all tagged "issues references" in string 's' with an HTML anchor-link to the live issue
// in its appropriate issue list, as determined by the issue's status.
// Format of an issue reference: <iref ref="ISS"/>
Expand Down Expand Up @@ -40,7 +40,7 @@ void replace_all_irefs(std::vector<lwg::issue> const & issues, std::string & s)
throw std::runtime_error{"bad number in iref"};
}

auto n = std::lower_bound(issues.begin(), issues.end(), num, lwg::order_by_issue_number{});
auto n = std::ranges::lower_bound(issues, num, {}, &lwg::issue::num);
if (n == issues.end() || n->num != num) {
std::ostringstream er;
er << "couldn't find number " << num << " in iref";
Expand Down Expand Up @@ -153,7 +153,7 @@ auto mailing_info::get_revision() const -> std::string {
}


auto mailing_info::get_revisions(std::vector<issue> const & issues, std::string const & diff_report) const -> std::string {
auto mailing_info::get_revisions(std::span<const issue> issues, std::string const & diff_report) const -> std::string {
auto i = m_data.find("<revision_history>");
if (i == std::string::npos) {
throw std::runtime_error{"Unable to find <revision_history> in lwg-issues.xml"};
Expand Down
4 changes: 2 additions & 2 deletions src/mailing_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#include <iosfwd>
#include <string>
#include <vector>
#include <span>

namespace lwg
{
Expand All @@ -17,7 +17,7 @@ struct mailing_info {
auto get_intro(std::string doc) const -> std::string;
auto get_maintainer() const -> std::string;
auto get_revision() const -> std::string;
auto get_revisions(std::vector<issue> const & issues, std::string const & diff_report) const -> std::string;
auto get_revisions(std::span<const issue> issues, std::string const & diff_report) const -> std::string;
auto get_statuses() const -> std::string;
auto get_date() const -> std::string;
auto get_title() const -> std::string;
Expand Down
Loading
Loading