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 std::vector
<std::string
> NoInclude
; // Folders to exclude from file search.
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
visitVersionInfoResource(const RCResource
*) override
;
59 Error
visitStringTableResource(const RCResource
*) override
;
60 Error
visitUserDefinedResource(const RCResource
*) override
;
62 Error
visitCaptionStmt(const CaptionStmt
*) override
;
63 Error
visitCharacteristicsStmt(const CharacteristicsStmt
*) override
;
64 Error
visitClassStmt(const ClassStmt
*) override
;
65 Error
visitExStyleStmt(const ExStyleStmt
*) override
;
66 Error
visitFontStmt(const FontStmt
*) override
;
67 Error
visitLanguageStmt(const LanguageResource
*) override
;
68 Error
visitStyleStmt(const StyleStmt
*) override
;
69 Error
visitVersionStmt(const VersionStmt
*) override
;
71 // Stringtables are output at the end of .res file. We need a separate
73 Error
dumpAllStringTables();
75 bool AppendNull
; // Append '\0' to each existing STRINGTABLE element?
78 uint16_t LanguageInfo
;
79 uint32_t Characteristics
;
82 Optional
<uint32_t> Style
;
83 Optional
<uint32_t> ExStyle
;
92 Optional
<FontInfo
> Font
;
96 : LanguageInfo(0), Characteristics(0), VersionInfo(0),
100 struct StringTableInfo
{
101 // Each STRINGTABLE bundle depends on ID of the bundle and language
103 using BundleKey
= std::pair
<uint16_t, uint16_t>;
104 // Each bundle is in fact an array of 16 strings.
106 std::array
<Optional
<StringRef
>, 16> Data
;
107 ObjectInfo DeclTimeInfo
;
108 uint16_t MemoryFlags
;
109 Bundle(const ObjectInfo
&Info
, uint16_t Flags
)
110 : DeclTimeInfo(Info
), MemoryFlags(Flags
) {}
112 std::map
<BundleKey
, Bundle
> BundleData
;
113 // Bundles are listed in the order of their first occurrence.
114 std::vector
<BundleKey
> BundleList
;
118 Error
handleError(Error Err
, const RCResource
*Res
);
121 writeResource(const RCResource
*Res
,
122 Error (ResourceFileWriter::*BodyWriter
)(const RCResource
*));
125 Error
writeNullBody(const RCResource
*);
127 // AcceleratorsResource
128 Error
writeSingleAccelerator(const AcceleratorsResource::Accelerator
&,
130 Error
writeAcceleratorsBody(const RCResource
*);
133 Error
visitBitmapResource(const RCResource
*) override
;
134 Error
writeBitmapBody(const RCResource
*);
136 // CursorResource and IconResource
137 Error
visitIconOrCursorResource(const RCResource
*);
138 Error
visitIconOrCursorGroup(const RCResource
*);
139 Error
visitSingleIconOrCursor(const RCResource
*);
140 Error
writeSingleIconOrCursorBody(const RCResource
*);
141 Error
writeIconOrCursorGroupBody(const RCResource
*);
144 Error
writeSingleDialogControl(const Control
&, bool IsExtended
);
145 Error
writeDialogBody(const RCResource
*);
148 Error
writeHTMLBody(const RCResource
*);
151 Error
writeMenuDefinition(const std::unique_ptr
<MenuDefinition
> &,
153 Error
writeMenuDefinitionList(const MenuDefinitionList
&List
);
154 Error
writeMenuBody(const RCResource
*);
156 // StringTableResource
157 Error
visitStringTableBundle(const RCResource
*);
158 Error
writeStringTableBundleBody(const RCResource
*);
159 Error
insertStringIntoBundle(StringTableInfo::Bundle
&Bundle
,
160 uint16_t StringID
, StringRef String
);
162 // User defined resource
163 Error
writeUserDefinedBody(const RCResource
*);
165 // VersionInfoResource
166 Error
writeVersionInfoBody(const RCResource
*);
167 Error
writeVersionInfoBlock(const VersionInfoBlock
&);
168 Error
writeVersionInfoValue(const VersionInfoValue
&);
170 const WriterParams
&Params
;
172 // Output stream handling.
173 std::unique_ptr
<raw_fd_ostream
> FS
;
175 uint64_t tell() const { return FS
->tell(); }
177 uint64_t writeObject(const ArrayRef
<uint8_t> Data
);
179 template <typename T
> uint64_t writeInt(const T
&Value
) {
180 support::detail::packed_endian_specific_integral
<T
, support::little
,
183 return writeObject(Object
);
186 template <typename T
> uint64_t writeObject(const T
&Value
) {
187 return writeObject(ArrayRef
<uint8_t>(
188 reinterpret_cast<const uint8_t *>(&Value
), sizeof(T
)));
191 template <typename T
> void writeObjectAt(const T
&Value
, uint64_t Position
) {
192 FS
->pwrite((const char *)&Value
, sizeof(T
), Position
);
195 Error
writeCString(StringRef Str
, bool WriteTerminator
= true);
197 Error
writeIdentifier(const IntOrString
&Ident
);
198 Error
writeIntOrString(const IntOrString
&Data
);
200 void writeRCInt(RCInt
);
202 Error
appendFile(StringRef Filename
);
204 void padStream(uint64_t Length
);
206 Expected
<std::unique_ptr
<MemoryBuffer
>> loadFile(StringRef File
) const;
208 // Icon and cursor IDs are allocated starting from 1 and increasing for
209 // each icon/cursor dumped. This maintains the current ID to be allocated.
210 uint16_t IconCursorID
;