12 enum class MHTMLHeaderType: std::size_t {
23 enum class MHTMLPartHeaderType: std::size_t {
30 enum class ContentType {
45 enum class LoadError {
50 enum class ParseError {
56 UnsupportedContentType,
61 enum class BuildError {
63 MissingPartContentType,
64 UnsupportedPartContentType,
68 enum class DecodeError {
69 InvalidHexASCIIEncoding
74 std::map<MHTMLPartHeaderType, std::string> header;
75 std::vector<std::string> content;
80 std::map<MHTMLHeaderType, std::string> header;
81 std::map<MHTMLPartHeaderType, std::string> bodyHeader;
83 std::map<std::string, MHTMLPart> resources;
90 std::string_view content;
93 using MHTMLHeader = std::map<MHTMLHeaderType, std::string>;
94 using MHTMLPartHeader = std::map<MHTMLPartHeaderType, std::string>;
95 using MHTMLParseResult = std::variant<MHTML, ParseError>;
96 using HeaderLineParseResult = std::variant<MHTMLHeaderLine<MHTMLHeaderType>, ParseError>;
97 using PartHeaderLineParseResult = std::variant<MHTMLHeaderLine<MHTMLPartHeaderType>, ParseError>;
98 using PartParseResult = std::variant<MHTMLPart, ParseError>;
99 using HeaderParseResult = std::variant<MHTMLHeader, ParseError>;
100 using PartHeaderParseResult = std::variant<MHTMLPartHeader, ParseError>;
101 using FileLoadResult = std::variant<std::vector<std::string>, LoadError>;
102 using PartDecodeResult = std::variant<std::vector<std::string>, DecodeError>;
103 using LineDecodeResult = std::variant<std::string, DecodeError>;
104 using CharDecodeResult = std::variant<char, DecodeError>;
105 using EncodingParseResult = std::variant<Encoding, ParseError>;
106 using ContentTypeParseResult = std::variant<ContentType, ParseError>;
107 using BuildResult = std::variant<std::string, BuildError>;
109 explicit ToHTML(
const std::filesystem::path& mhtml_file);
110 explicit ToHTML(
const std::vector<std::string>& mhtml);
114 std::string output();
117 static FileLoadResult LoadFile(
const std::filesystem::path& path);
119 static MHTMLParseResult ParseMHTML(
const std::vector<std::string>& mhtml);
120 static HeaderLineParseResult ParseHeaderLine(std::string_view line);
121 static PartParseResult ParsePart(
const std::vector<std::string>& mhtml, std::size_t& index,
const std::string_view& boundary);
122 static PartHeaderParseResult ParsePartHeader(
const std::vector<std::string>& mhtml, std::size_t& index,
const std::string_view& boundary);
123 static PartHeaderLineParseResult ParsePartHeaderLine(std::string_view line);
124 static EncodingParseResult EncodingFromString(
const std::string_view& str);
125 static ContentTypeParseResult ContentTypeFromString(
const std::string_view& str);
127 template<Encoding enc>
static PartDecodeResult DecodePart(
const std::vector<std::string>& mhtml, std::size_t& index,
const std::string_view& boundary);
128 template<Encoding enc>
static LineDecodeResult DecodeLine(std::string_view mhtml);
129 static CharDecodeResult HexToASCII(
const std::string& hex);
131 static BuildResult BuildHTML(
const MHTML& mhtml);
132 template<ContentType ct>
static BuildResult BuildSubstitute(
const MHTMLPart& part,
const std::string_view& contentType);
133 static BuildResult BuildImageSubstitute(
const MHTMLPart& part,
const std::string_view& contentType);
135 static void RemovePrefix(std::string_view& str,
const std::string_view& prefix);
136 static void RemoveSuffix(std::string_view& str,
const std::string_view& prefix);
138 static bool IsBoundary(std::string_view line,
const std::string_view& boundary);
139 static bool IsHexadecimal(std::string_view line);
141 static std::string GetEncoding(
const MHTMLPartHeader& header);
142 static std::string GetContentType(
const MHTMLPartHeader& header);
144 static constexpr std::string_view WHITE_SPACE =
" \t\n\r\f\v";
145 static constexpr std::array<std::string_view, static_cast<std::size_t>(MHTMLHeaderType::CTBoundary) + 1> meta_starts =
148 "Snapshot-Content-Location:",
156 static constexpr std::array<std::string_view, static_cast<std::size_t>(MHTMLPartHeaderType::Location) + 1> part_starts =
160 "Content-Transfer-Encoding:",
166 std::string m_output;