diff -r fa5f493adfb5 -r 1ff88eb9555c src/html.cpp --- a/src/html.cpp Fri Feb 27 14:38:01 2026 +0100 +++ b/src/html.cpp Thu Mar 12 12:00:50 2026 +0100 @@ -27,18 +27,42 @@ #include #include #include +#include using namespace std::chrono; namespace html { static constexpr const char* weekdays[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; + struct output_reference { + FILE *file; + explicit output_reference(FILE *f) : file{f} {} + output_reference(output_reference const &) = delete; + output_reference(output_reference && other) noexcept : file(other.file) { + other.file = nullptr; + } + output_reference &operator=(output_reference const &) = delete; + output_reference &operator=(output_reference && other) noexcept { + using std::swap; + swap(other.file, file); + return *this; + } + ~output_reference() { + if (file != nullptr && file != stdout) { + fclose(file); + file = nullptr; + } + } + }; + + static output_reference output{stdout}; + static unsigned indentation; static const char *tabs = " "; static void indent(int change = 0) { indentation += change; assert(indentation <= max_indentation); - fwrite(tabs, 4, indentation, stdout); + fwrite(tabs, 4, indentation, output.file); } static std::string encode(const std::string &data) { @@ -158,8 +182,21 @@ } } +int html::set_output(std::string const &path) { + if (path.empty()) { + output = output_reference{stdout}; + return 0; + } + FILE * f = fopen(path.c_str(), "w"); + if (f == nullptr) { + return -1; + } + output = output_reference{f}; + return 0; +} + void html::styles_and_script() { - puts(R"(