1 //===-- ResourceSerializator.h ----------------------------------*- C++-*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===---------------------------------------------------------------------===//
9 // This defines a visitor serializing resources to a .res stream.
11 //===---------------------------------------------------------------------===//
13 #ifndef LLVM_TOOLS_LLVMRC_RESOURCESERIALIZATOR_H
14 #define LLVM_TOOLS_LLVMRC_RESOURCESERIALIZATOR_H
16 #include "ResourceScriptStmt.h"
17 #include "ResourceVisitor.h"
19 #include "llvm/Support/Endian.h"
28 CpAcp
= 0, // The current used codepage. Since there's no such
29 // notion in LLVM what codepage it actually means,
30 // this only allows ASCII.
31 CpWin1252
= 1252, // A codepage where most 8 bit values correspond to
32 // unicode code points with the same value.
33 CpUtf8
= 65001, // UTF-8.
37 std::vector
<std::string
> Include
; // Additional folders to search for files.
38 bool NoInclude
; // Ignore the INCLUDE variable.
39 StringRef InputFilePath
; // The full path of the input file.
40 int CodePage
= CpAcp
; // The codepage for interpreting characters.
43 class ResourceFileWriter
: public Visitor
{
45 ResourceFileWriter(const WriterParams
&Params
,
46 std::unique_ptr
<raw_fd_ostream
> Stream
)
47 : Params(Params
), FS(std::move(Stream
)), IconCursorID(1) {
48 assert(FS
&& "Output stream needs to be provided to the serializator");
51 Error
visitNullResource(const RCResource
*) override
;
52 Error
visitAcceleratorsResource(const RCResource
*) override
;
53 Error
visitCursorResource(const RCResource
*) override
;
54 Error
visitDialogResource(const RCResource
*) override
;
55 Error
visitHTMLResource(const RCResource
*) override
;
56 Error
visitIconResource(const RCResource
*) override
;
57 Error
visitMenuResource(const RCResource
*) override
;
58 Error
visitMenuExResource(const RCResource
*) override
;
59 Error
visitVersionInfoResource(const RCResource
*) override
;
60 Error
visitStringTableResource(const RCResource
*) override
;
61 Error
visitUserDefinedResource(const RCResource
*) override
;
63 Error
visitCaptionStmt(const CaptionStmt
*) override
;
64 Error
visitCharacteristicsStmt(const CharacteristicsStmt
*) override
;
65 Error
visitClassStmt(const ClassStmt
*) override
;
66 Error
visitExStyleStmt(const ExStyleStmt
*) override
;
67 Error
visitFontStmt(const FontStmt
*) override
;
68 Error
visitLanguageStmt(const LanguageResource
*) override
;
69 Error
visitStyleStmt(const StyleStmt
*) override
;
70 Error
visitVersionStmt(const VersionStmt
*) override
;
72 // Stringtables are output at the end of .res file. We need a separate
74 Error
dumpAllStringTables();
76 bool AppendNull
= false; // Append '\0' to each existing STRINGTABLE element?
79 uint16_t LanguageInfo
;
80 uint32_t Characteristics
;
83 std::optional
<uint32_t> Style
;
84 std::optional
<uint32_t> ExStyle
;
93 std::optional
<FontInfo
> Font
;
97 : LanguageInfo(0), Characteristics(0), VersionInfo(0),
101 struct StringTableInfo
{
102 // Each STRINGTABLE bundle depends on ID of the bundle and language
104 using BundleKey
= std::pair
<uint16_t, uint16_t>;
105 // Each bundle is in fact an array of 16 strings.
107 std::array
<std::optional
<std::vector
<StringRef
>>, 16> Data
;
108 ObjectInfo DeclTimeInfo
;
109 uint16_t MemoryFlags
;
110 Bundle(const ObjectInfo
&Info
, uint16_t Flags
)
111 : DeclTimeInfo(Info
), MemoryFlags(Flags
) {}
113 std::map
<BundleKey
, Bundle
> BundleData
;
114 // Bundles are listed in the order of their first occurrence.
115 std::vector
<BundleKey
> BundleList
;
119 Error
handleError(Error Err
, const RCResource
*Res
);
122 writeResource(const RCResource
*Res
,
123 Error (ResourceFileWriter::*BodyWriter
)(const RCResource
*));
126 Error
writeNullBody(const RCResource
*);
128 // AcceleratorsResource
129 Error
writeSingleAccelerator(const AcceleratorsResource::Accelerator
&,
131 Error
writeAcceleratorsBody(const RCResource
*);
134 Error
visitBitmapResource(const RCResource
*) override
;
135 Error
writeBitmapBody(const RCResource
*);
137 // CursorResource and IconResource
138 Error
visitIconOrCursorResource(const RCResource
*);
139 Error
visitIconOrCursorGroup(const RCResource
*);
140 Error
visitSingleIconOrCursor(const RCResource
*);
141 Error
writeSingleIconOrCursorBody(const RCResource
*);
142 Error
writeIconOrCursorGroupBody(const RCResource
*);
145 Error
writeSingleDialogControl(const Control
&, bool IsExtended
);
146 Error
writeDialogBody(const RCResource
*);
149 Error
writeHTMLBody(const RCResource
*);
152 Error
writeMenuDefinition(const std::unique_ptr
<MenuDefinition
> &,
154 Error
writeMenuExDefinition(const std::unique_ptr
<MenuDefinition
> &,
156 Error
writeMenuDefinitionList(const MenuDefinitionList
&List
);
157 Error
writeMenuExDefinitionList(const MenuDefinitionList
&List
);
158 Error
writeMenuBody(const RCResource
*);
159 Error
writeMenuExBody(const RCResource
*);
161 // StringTableResource
162 Error
visitStringTableBundle(const RCResource
*);
163 Error
writeStringTableBundleBody(const RCResource
*);
164 Error
insertStringIntoBundle(StringTableInfo::Bundle
&Bundle
,
166 const std::vector
<StringRef
> &String
);
168 // User defined resource
169 Error
writeUserDefinedBody(const RCResource
*);
171 // VersionInfoResource
172 Error
writeVersionInfoBody(const RCResource
*);
173 Error
writeVersionInfoBlock(const VersionInfoBlock
&);
174 Error
writeVersionInfoValue(const VersionInfoValue
&);
176 const WriterParams
&Params
;
178 // Output stream handling.
179 std::unique_ptr
<raw_fd_ostream
> FS
;
181 uint64_t tell() const { return FS
->tell(); }
183 uint64_t writeObject(const ArrayRef
<uint8_t> Data
);
185 template <typename T
> uint64_t writeInt(const T
&Value
) {
186 support::detail::packed_endian_specific_integral
<
187 T
, llvm::endianness::little
, support::unaligned
>
189 return writeObject(Object
);
192 template <typename T
> uint64_t writeObject(const T
&Value
) {
193 return writeObject(ArrayRef
<uint8_t>(
194 reinterpret_cast<const uint8_t *>(&Value
), sizeof(T
)));
197 template <typename T
> void writeObjectAt(const T
&Value
, uint64_t Position
) {
198 FS
->pwrite((const char *)&Value
, sizeof(T
), Position
);
201 Error
writeCString(StringRef Str
, bool WriteTerminator
= true);
203 Error
writeIdentifier(const IntOrString
&Ident
);
204 Error
writeIntOrString(const IntOrString
&Data
);
206 void writeRCInt(RCInt
);
208 Error
appendFile(StringRef Filename
);
210 void padStream(uint64_t Length
);
212 Expected
<std::unique_ptr
<MemoryBuffer
>> loadFile(StringRef File
) const;
214 // Icon and cursor IDs are allocated starting from 1 and increasing for
215 // each icon/cursor dumped. This maintains the current ID to be allocated.
216 uint16_t IconCursorID
;