blob: dcdebbf47fd7af39f89ab8b209aab9d46e1634be [file] [log] [blame]
Marek Sokolowski8f193432017-09-29 17:14:09 +00001//===-- ResourceSerializator.h ----------------------------------*- C++-*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===---------------------------------------------------------------------===//
9//
10// This defines a visitor serializing resources to a .res stream.
11//
12//===---------------------------------------------------------------------===//
13
14#ifndef LLVM_TOOLS_LLVMRC_RESOURCESERIALIZATOR_H
15#define LLVM_TOOLS_LLVMRC_RESOURCESERIALIZATOR_H
16
17#include "ResourceScriptStmt.h"
18#include "ResourceVisitor.h"
19
20#include "llvm/Support/Endian.h"
21
22namespace llvm {
Zachary Turnerbd159d32017-11-17 01:00:35 +000023
24class MemoryBuffer;
25
Marek Sokolowski8f193432017-09-29 17:14:09 +000026namespace rc {
27
Zachary Turnerfa0ca6c2017-10-11 20:12:09 +000028struct SearchParams {
29 std::vector<std::string> Include; // Additional folders to search for files.
30 std::vector<std::string> NoInclude; // Folders to exclude from file search.
31 StringRef InputFilePath; // The full path of the input file.
32};
33
Marek Sokolowski8f193432017-09-29 17:14:09 +000034class ResourceFileWriter : public Visitor {
35public:
Zachary Turnerfa0ca6c2017-10-11 20:12:09 +000036 ResourceFileWriter(const SearchParams &Params,
37 std::unique_ptr<raw_fd_ostream> Stream)
38 : Params(Params), FS(std::move(Stream)), IconCursorID(1) {
Marek Sokolowski8f193432017-09-29 17:14:09 +000039 assert(FS && "Output stream needs to be provided to the serializator");
40 }
41
42 Error visitNullResource(const RCResource *) override;
Marek Sokolowski22fccd62017-09-29 19:07:44 +000043 Error visitAcceleratorsResource(const RCResource *) override;
Zachary Turnerc3ab0132017-10-06 21:25:44 +000044 Error visitCursorResource(const RCResource *) override;
Marek Sokolowski7f7745c2017-09-30 00:38:52 +000045 Error visitDialogResource(const RCResource *) override;
Marek Sokolowski8f193432017-09-29 17:14:09 +000046 Error visitHTMLResource(const RCResource *) override;
Zachary Turnerc3ab0132017-10-06 21:25:44 +000047 Error visitIconResource(const RCResource *) override;
Marek Sokolowski42f494d2017-09-29 22:25:05 +000048 Error visitMenuResource(const RCResource *) override;
Zachary Turner07bc04f2017-10-06 21:26:06 +000049 Error visitVersionInfoResource(const RCResource *) override;
Zachary Turnerda366692017-10-06 21:30:55 +000050 Error visitStringTableResource(const RCResource *) override;
Zachary Turner9d8b3582017-10-06 21:52:15 +000051 Error visitUserDefinedResource(const RCResource *) override;
Marek Sokolowski8f193432017-09-29 17:14:09 +000052
Zachary Turner420090a2017-10-06 20:51:20 +000053 Error visitCaptionStmt(const CaptionStmt *) override;
Marek Sokolowski22fccd62017-09-29 19:07:44 +000054 Error visitCharacteristicsStmt(const CharacteristicsStmt *) override;
Zachary Turner420090a2017-10-06 20:51:20 +000055 Error visitFontStmt(const FontStmt *) override;
Marek Sokolowski8f193432017-09-29 17:14:09 +000056 Error visitLanguageStmt(const LanguageResource *) override;
Zachary Turner420090a2017-10-06 20:51:20 +000057 Error visitStyleStmt(const StyleStmt *) override;
Marek Sokolowski22fccd62017-09-29 19:07:44 +000058 Error visitVersionStmt(const VersionStmt *) override;
Marek Sokolowski8f193432017-09-29 17:14:09 +000059
Zachary Turnerda366692017-10-06 21:30:55 +000060 // Stringtables are output at the end of .res file. We need a separate
61 // function to do it.
62 Error dumpAllStringTables();
63
64 bool AppendNull; // Append '\0' to each existing STRINGTABLE element?
65
Marek Sokolowski8f193432017-09-29 17:14:09 +000066 struct ObjectInfo {
67 uint16_t LanguageInfo;
Marek Sokolowski22fccd62017-09-29 19:07:44 +000068 uint32_t Characteristics;
69 uint32_t VersionInfo;
Marek Sokolowski8f193432017-09-29 17:14:09 +000070
Zachary Turner420090a2017-10-06 20:51:20 +000071 Optional<uint32_t> Style;
72 StringRef Caption;
73 struct FontInfo {
74 uint32_t Size;
75 StringRef Typeface;
76 uint32_t Weight;
77 bool IsItalic;
78 uint32_t Charset;
79 };
80 Optional<FontInfo> Font;
81
Marek Sokolowski22fccd62017-09-29 19:07:44 +000082 ObjectInfo() : LanguageInfo(0), Characteristics(0), VersionInfo(0) {}
Marek Sokolowski8f193432017-09-29 17:14:09 +000083 } ObjectData;
84
Zachary Turnerda366692017-10-06 21:30:55 +000085 struct StringTableInfo {
86 // Each STRINGTABLE bundle depends on ID of the bundle and language
87 // description.
88 using BundleKey = std::pair<uint16_t, uint16_t>;
89 // Each bundle is in fact an array of 16 strings.
90 struct Bundle {
91 std::array<Optional<StringRef>, 16> Data;
92 ObjectInfo DeclTimeInfo;
93 Bundle(const ObjectInfo &Info) : DeclTimeInfo(Info) {}
94 };
95 std::map<BundleKey, Bundle> BundleData;
Malcolm Parsons21e545d2018-01-24 10:33:39 +000096 // Bundles are listed in the order of their first occurrence.
Zachary Turnerda366692017-10-06 21:30:55 +000097 std::vector<BundleKey> BundleList;
98 } StringTableData;
99
Marek Sokolowski8f193432017-09-29 17:14:09 +0000100private:
Zachary Turner514b7102017-10-09 18:50:29 +0000101 Error handleError(Error Err, const RCResource *Res);
Marek Sokolowski8f193432017-09-29 17:14:09 +0000102
103 Error
104 writeResource(const RCResource *Res,
105 Error (ResourceFileWriter::*BodyWriter)(const RCResource *));
106
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000107 // NullResource
Marek Sokolowski8f193432017-09-29 17:14:09 +0000108 Error writeNullBody(const RCResource *);
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000109
110 // AcceleratorsResource
111 Error writeSingleAccelerator(const AcceleratorsResource::Accelerator &,
112 bool IsLastItem);
113 Error writeAcceleratorsBody(const RCResource *);
114
Zachary Turnerc3ab0132017-10-06 21:25:44 +0000115 // CursorResource and IconResource
116 Error visitIconOrCursorResource(const RCResource *);
117 Error visitIconOrCursorGroup(const RCResource *);
118 Error visitSingleIconOrCursor(const RCResource *);
119 Error writeSingleIconOrCursorBody(const RCResource *);
120 Error writeIconOrCursorGroupBody(const RCResource *);
121
Marek Sokolowski7f7745c2017-09-30 00:38:52 +0000122 // DialogResource
123 Error writeSingleDialogControl(const Control &, bool IsExtended);
124 Error writeDialogBody(const RCResource *);
125
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000126 // HTMLResource
Marek Sokolowski8f193432017-09-29 17:14:09 +0000127 Error writeHTMLBody(const RCResource *);
128
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000129 // MenuResource
130 Error writeMenuDefinition(const std::unique_ptr<MenuDefinition> &,
131 uint16_t Flags);
132 Error writeMenuDefinitionList(const MenuDefinitionList &List);
133 Error writeMenuBody(const RCResource *);
134
Zachary Turnerda366692017-10-06 21:30:55 +0000135 // StringTableResource
136 Error visitStringTableBundle(const RCResource *);
137 Error writeStringTableBundleBody(const RCResource *);
138 Error insertStringIntoBundle(StringTableInfo::Bundle &Bundle,
139 uint16_t StringID, StringRef String);
140
Zachary Turner9d8b3582017-10-06 21:52:15 +0000141 // User defined resource
142 Error writeUserDefinedBody(const RCResource *);
143
Zachary Turner07bc04f2017-10-06 21:26:06 +0000144 // VersionInfoResource
145 Error writeVersionInfoBody(const RCResource *);
146 Error writeVersionInfoBlock(const VersionInfoBlock &);
147 Error writeVersionInfoValue(const VersionInfoValue &);
148
Zachary Turnerfa0ca6c2017-10-11 20:12:09 +0000149 const SearchParams &Params;
150
Marek Sokolowski8f193432017-09-29 17:14:09 +0000151 // Output stream handling.
152 std::unique_ptr<raw_fd_ostream> FS;
153
154 uint64_t tell() const { return FS->tell(); }
155
156 uint64_t writeObject(const ArrayRef<uint8_t> Data);
157
158 template <typename T> uint64_t writeInt(const T &Value) {
159 support::detail::packed_endian_specific_integral<T, support::little,
160 support::unaligned>
161 Object(Value);
162 return writeObject(Object);
163 }
164
165 template <typename T> uint64_t writeObject(const T &Value) {
166 return writeObject(ArrayRef<uint8_t>(
167 reinterpret_cast<const uint8_t *>(&Value), sizeof(T)));
168 }
169
170 template <typename T> void writeObjectAt(const T &Value, uint64_t Position) {
171 FS->pwrite((const char *)&Value, sizeof(T), Position);
172 }
173
174 Error writeCString(StringRef Str, bool WriteTerminator = true);
175
176 Error writeIdentifier(const IntOrString &Ident);
177 Error writeIntOrString(const IntOrString &Data);
178
Zachary Turner07bc04f2017-10-06 21:26:06 +0000179 void writeRCInt(RCInt);
180
Marek Sokolowski8f193432017-09-29 17:14:09 +0000181 Error appendFile(StringRef Filename);
182
183 void padStream(uint64_t Length);
Zachary Turnerc3ab0132017-10-06 21:25:44 +0000184
Zachary Turnerfa0ca6c2017-10-11 20:12:09 +0000185 Expected<std::unique_ptr<MemoryBuffer>> loadFile(StringRef File) const;
186
Zachary Turnerc3ab0132017-10-06 21:25:44 +0000187 // Icon and cursor IDs are allocated starting from 1 and increasing for
188 // each icon/cursor dumped. This maintains the current ID to be allocated.
189 uint16_t IconCursorID;
Marek Sokolowski8f193432017-09-29 17:14:09 +0000190};
191
192} // namespace rc
193} // namespace llvm
194
195#endif