228 lines · c
1//===-- ResourceSerializator.h ----------------------------------*- C++-*-===//2//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-exception6//7//===---------------------------------------------------------------------===//8//9// This defines a visitor serializing resources to a .res stream.10//11//===---------------------------------------------------------------------===//12 13#ifndef LLVM_TOOLS_LLVMRC_RESOURCESERIALIZATOR_H14#define LLVM_TOOLS_LLVMRC_RESOURCESERIALIZATOR_H15 16#include "ResourceScriptStmt.h"17#include "ResourceVisitor.h"18 19#include "llvm/ADT/StringRef.h"20#include "llvm/Support/Endian.h"21 22#include <map>23 24namespace llvm {25 26class MemoryBuffer;27 28namespace rc {29 30enum CodePage {31 CpAcp = 0, // The current used codepage. Since there's no such32 // notion in LLVM what codepage it actually means,33 // this only allows ASCII.34 CpWin1252 = 1252, // A codepage where most 8 bit values correspond to35 // unicode code points with the same value.36 CpUtf8 = 65001, // UTF-8.37};38 39struct WriterParams {40 std::vector<std::string> Include; // Additional folders to search for files.41 bool NoInclude; // Ignore the INCLUDE variable.42 StringRef InputFilePath; // The full path of the input file.43 int CodePage = CpAcp; // The codepage for interpreting characters.44};45 46class ResourceFileWriter : public Visitor {47public:48 ResourceFileWriter(const WriterParams &Params,49 std::unique_ptr<raw_fd_ostream> Stream)50 : Params(Params), FS(std::move(Stream)), IconCursorID(1) {51 assert(FS && "Output stream needs to be provided to the serializator");52 }53 54 Error visitNullResource(const RCResource *) override;55 Error visitAcceleratorsResource(const RCResource *) override;56 Error visitCursorResource(const RCResource *) override;57 Error visitDialogResource(const RCResource *) override;58 Error visitHTMLResource(const RCResource *) override;59 Error visitIconResource(const RCResource *) override;60 Error visitMenuResource(const RCResource *) override;61 Error visitMenuExResource(const RCResource *) override;62 Error visitVersionInfoResource(const RCResource *) override;63 Error visitStringTableResource(const RCResource *) override;64 Error visitUserDefinedResource(const RCResource *) override;65 66 Error visitCaptionStmt(const CaptionStmt *) override;67 Error visitCharacteristicsStmt(const CharacteristicsStmt *) override;68 Error visitClassStmt(const ClassStmt *) override;69 Error visitExStyleStmt(const ExStyleStmt *) override;70 Error visitFontStmt(const FontStmt *) override;71 Error visitLanguageStmt(const LanguageResource *) override;72 Error visitStyleStmt(const StyleStmt *) override;73 Error visitVersionStmt(const VersionStmt *) override;74 Error visitMenuStmt(const MenuStmt *) override;75 76 // Stringtables are output at the end of .res file. We need a separate77 // function to do it.78 Error dumpAllStringTables();79 80 bool AppendNull = false; // Append '\0' to each existing STRINGTABLE element?81 82 struct ObjectInfo {83 uint16_t LanguageInfo;84 uint32_t Characteristics;85 uint32_t VersionInfo;86 87 std::optional<uint32_t> Style;88 std::optional<uint32_t> ExStyle;89 StringRef Caption;90 struct FontInfo {91 uint32_t Size;92 StringRef Typeface;93 uint32_t Weight;94 bool IsItalic;95 uint32_t Charset;96 };97 std::optional<FontInfo> Font;98 IntOrString Class;99 IntOrString Menu;100 101 ObjectInfo()102 : LanguageInfo(0), Characteristics(0), VersionInfo(0),103 Class(StringRef()), Menu(StringRef()) {}104 } ObjectData;105 106 struct StringTableInfo {107 // Each STRINGTABLE bundle depends on ID of the bundle and language108 // description.109 using BundleKey = std::pair<uint16_t, uint16_t>;110 // Each bundle is in fact an array of 16 strings.111 struct Bundle {112 std::array<std::optional<std::vector<StringRef>>, 16> Data;113 ObjectInfo DeclTimeInfo;114 uint16_t MemoryFlags;115 Bundle(const ObjectInfo &Info, uint16_t Flags)116 : DeclTimeInfo(Info), MemoryFlags(Flags) {}117 };118 std::map<BundleKey, Bundle> BundleData;119 // Bundles are listed in the order of their first occurrence.120 std::vector<BundleKey> BundleList;121 } StringTableData;122 123private:124 Error handleError(Error Err, const RCResource *Res);125 126 Error127 writeResource(const RCResource *Res,128 Error (ResourceFileWriter::*BodyWriter)(const RCResource *));129 130 // NullResource131 Error writeNullBody(const RCResource *);132 133 // AcceleratorsResource134 Error writeSingleAccelerator(const AcceleratorsResource::Accelerator &,135 bool IsLastItem);136 Error writeAcceleratorsBody(const RCResource *);137 138 // BitmapResource139 Error visitBitmapResource(const RCResource *) override;140 Error writeBitmapBody(const RCResource *);141 142 // CursorResource and IconResource143 Error visitIconOrCursorResource(const RCResource *);144 Error visitIconOrCursorGroup(const RCResource *);145 Error visitSingleIconOrCursor(const RCResource *);146 Error writeSingleIconOrCursorBody(const RCResource *);147 Error writeIconOrCursorGroupBody(const RCResource *);148 149 // DialogResource150 Error writeSingleDialogControl(const Control &, bool IsExtended);151 Error writeDialogBody(const RCResource *);152 153 // HTMLResource154 Error writeHTMLBody(const RCResource *);155 156 // MenuResource157 Error writeMenuDefinition(const std::unique_ptr<MenuDefinition> &,158 uint16_t Flags);159 Error writeMenuExDefinition(const std::unique_ptr<MenuDefinition> &,160 uint16_t Flags);161 Error writeMenuDefinitionList(const MenuDefinitionList &List);162 Error writeMenuExDefinitionList(const MenuDefinitionList &List);163 Error writeMenuBody(const RCResource *);164 Error writeMenuExBody(const RCResource *);165 166 // StringTableResource167 Error visitStringTableBundle(const RCResource *);168 Error writeStringTableBundleBody(const RCResource *);169 Error insertStringIntoBundle(StringTableInfo::Bundle &Bundle,170 uint16_t StringID,171 const std::vector<StringRef> &String);172 173 // User defined resource174 Error writeUserDefinedBody(const RCResource *);175 176 // VersionInfoResource177 Error writeVersionInfoBody(const RCResource *);178 Error writeVersionInfoBlock(const VersionInfoBlock &);179 Error writeVersionInfoValue(const VersionInfoValue &);180 181 const WriterParams &Params;182 183 // Output stream handling.184 std::unique_ptr<raw_fd_ostream> FS;185 186 uint64_t tell() const { return FS->tell(); }187 188 uint64_t writeObject(const ArrayRef<uint8_t> Data);189 190 template <typename T> uint64_t writeInt(const T &Value) {191 support::detail::packed_endian_specific_integral<192 T, llvm::endianness::little, support::unaligned>193 Object(Value);194 return writeObject(Object);195 }196 197 template <typename T> uint64_t writeObject(const T &Value) {198 return writeObject(ArrayRef<uint8_t>(199 reinterpret_cast<const uint8_t *>(&Value), sizeof(T)));200 }201 202 template <typename T> void writeObjectAt(const T &Value, uint64_t Position) {203 FS->pwrite((const char *)&Value, sizeof(T), Position);204 }205 206 Error writeCString(StringRef Str, bool WriteTerminator = true);207 208 Error writeIdentifier(const IntOrString &Ident);209 Error writeIntOrString(const IntOrString &Data);210 211 void writeRCInt(RCInt);212 213 Error appendFile(StringRef Filename);214 215 void padStream(uint64_t Length);216 217 Expected<std::unique_ptr<MemoryBuffer>> loadFile(StringRef File) const;218 219 // Icon and cursor IDs are allocated starting from 1 and increasing for220 // each icon/cursor dumped. This maintains the current ID to be allocated.221 uint16_t IconCursorID;222};223 224} // namespace rc225} // namespace llvm226 227#endif228