libdcp
verify_report.h
1 /*
2  Copyright (C) 2022 Carl Hetherington <cth@carlh.net>
3 
4  This file is part of DCP-o-matic.
5 
6  DCP-o-matic is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  DCP-o-matic is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
18 
19 */
20 
21 
22 #include "compose.hpp"
23 #include "file.h"
24 #include "verify.h"
25 #include <boost/filesystem.hpp>
26 #include <vector>
27 
28 
29 namespace dcp {
30 
31 
32 class Formatter
33 {
34 public:
35  Formatter(boost::filesystem::path file)
36  : _file(file, "w")
37  {}
38 
39  class Wrap
40  {
41  public:
42  Wrap() = default;
43 
44  Wrap(Formatter* formatter, std::string const& close)
45  : _formatter(formatter)
46  , _close(close)
47  {}
48 
49  Wrap(Formatter* formatter, std::string const& close, std::function<void ()> closer)
50  : _formatter(formatter)
51  , _close(close)
52  , _closer(closer)
53  {}
54 
55  Wrap(Wrap&& other)
56  {
57  std::swap(_formatter, other._formatter);
58  std::swap(_close, other._close);
59  std::swap(_closer, other._closer);
60  }
61 
62  ~Wrap()
63  {
64  if (_formatter) {
65  _formatter->file().puts(_close.c_str());
66  }
67  if (_closer) {
68  _closer();
69  }
70  }
71 
72  private:
73  Formatter* _formatter = nullptr;
74  std::string _close;
75  std::function<void ()> _closer = nullptr;
76  };
77 
78  virtual Wrap document() { return {}; }
79 
80  virtual void heading(std::string const& text) = 0;
81  virtual void subheading(std::string const& text) = 0;
82  virtual Wrap body() { return {}; }
83 
84  virtual Wrap unordered_list() = 0;
85  virtual void list_item(std::string const& text, boost::optional<std::string> type = {}) = 0;
86 
87  virtual std::function<std::string (std::string)> process_string() = 0;
88  virtual std::function<std::string (std::string)> process_filename() = 0;
89 
90  dcp::File& file() {
91  return _file;
92  }
93 
94 protected:
95  dcp::File _file;
96 };
97 
98 
99 class TextFormatter : public Formatter
100 {
101 public:
102  TextFormatter(boost::filesystem::path file)
103  : Formatter(file)
104  {}
105 
106  void heading(std::string const& text) override {
107  print(text);
108  }
109 
110  void subheading(std::string const& text) override {
111  print("");
112  print(text);
113  }
114 
115  Wrap unordered_list() override {
116  _indent++;
117  return Wrap(this, "", [this]() { _indent--; });
118  }
119 
120  void list_item(std::string const& text, boost::optional<std::string> type = {}) override {
121  LIBDCP_UNUSED(type);
122  for (int i = 0; i < _indent * 2; ++i) {
123  _file.puts(" ");
124  }
125  _file.puts("* ");
126  print(text);
127  }
128 
129  std::function<std::string (std::string)> process_string() override {
130  return [](std::string s) {
131  return s;
132  };
133  }
134 
135  std::function<std::string (std::string)> process_filename() override {
136  return [](std::string s) {
137  return s;
138  };
139  }
140 
141 private:
142  void print(std::string const& text) {
143  _file.puts(text.c_str());
144  _file.puts("\n");
145  }
146 
147  int _indent = 0;
148 };
149 
150 
151 class HTMLFormatter : public Formatter
152 {
153 public:
154  HTMLFormatter(boost::filesystem::path file)
155  : Formatter(file)
156  {}
157 
158  void heading(std::string const& text) override {
159  tagged("h1", text);
160  }
161 
162  void subheading(std::string const& text) override {
163  tagged("h2", text);
164  }
165 
166  Wrap document() override {
167  auto html = wrapped("html");
168  auto head = wrapped("head");
169  auto style = wrapped("style");
170  _file.puts("li {\n"
171  " margin: 2px;\n"
172  " padding: 2px 2px 2px 1em;\n"
173  "}\n"
174  );
175  _file.puts("li.ok {\n"
176  " background-color: #00ff00;\n"
177  "}\n"
178  "li.warning {\n"
179  " background-color: #ffa500;\n"
180  "}\n"
181  "li.error {\n"
182  " background-color: #ff0000;\n"
183  "}\n"
184  "li.bv21-error {\n"
185  " background-color: #ff6666;\n"
186  "}\n"
187  "ul {\n"
188  " list-style: none;\n"
189  "}\n"
190  );
191  return html;
192  }
193 
194  Wrap body() override {
195  return wrapped("body");
196  }
197 
198  Wrap unordered_list() override {
199  return wrapped("ul");
200  }
201 
202  void list_item(std::string const& text, boost::optional<std::string> type = {}) override {
203  if (type) {
204  _file.puts(dcp::String::compose("<li class=\"%1\">%2", *type, text).c_str());
205  } else {
206  _file.puts(dcp::String::compose("<li>%1", text).c_str());
207  }
208  }
209 
210  std::function<std::string (std::string)> process_string() override {
211  return [](std::string s) {
212  boost::replace_all(s, "<", "&lt;");
213  boost::replace_all(s, ">", "&gt;");
214  return s;
215  };
216  }
217 
218  std::function<std::string (std::string)> process_filename() override {
219  return [](std::string s) {
220  return String::compose("<code>%1</code>", s);
221  };
222  }
223 
224 private:
225  void tagged(std::string tag, std::string content) {
226  _file.puts(String::compose("<%1>%2</%3>\n", tag, content, tag).c_str());
227  };
228 
229  Wrap wrapped(std::string const& tag) {
230  _file.puts(String::compose("<%1>", tag).c_str());
231  return Wrap(this, String::compose("</%1>", tag));
232  };
233 };
234 
235 
236 extern void verify_report(dcp::VerificationResult const& result, Formatter& formatter);
237 
238 
239 }
240 
Definition: file.h:49
int puts(char const *s)
Definition: file.cc:138
Namespace for everything in libdcp.
Definition: array_data.h:50
dcp::verify() method and associated code