1 //===-- ResourceSerializator.h ----------------------------------*- C++-*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===---------------------------------------------------------------------===//
10 // This defines a visitor serializing resources to a .res stream.
12 //===---------------------------------------------------------------------===//
14 #ifndef LLVM_TOOLS_LLVMRC_RESOURCESERIALIZATOR_H
15 #define LLVM_TOOLS_LLVMRC_RESOURCESERIALIZATOR_H
17 #include "ResourceScriptStmt.h"
18 #include "ResourceVisitor.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 std::vector<std::string> NoInclude; // Folders to exclude from file search.
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 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 visitFontStmt(const FontStmt *) override;
66 Error visitLanguageStmt(const LanguageResource *) override;
67 Error visitStyleStmt(const StyleStmt *) override;
68 Error visitVersionStmt(const VersionStmt *) override;
70 // Stringtables are output at the end of .res file. We need a separate
72 Error dumpAllStringTables();
74 bool AppendNull; // Append '\0' to each existing STRINGTABLE element?
77 uint16_t LanguageInfo;
78 uint32_t Characteristics;
81 Optional<uint32_t> Style;
90 Optional<FontInfo> Font;
92 ObjectInfo() : LanguageInfo(0), Characteristics(0), VersionInfo(0) {}
95 struct StringTableInfo {
96 // Each STRINGTABLE bundle depends on ID of the bundle and language
98 using BundleKey = std::pair<uint16_t, uint16_t>;
99 // Each bundle is in fact an array of 16 strings.
101 std::array<Optional<StringRef>, 16> Data;
102 ObjectInfo DeclTimeInfo;
103 Bundle(const ObjectInfo &Info) : DeclTimeInfo(Info) {}
105 std::map<BundleKey, Bundle> BundleData;
106 // Bundles are listed in the order of their first occurrence.
107 std::vector<BundleKey> BundleList;
111 Error handleError(Error Err, const RCResource *Res);
114 writeResource(const RCResource *Res,
115 Error (ResourceFileWriter::*BodyWriter)(const RCResource *));
118 Error writeNullBody(const RCResource *);
120 // AcceleratorsResource
121 Error writeSingleAccelerator(const AcceleratorsResource::Accelerator &,
123 Error writeAcceleratorsBody(const RCResource *);
125 // CursorResource and IconResource
126 Error visitIconOrCursorResource(const RCResource *);
127 Error visitIconOrCursorGroup(const RCResource *);
128 Error visitSingleIconOrCursor(const RCResource *);
129 Error writeSingleIconOrCursorBody(const RCResource *);
130 Error writeIconOrCursorGroupBody(const RCResource *);
133 Error writeSingleDialogControl(const Control &, bool IsExtended);
134 Error writeDialogBody(const RCResource *);
137 Error writeHTMLBody(const RCResource *);
140 Error writeMenuDefinition(const std::unique_ptr<MenuDefinition> &,
142 Error writeMenuDefinitionList(const MenuDefinitionList &List);
143 Error writeMenuBody(const RCResource *);
145 // StringTableResource
146 Error visitStringTableBundle(const RCResource *);
147 Error writeStringTableBundleBody(const RCResource *);
148 Error insertStringIntoBundle(StringTableInfo::Bundle &Bundle,
149 uint16_t StringID, StringRef String);
151 // User defined resource
152 Error writeUserDefinedBody(const RCResource *);
154 // VersionInfoResource
155 Error writeVersionInfoBody(const RCResource *);
156 Error writeVersionInfoBlock(const VersionInfoBlock &);
157 Error writeVersionInfoValue(const VersionInfoValue &);
159 const WriterParams &Params;
161 // Output stream handling.
162 std::unique_ptr<raw_fd_ostream> FS;
164 uint64_t tell() const { return FS->tell(); }
166 uint64_t writeObject(const ArrayRef<uint8_t> Data);
168 template <typename T> uint64_t writeInt(const T &Value) {
169 support::detail::packed_endian_specific_integral<T, support::little,
172 return writeObject(Object);
175 template <typename T> uint64_t writeObject(const T &Value) {
176 return writeObject(ArrayRef<uint8_t>(
177 reinterpret_cast<const uint8_t *>(&Value), sizeof(T)));
180 template <typename T> void writeObjectAt(const T &Value, uint64_t Position) {
181 FS->pwrite((const char *)&Value, sizeof(T), Position);
184 Error writeCString(StringRef Str, bool WriteTerminator = true);
186 Error writeIdentifier(const IntOrString &Ident);
187 Error writeIntOrString(const IntOrString &Data);
189 void writeRCInt(RCInt);
191 Error appendFile(StringRef Filename);
193 void padStream(uint64_t Length);
195 Expected<std::unique_ptr<MemoryBuffer>> loadFile(StringRef File) const;
197 // Icon and cursor IDs are allocated starting from 1 and increasing for
198 // each icon/cursor dumped. This maintains the current ID to be allocated.
199 uint16_t IconCursorID;