blob: 8d193d6a9488bc3808138f17ee657f7276eec560 [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 {
23namespace rc {
24
25class ResourceFileWriter : public Visitor {
26public:
27 ResourceFileWriter(std::unique_ptr<raw_fd_ostream> Stream)
Zachary Turnerc3ab0132017-10-06 21:25:44 +000028 : FS(std::move(Stream)), IconCursorID(1) {
Marek Sokolowski8f193432017-09-29 17:14:09 +000029 assert(FS && "Output stream needs to be provided to the serializator");
30 }
31
32 Error visitNullResource(const RCResource *) override;
Marek Sokolowski22fccd62017-09-29 19:07:44 +000033 Error visitAcceleratorsResource(const RCResource *) override;
Zachary Turnerc3ab0132017-10-06 21:25:44 +000034 Error visitCursorResource(const RCResource *) override;
Marek Sokolowski7f7745c2017-09-30 00:38:52 +000035 Error visitDialogResource(const RCResource *) override;
Marek Sokolowski8f193432017-09-29 17:14:09 +000036 Error visitHTMLResource(const RCResource *) override;
Zachary Turnerc3ab0132017-10-06 21:25:44 +000037 Error visitIconResource(const RCResource *) override;
Marek Sokolowski42f494d2017-09-29 22:25:05 +000038 Error visitMenuResource(const RCResource *) override;
Zachary Turner07bc04f2017-10-06 21:26:06 +000039 Error visitVersionInfoResource(const RCResource *) override;
Zachary Turnerda366692017-10-06 21:30:55 +000040 Error visitStringTableResource(const RCResource *) override;
Zachary Turner9d8b3582017-10-06 21:52:15 +000041 Error visitUserDefinedResource(const RCResource *) override;
Marek Sokolowski8f193432017-09-29 17:14:09 +000042
Zachary Turner420090a2017-10-06 20:51:20 +000043 Error visitCaptionStmt(const CaptionStmt *) override;
Marek Sokolowski22fccd62017-09-29 19:07:44 +000044 Error visitCharacteristicsStmt(const CharacteristicsStmt *) override;
Zachary Turner420090a2017-10-06 20:51:20 +000045 Error visitFontStmt(const FontStmt *) override;
Marek Sokolowski8f193432017-09-29 17:14:09 +000046 Error visitLanguageStmt(const LanguageResource *) override;
Zachary Turner420090a2017-10-06 20:51:20 +000047 Error visitStyleStmt(const StyleStmt *) override;
Marek Sokolowski22fccd62017-09-29 19:07:44 +000048 Error visitVersionStmt(const VersionStmt *) override;
Marek Sokolowski8f193432017-09-29 17:14:09 +000049
Zachary Turnerda366692017-10-06 21:30:55 +000050 // Stringtables are output at the end of .res file. We need a separate
51 // function to do it.
52 Error dumpAllStringTables();
53
54 bool AppendNull; // Append '\0' to each existing STRINGTABLE element?
55
Marek Sokolowski8f193432017-09-29 17:14:09 +000056 struct ObjectInfo {
57 uint16_t LanguageInfo;
Marek Sokolowski22fccd62017-09-29 19:07:44 +000058 uint32_t Characteristics;
59 uint32_t VersionInfo;
Marek Sokolowski8f193432017-09-29 17:14:09 +000060
Zachary Turner420090a2017-10-06 20:51:20 +000061 Optional<uint32_t> Style;
62 StringRef Caption;
63 struct FontInfo {
64 uint32_t Size;
65 StringRef Typeface;
66 uint32_t Weight;
67 bool IsItalic;
68 uint32_t Charset;
69 };
70 Optional<FontInfo> Font;
71
Marek Sokolowski22fccd62017-09-29 19:07:44 +000072 ObjectInfo() : LanguageInfo(0), Characteristics(0), VersionInfo(0) {}
Marek Sokolowski8f193432017-09-29 17:14:09 +000073 } ObjectData;
74
Zachary Turnerda366692017-10-06 21:30:55 +000075 struct StringTableInfo {
76 // Each STRINGTABLE bundle depends on ID of the bundle and language
77 // description.
78 using BundleKey = std::pair<uint16_t, uint16_t>;
79 // Each bundle is in fact an array of 16 strings.
80 struct Bundle {
81 std::array<Optional<StringRef>, 16> Data;
82 ObjectInfo DeclTimeInfo;
83 Bundle(const ObjectInfo &Info) : DeclTimeInfo(Info) {}
84 };
85 std::map<BundleKey, Bundle> BundleData;
86 // Bundles are listed in the order of their first occurence.
87 std::vector<BundleKey> BundleList;
88 } StringTableData;
89
Marek Sokolowski8f193432017-09-29 17:14:09 +000090private:
Zachary Turner514b7102017-10-09 18:50:29 +000091 Error handleError(Error Err, const RCResource *Res);
Marek Sokolowski8f193432017-09-29 17:14:09 +000092
93 Error
94 writeResource(const RCResource *Res,
95 Error (ResourceFileWriter::*BodyWriter)(const RCResource *));
96
Marek Sokolowski22fccd62017-09-29 19:07:44 +000097 // NullResource
Marek Sokolowski8f193432017-09-29 17:14:09 +000098 Error writeNullBody(const RCResource *);
Marek Sokolowski22fccd62017-09-29 19:07:44 +000099
100 // AcceleratorsResource
101 Error writeSingleAccelerator(const AcceleratorsResource::Accelerator &,
102 bool IsLastItem);
103 Error writeAcceleratorsBody(const RCResource *);
104
Zachary Turnerc3ab0132017-10-06 21:25:44 +0000105 // CursorResource and IconResource
106 Error visitIconOrCursorResource(const RCResource *);
107 Error visitIconOrCursorGroup(const RCResource *);
108 Error visitSingleIconOrCursor(const RCResource *);
109 Error writeSingleIconOrCursorBody(const RCResource *);
110 Error writeIconOrCursorGroupBody(const RCResource *);
111
Marek Sokolowski7f7745c2017-09-30 00:38:52 +0000112 // DialogResource
113 Error writeSingleDialogControl(const Control &, bool IsExtended);
114 Error writeDialogBody(const RCResource *);
115
Marek Sokolowski22fccd62017-09-29 19:07:44 +0000116 // HTMLResource
Marek Sokolowski8f193432017-09-29 17:14:09 +0000117 Error writeHTMLBody(const RCResource *);
118
Marek Sokolowski42f494d2017-09-29 22:25:05 +0000119 // MenuResource
120 Error writeMenuDefinition(const std::unique_ptr<MenuDefinition> &,
121 uint16_t Flags);
122 Error writeMenuDefinitionList(const MenuDefinitionList &List);
123 Error writeMenuBody(const RCResource *);
124
Zachary Turnerda366692017-10-06 21:30:55 +0000125 // StringTableResource
126 Error visitStringTableBundle(const RCResource *);
127 Error writeStringTableBundleBody(const RCResource *);
128 Error insertStringIntoBundle(StringTableInfo::Bundle &Bundle,
129 uint16_t StringID, StringRef String);
130
Zachary Turner9d8b3582017-10-06 21:52:15 +0000131 // User defined resource
132 Error writeUserDefinedBody(const RCResource *);
133
Zachary Turner07bc04f2017-10-06 21:26:06 +0000134 // VersionInfoResource
135 Error writeVersionInfoBody(const RCResource *);
136 Error writeVersionInfoBlock(const VersionInfoBlock &);
137 Error writeVersionInfoValue(const VersionInfoValue &);
138
Marek Sokolowski8f193432017-09-29 17:14:09 +0000139 // Output stream handling.
140 std::unique_ptr<raw_fd_ostream> FS;
141
142 uint64_t tell() const { return FS->tell(); }
143
144 uint64_t writeObject(const ArrayRef<uint8_t> Data);
145
146 template <typename T> uint64_t writeInt(const T &Value) {
147 support::detail::packed_endian_specific_integral<T, support::little,
148 support::unaligned>
149 Object(Value);
150 return writeObject(Object);
151 }
152
153 template <typename T> uint64_t writeObject(const T &Value) {
154 return writeObject(ArrayRef<uint8_t>(
155 reinterpret_cast<const uint8_t *>(&Value), sizeof(T)));
156 }
157
158 template <typename T> void writeObjectAt(const T &Value, uint64_t Position) {
159 FS->pwrite((const char *)&Value, sizeof(T), Position);
160 }
161
162 Error writeCString(StringRef Str, bool WriteTerminator = true);
163
164 Error writeIdentifier(const IntOrString &Ident);
165 Error writeIntOrString(const IntOrString &Data);
166
Zachary Turner07bc04f2017-10-06 21:26:06 +0000167 void writeRCInt(RCInt);
168
Marek Sokolowski8f193432017-09-29 17:14:09 +0000169 Error appendFile(StringRef Filename);
170
171 void padStream(uint64_t Length);
Zachary Turnerc3ab0132017-10-06 21:25:44 +0000172
173 // Icon and cursor IDs are allocated starting from 1 and increasing for
174 // each icon/cursor dumped. This maintains the current ID to be allocated.
175 uint16_t IconCursorID;
Marek Sokolowski8f193432017-09-29 17:14:09 +0000176};
177
178} // namespace rc
179} // namespace llvm
180
181#endif