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
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ all: pgms

pgms: $(PGMS)

bin/lists: src/date.o src/issues.o src/status.o src/sections.o src/mailing_info.o src/report_generator.o src/lists.o
bin/lists: src/date.o src/issues.o src/status.o src/sections.o src/mailing_info.o src/report_generator.o src/lists.o src/metadata.o

bin/section_data: src/section_data.o

bin/toc_diff: src/toc_diff.o

bin/list_issues: src/date.o src/issues.o src/status.o src/sections.o src/list_issues.o
bin/list_issues: src/date.o src/issues.o src/status.o src/sections.o src/list_issues.o src/metadata.o

bin/set_status: src/set_status.o src/status.o

Expand Down
27 changes: 6 additions & 21 deletions src/issues.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#endif

#include "issues.h"
#include "sections.h"
#include "metadata.h"
#include "status.h"

#include <algorithm>
Expand Down Expand Up @@ -64,26 +64,10 @@ auto make_date(std::tm const & mod) -> gregorian::date {
return gregorian::year((unsigned short)(mod.tm_year+1900)) / (mod.tm_mon+1) / mod.tm_mday;
}

struct issue_mod_time {
int id;
std::time_t t;
operator std::pair<const int, std::time_t>() const { return { id, t }; }
friend std::istream& operator>>(std::istream& in, issue_mod_time& v) { return in >> v.id >> v.t; }
};

auto git_commit_times() -> std::map<int, std::time_t>
{
using Iter = std::istream_iterator<issue_mod_time>;
std::ifstream f{"meta-data/dates"};
std::map<int, std::time_t> times{ Iter{f}, Iter{} };
return times;
}

auto report_date_file_last_modified(std::filesystem::path const & filename) -> gregorian::date {
auto report_date_file_last_modified(std::filesystem::path const & filename, lwg::metadata const& meta) -> gregorian::date {
std::time_t mtime;
int id = std::stoi(filename.filename().stem().native().substr(5));
static auto git_times = git_commit_times();
if (auto it = git_times.find(id); it != git_times.end())
if (auto it = meta.git_commit_times.find(id); it != meta.git_commit_times.end())
mtime = it->second;
else
{
Expand Down Expand Up @@ -112,7 +96,8 @@ std::string escape_special_chars(std::string s) {
} // close unnamed namespace

auto lwg::parse_issue_from_file(std::string tx, std::string const & filename,
lwg::section_map & section_db) -> issue {
lwg::metadata & meta) -> issue {
auto& section_db = meta.section_db;
struct bad_issue_file : std::runtime_error {
bad_issue_file(std::string const & filename, std::string error_message)
: runtime_error{"Error parsing issue file " + filename + ": " + error_message}
Expand Down Expand Up @@ -263,7 +248,7 @@ auto lwg::parse_issue_from_file(std::string tx, std::string const & filename,
is.date = parse_date(temp);

// Get modification date
is.mod_date = report_date_file_last_modified(filename);
is.mod_date = report_date_file_last_modified(filename, meta);
}
catch(std::exception const & ex) {
throw bad_issue_file{filename, ex.what()};
Expand Down
4 changes: 2 additions & 2 deletions src/issues.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

// solution specific headers
#include "date.h"
#include "sections.h"
#include "metadata.h"
#include "status.h"

namespace lwg
Expand Down Expand Up @@ -38,7 +38,7 @@ struct order_by_issue_number {
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::section_map & section_db) -> issue;
auto parse_issue_from_file(std::string file_contents, std::string const & filename, lwg::metadata & meta) -> issue;
// Seems appropriate constructor behavior.
//
// Note that 'section_db' is modifiable as new (unknown) sections may be inserted,
Expand Down
25 changes: 5 additions & 20 deletions src/list_issues.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ namespace fs = std::filesystem;

// solution specific headers
#include "issues.h"
#include "sections.h"
#include "metadata.h"


auto read_file_into_string(fs::path const & filename) -> std::string {
Expand All @@ -66,7 +66,7 @@ auto is_issue_xml_file(fs::directory_entry const & e) {
return false;
}

void filter_issues(fs::path const & issues_path, lwg::section_map & section_db, std::function<bool(lwg::issue const &)> predicate) {
void filter_issues(fs::path const & issues_path, lwg::metadata & meta, std::function<bool(lwg::issue const &)> predicate) {
// Open the specified directory, 'issues_path', and iterate all the '.xml' files
// it contains, parsing each such file as an LWG issue document. Collect
// the number of every issue that satisfies the 'predicate'.
Expand All @@ -75,7 +75,7 @@ void filter_issues(fs::path const & issues_path, lwg::section_map & section_db,
for (auto ent : fs::directory_iterator(issues_path)) {
if (is_issue_xml_file(ent)) {
fs::path const issue_file = ent.path();
auto const iss = parse_issue_from_file(read_file_into_string(issue_file), issue_file.string(), section_db);
auto const iss = parse_issue_from_file(read_file_into_string(issue_file), issue_file.string(), meta);
if (predicate(iss)) {
nums.push_back(iss.num);
}
Expand All @@ -97,8 +97,6 @@ void check_is_directory(fs::path const & directory) {

int main(int argc, char const* argv[]) {
try {
bool trace_on{false}; // Will pick this up from the command line later

if (argc != 2) {
std::cerr << "Must specify exactly one status\n";
return 2;
Expand All @@ -109,22 +107,9 @@ int main(int argc, char const* argv[]) {

check_is_directory(path);

lwg::section_map section_db = [&] {
// This lambda expression scopes the lifetime of an open 'fstream'
auto filename = path / "meta-data/section.data";
std::ifstream infile{filename};
if (!infile.is_open()) {
throw std::runtime_error{"Can't open section.data at " + path.string() + "meta-data"};
}

if (trace_on) {
std::cout << "Reading section-tag index from: " << filename << std::endl;
}

return lwg::read_section_db(infile);
}();
auto metadata = lwg::metadata::read_from_path(path);

filter_issues(path / "xml/", section_db, [status](lwg::issue const & iss) { return status == iss.stat; });
filter_issues(path / "xml/", metadata, [status](lwg::issue const & iss) { return status == iss.stat; });
}
catch(std::exception const & ex) {
std::cout << ex.what() << std::endl;
Expand Down
46 changes: 14 additions & 32 deletions src/lists.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ auto is_issue_xml_file(fs::directory_entry const & e) {
return false;
}

auto read_issues(fs::path const & issues_path, lwg::section_map & section_db) -> std::vector<lwg::issue> {
auto read_issues(fs::path const & issues_path, lwg::metadata & meta) -> std::vector<lwg::issue> {
// Open the specified directory, 'issues_path', and iterate all the '.xml' files
// it contains, parsing each such file as an LWG issue document. Return the set
// of issues as a vector.
Expand All @@ -87,7 +87,7 @@ auto read_issues(fs::path const & issues_path, lwg::section_map & section_db) ->
for (auto ent : fs::directory_iterator(issues_path)) {
if (is_issue_xml_file(ent)) {
fs::path const issue_file = ent.path();
issues.emplace_back(parse_issue_from_file(read_file_into_string(issue_file), issue_file.string(), section_db));
issues.emplace_back(parse_issue_from_file(read_file_into_string(issue_file), issue_file.string(), meta));
}
}

Expand Down Expand Up @@ -218,18 +218,9 @@ namespace
};
}

std::unordered_map<std::string, std::string> paper_titles = [] {
std::unordered_map<std::string, std::string> titles;
std::ifstream in{"meta-data/paper_titles.txt"};
std::string paper_number, title;
while (in >> paper_number && std::getline(in, title))
titles[paper_number] = title;
return titles;
}();

// The title of the specified paper, formatted as an HTML title="..." attribute.
std::string paper_title_attr(std::string paper_number) {
auto title = paper_titles[paper_number];
std::string paper_title_attr(std::string paper_number, lwg::metadata& meta) {
auto title = meta.paper_titles[paper_number];
if (!title.empty())
{
title = lwg::replace_reserved_char(std::move(title), '&', "&amp;");
Expand All @@ -242,8 +233,9 @@ std::string paper_title_attr(std::string paper_number) {
void format_issue_as_html(lwg::issue & is,
std::vector<lwg::issue>::iterator first_issue,
std::vector<lwg::issue>::iterator last_issue,
lwg::section_map & section_db) {
lwg::metadata & meta) {

auto& section_db = meta.section_db;
std::vector<std::string> tag_stack; // stack of open XML tags as we parse

// Used by fix_tags to report errors.
Expand Down Expand Up @@ -453,7 +445,7 @@ void format_issue_as_html(lwg::issue & is,
std::transform(paper_number.begin(), paper_number.end(), paper_number.begin(),
[] (unsigned char c) { return std::toupper(c); });

auto title = paper_title_attr(paper_number);
auto title = paper_title_attr(paper_number, meta);

j -= i - 1;
std::string r = "<a href=\"https://wg21.link/" + paper_number + "\"" + title + ">" + paper_number + "</a>";
Expand Down Expand Up @@ -497,7 +489,7 @@ void format_issue_as_html(lwg::issue & is,
}


void prepare_issues(std::vector<lwg::issue> & issues, lwg::section_map & section_db) {
void prepare_issues(std::vector<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{});

Expand All @@ -507,7 +499,7 @@ void prepare_issues(std::vector<lwg::issue> & issues, lwg::section_map & section
// Currently, the 'format' function takes a reference-to-non-const-vector-of-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(), section_db); }
for (auto & i : issues) { format_issue_as_html(i, issues.begin(), issues.end(), 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 Down Expand Up @@ -754,20 +746,10 @@ int main(int argc, char* argv[]) {
const fs::path target_path{path / "mailing"};
check_is_directory(target_path);


lwg::section_map section_db =[&path]() {
auto filename = path / "meta-data" / "section.data";
std::ifstream infile{filename};
if (!infile.is_open()) {
throw std::runtime_error{"Can't open section.data at " + path.string() + "meta-data"};
}
std::cout << "Reading section-tag index from: " << filename << std::endl;

return lwg::read_section_db(infile);
}();
auto metadata = lwg::metadata::read_from_path(path);
#if defined (DEBUG_LOGGING)
// dump the contents of the section index
for (auto const & elem : section_db ) {
for (auto const & elem : metadata.section_db ) {
std::string temp = elem.first;
temp.erase(temp.end()-1);
temp.erase(temp.begin());
Expand All @@ -793,11 +775,11 @@ int main(int argc, char* argv[]) {


std::cout << "Reading issues from: " << issues_path << std::endl;
auto issues = read_issues(issues_path, section_db);
prepare_issues(issues, section_db);
auto issues = read_issues(issues_path, metadata);
prepare_issues(issues, metadata);


lwg::report_generator generator{lwg_issues_xml, section_db};
lwg::report_generator generator{lwg_issues_xml, metadata.section_db};


// issues must be sorted by number before making the mailing list documents
Expand Down
46 changes: 46 additions & 0 deletions src/metadata.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "metadata.h"

#include <fstream>
#include <iterator>
#include <iostream>

namespace {
struct issue_mod_time {
int id;
std::time_t t;
operator std::pair<const int, std::time_t>() const { return { id, t }; }
friend std::istream& operator>>(std::istream& in, issue_mod_time& v) { return in >> v.id >> v.t; }
};

auto read_git_commit_times(std::filesystem::path const& path) -> std::map<int, std::time_t>
{
using Iter = std::istream_iterator<issue_mod_time>;
std::ifstream f{path};
std::map<int, std::time_t> times{ Iter{f}, Iter{} };
return times;
}

auto read_paper_titles(std::filesystem::path const& path) -> std::unordered_map<std::string, std::string> {
std::unordered_map<std::string, std::string> titles;
std::ifstream in{path};
std::string paper_number, title;
while (in >> paper_number && std::getline(in, title))
titles[paper_number] = title;
return titles;
}

}

auto lwg::metadata::read_from_path(std::filesystem::path const& path) -> metadata {
auto filename = path / "meta-data" / "section.data";
std::ifstream infile{filename};
if (!infile.is_open()) {
throw std::runtime_error{"Can't open section.data at " + path.string() + "meta-data"};
}
std::cout << "Reading section-tag index from: " << filename << std::endl;
return {
read_section_db(infile),
read_git_commit_times(path / "meta-data" / "dates"),
read_paper_titles(path / "meta-data" / "paper_titles.txt"),
};
}
21 changes: 21 additions & 0 deletions src/metadata.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef INCLUDE_LWG_METADATA_H
#define INCLUDE_LWG_METADATA_H
#include "sections.h"
#include <map>
#include <unordered_map>
#include <ctime>
#include <filesystem>

namespace lwg {

// Various things read from meta-data/
struct metadata {
section_map section_db;
std::map<int, std::time_t> git_commit_times;
std::unordered_map<std::string, std::string> paper_titles;

static metadata read_from_path(std::filesystem::path const& path);
};

}
#endif
Loading