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/ADT/StringRef.h"
20 #include "llvm/Support/Endian.h"
29 CpAcp
= 0, // The current used codepage. Since there's no such
30 // notion in LLVM what codepage it actually means,
31 // this only allows ASCII.
32 CpWin1252
= 1252, // A codepage where most 8 bit values correspond to
33 // unicode code points with the same value.
34 CpUtf8
= 65001, // UTF-8.
38 std::vector
<std::string
> Include
; // Additional folders to search for files.
39 bool NoInclude
; // Ignore the INCLUDE variable.
40 StringRef InputFilePath
; // The full path of the input file.
41 int CodePage
= CpAcp
; // The codepage for interpreting characters.
44 class ResourceFileWriter
: public Visitor
{
46 ResourceFileWriter(const WriterParams
&Params
,
47 std::unique_ptr
<raw_fd_ostream
> Stream
)
48 : Params(Params
), FS(std::move(Stream
)), IconCursorID(1) {
49 assert(FS
&& "Output stream needs to be provided to the serializator");
52 Error
visitNullResource(const RCResource
*) override
;
53 Error
visitAcceleratorsResource(const RCResource
*) override
;
54 Error
visitCursorResource(const RCResource
*) override
;
55 Error
visitDialogResource(const RCResource
*) override
;
56 Error
visitHTMLResource(const RCResource
*) override
;
57 Error
visitIconResource(const RCResource
*) override
;
58 Error
visitMenuResource(const RCResource
*) override
;
59 Error
visitMenuExResource(const RCResource
*) override
;
60 Error
visitVersionInfoResource(const RCResource
*) override
;
61 Error
visitStringTableResource(const RCResource
*) override
;
62 Error
visitUserDefinedResource(const RCResource
*) override
;
64 Error
visitCaptionStmt(const CaptionStmt
*) override
;
65 Error
visitCharacteristicsStmt(const CharacteristicsStmt
*) override
;
66 Error
visitClassStmt(const ClassStmt
*) override
;
67 Error
visitExStyleStmt(const ExStyleStmt
*) override
;
68 Error
visitFontStmt(const FontStmt
*) override
;
69 Error
visitLanguageStmt(const LanguageResource
*) override
;
70 Error
visitStyleStmt(const StyleStmt
*) override
;
71 Error
visitVersionStmt(const VersionStmt
*) override
;
72 Error
visitMenuStmt(const MenuStmt
*) override
;
74 // Stringtables are output at the end of .res file. We need a separate
76 Error
dumpAllStringTables();
78 bool AppendNull
= false; // Append '\0' to each existing STRINGTABLE element?
81 uint16_t LanguageInfo
;
82 uint32_t Characteristics
;
85 std::optional
<uint32_t> Style
;
86 std::optional
<uint32_t> ExStyle
;
95 std::optional
<FontInfo
> Font
;
100 : LanguageInfo(0), Characteristics(0), VersionInfo(0),
101 Class(StringRef()), Menu(StringRef()) {}
104 struct StringTableInfo
{
105 // Each STRINGTABLE bundle depends on ID of the bundle and language
107 using BundleKey
= std::pair
<uint16_t, uint16_t>;
108 // Each bundle is in fact an array of 16 strings.
110 std::array
<std::optional
<std::vector
<StringRef
>>, 16> Data
;
111 ObjectInfo DeclTimeInfo
;
112 uint16_t MemoryFlags
;
113 Bundle(const ObjectInfo
&Info
, uint16_t Flags
)
114 : DeclTimeInfo(Info
), MemoryFlags(Flags
) {}
116 std::map
<BundleKey
, Bundle
> BundleData
;
117 // Bundles are listed in the order of their first occurrence.
118 std::vector
<BundleKey
> BundleList
;
122 Error
handleError(Error Err
, const RCResource
*Res
);
125 writeResource(const RCResource
*Res
,
126 Error (ResourceFileWriter::*BodyWriter
)(const RCResource
*));
129 Error
writeNullBody(const RCResource
*);
131 // AcceleratorsResource
132 Error
writeSingleAccelerator(const AcceleratorsResource::Accelerator
&,
134 Error
writeAcceleratorsBody(const RCResource
*);
137 Error
visitBitmapResource(const RCResource
*) override
;
138 Error
writeBitmapBody(const RCResource
*);
140 // CursorResource and IconResource
141 Error
visitIconOrCursorResource(const RCResource
*);
142 Error
visitIconOrCursorGroup(const RCResource
*);
143 Error
visitSingleIconOrCursor(const RCResource
*);
144 Error
writeSingleIconOrCursorBody(const RCResource
*);
145 Error
writeIconOrCursorGroupBody(const RCResource
*);
148 Error
writeSingleDialogControl(const Control
&, bool IsExtended
);
149 Error
writeDialogBody(const RCResource
*);
152 Error
writeHTMLBody(const RCResource
*);
155 Error
writeMenuDefinition(const std::unique_ptr
<MenuDefinition
> &,
157 Error
writeMenuExDefinition(const std::unique_ptr
<MenuDefinition
> &,
159 Error
writeMenuDefinitionList(const MenuDefinitionList
&List
);
160 Error
writeMenuExDefinitionList(const MenuDefinitionList
&List
);
161 Error
writeMenuBody(const RCResource
*);
162 Error
writeMenuExBody(const RCResource
*);
164 // StringTableResource
165 Error
visitStringTableBundle(const RCResource
*);
166 Error
writeStringTableBundleBody(const RCResource
*);
167 Error
insertStringIntoBundle(StringTableInfo::Bundle
&Bundle
,
169 const std::vector
<StringRef
> &String
);
171 // User defined resource
172 Error
writeUserDefinedBody(const RCResource
*);
174 // VersionInfoResource
175 Error
writeVersionInfoBody(const RCResource
*);
176 Error
writeVersionInfoBlock(const VersionInfoBlock
&);
177 Error
writeVersionInfoValue(const VersionInfoValue
&);
179 const WriterParams
&Params
;
181 // Output stream handling.
182 std::unique_ptr
<raw_fd_ostream
> FS
;
184 uint64_t tell() const { return FS
->tell(); }
186 uint64_t writeObject(const ArrayRef
<uint8_t> Data
);
188 template <typename T
> uint64_t writeInt(const T
&Value
) {
189 support::detail::packed_endian_specific_integral
<
190 T
, llvm::endianness::little
, support::unaligned
>
192 return writeObject(Object
);
195 template <typename T
> uint64_t writeObject(const T
&Value
) {
196 return writeObject(ArrayRef
<uint8_t>(
197 reinterpret_cast<const uint8_t *>(&Value
), sizeof(T
)));
200 template <typename T
> void writeObjectAt(const T
&Value
, uint64_t Position
) {
201 FS
->pwrite((const char *)&Value
, sizeof(T
), Position
);
204 Error
writeCString(StringRef Str
, bool WriteTerminator
= true);
206 Error
writeIdentifier(const IntOrString
&Ident
);
207 Error
writeIntOrString(const IntOrString
&Data
);
209 void writeRCInt(RCInt
);
211 Error
appendFile(StringRef Filename
);
213 void padStream(uint64_t Length
);
215 Expected
<std::unique_ptr
<MemoryBuffer
>> loadFile(StringRef File
) const;
217 // Icon and cursor IDs are allocated starting from 1 and increasing for
218 // each icon/cursor dumped. This maintains the current ID to be allocated.
219 uint16_t IconCursorID
;