123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- //===-- ResourceSerializator.h ----------------------------------*- C++-*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===---------------------------------------------------------------------===//
- //
- // This defines a visitor serializing resources to a .res stream.
- //
- //===---------------------------------------------------------------------===//
- #ifndef LLVM_TOOLS_LLVMRC_RESOURCESERIALIZATOR_H
- #define LLVM_TOOLS_LLVMRC_RESOURCESERIALIZATOR_H
- #include "ResourceScriptStmt.h"
- #include "ResourceVisitor.h"
- #include "llvm/Support/Endian.h"
- namespace llvm {
- class MemoryBuffer;
- namespace rc {
- enum CodePage {
- CpAcp = 0, // The current used codepage. Since there's no such
- // notion in LLVM what codepage it actually means,
- // this only allows ASCII.
- CpWin1252 = 1252, // A codepage where most 8 bit values correspond to
- // unicode code points with the same value.
- CpUtf8 = 65001, // UTF-8.
- };
- struct WriterParams {
- std::vector<std::string> Include; // Additional folders to search for files.
- std::vector<std::string> NoInclude; // Folders to exclude from file search.
- StringRef InputFilePath; // The full path of the input file.
- int CodePage = CpAcp; // The codepage for interpreting characters.
- };
- class ResourceFileWriter : public Visitor {
- public:
- ResourceFileWriter(const WriterParams &Params,
- std::unique_ptr<raw_fd_ostream> Stream)
- : Params(Params), FS(std::move(Stream)), IconCursorID(1) {
- assert(FS && "Output stream needs to be provided to the serializator");
- }
- Error visitNullResource(const RCResource *) override;
- Error visitAcceleratorsResource(const RCResource *) override;
- Error visitCursorResource(const RCResource *) override;
- Error visitDialogResource(const RCResource *) override;
- Error visitHTMLResource(const RCResource *) override;
- Error visitIconResource(const RCResource *) override;
- Error visitMenuResource(const RCResource *) override;
- Error visitVersionInfoResource(const RCResource *) override;
- Error visitStringTableResource(const RCResource *) override;
- Error visitUserDefinedResource(const RCResource *) override;
- Error visitCaptionStmt(const CaptionStmt *) override;
- Error visitCharacteristicsStmt(const CharacteristicsStmt *) override;
- Error visitClassStmt(const ClassStmt *) override;
- Error visitExStyleStmt(const ExStyleStmt *) override;
- Error visitFontStmt(const FontStmt *) override;
- Error visitLanguageStmt(const LanguageResource *) override;
- Error visitStyleStmt(const StyleStmt *) override;
- Error visitVersionStmt(const VersionStmt *) override;
- // Stringtables are output at the end of .res file. We need a separate
- // function to do it.
- Error dumpAllStringTables();
- bool AppendNull = false; // Append '\0' to each existing STRINGTABLE element?
- struct ObjectInfo {
- uint16_t LanguageInfo;
- uint32_t Characteristics;
- uint32_t VersionInfo;
- Optional<uint32_t> Style;
- Optional<uint32_t> ExStyle;
- StringRef Caption;
- struct FontInfo {
- uint32_t Size;
- StringRef Typeface;
- uint32_t Weight;
- bool IsItalic;
- uint32_t Charset;
- };
- Optional<FontInfo> Font;
- IntOrString Class;
- ObjectInfo()
- : LanguageInfo(0), Characteristics(0), VersionInfo(0),
- Class(StringRef()) {}
- } ObjectData;
- struct StringTableInfo {
- // Each STRINGTABLE bundle depends on ID of the bundle and language
- // description.
- using BundleKey = std::pair<uint16_t, uint16_t>;
- // Each bundle is in fact an array of 16 strings.
- struct Bundle {
- std::array<Optional<std::vector<StringRef>>, 16> Data;
- ObjectInfo DeclTimeInfo;
- uint16_t MemoryFlags;
- Bundle(const ObjectInfo &Info, uint16_t Flags)
- : DeclTimeInfo(Info), MemoryFlags(Flags) {}
- };
- std::map<BundleKey, Bundle> BundleData;
- // Bundles are listed in the order of their first occurrence.
- std::vector<BundleKey> BundleList;
- } StringTableData;
- private:
- Error handleError(Error Err, const RCResource *Res);
- Error
- writeResource(const RCResource *Res,
- Error (ResourceFileWriter::*BodyWriter)(const RCResource *));
- // NullResource
- Error writeNullBody(const RCResource *);
- // AcceleratorsResource
- Error writeSingleAccelerator(const AcceleratorsResource::Accelerator &,
- bool IsLastItem);
- Error writeAcceleratorsBody(const RCResource *);
- // BitmapResource
- Error visitBitmapResource(const RCResource *) override;
- Error writeBitmapBody(const RCResource *);
- // CursorResource and IconResource
- Error visitIconOrCursorResource(const RCResource *);
- Error visitIconOrCursorGroup(const RCResource *);
- Error visitSingleIconOrCursor(const RCResource *);
- Error writeSingleIconOrCursorBody(const RCResource *);
- Error writeIconOrCursorGroupBody(const RCResource *);
- // DialogResource
- Error writeSingleDialogControl(const Control &, bool IsExtended);
- Error writeDialogBody(const RCResource *);
- // HTMLResource
- Error writeHTMLBody(const RCResource *);
- // MenuResource
- Error writeMenuDefinition(const std::unique_ptr<MenuDefinition> &,
- uint16_t Flags);
- Error writeMenuDefinitionList(const MenuDefinitionList &List);
- Error writeMenuBody(const RCResource *);
- // StringTableResource
- Error visitStringTableBundle(const RCResource *);
- Error writeStringTableBundleBody(const RCResource *);
- Error insertStringIntoBundle(StringTableInfo::Bundle &Bundle,
- uint16_t StringID,
- const std::vector<StringRef> &String);
- // User defined resource
- Error writeUserDefinedBody(const RCResource *);
- // VersionInfoResource
- Error writeVersionInfoBody(const RCResource *);
- Error writeVersionInfoBlock(const VersionInfoBlock &);
- Error writeVersionInfoValue(const VersionInfoValue &);
- const WriterParams &Params;
- // Output stream handling.
- std::unique_ptr<raw_fd_ostream> FS;
- uint64_t tell() const { return FS->tell(); }
- uint64_t writeObject(const ArrayRef<uint8_t> Data);
- template <typename T> uint64_t writeInt(const T &Value) {
- support::detail::packed_endian_specific_integral<T, support::little,
- support::unaligned>
- Object(Value);
- return writeObject(Object);
- }
- template <typename T> uint64_t writeObject(const T &Value) {
- return writeObject(ArrayRef<uint8_t>(
- reinterpret_cast<const uint8_t *>(&Value), sizeof(T)));
- }
- template <typename T> void writeObjectAt(const T &Value, uint64_t Position) {
- FS->pwrite((const char *)&Value, sizeof(T), Position);
- }
- Error writeCString(StringRef Str, bool WriteTerminator = true);
- Error writeIdentifier(const IntOrString &Ident);
- Error writeIntOrString(const IntOrString &Data);
- void writeRCInt(RCInt);
- Error appendFile(StringRef Filename);
- void padStream(uint64_t Length);
- Expected<std::unique_ptr<MemoryBuffer>> loadFile(StringRef File) const;
- // Icon and cursor IDs are allocated starting from 1 and increasing for
- // each icon/cursor dumped. This maintains the current ID to be allocated.
- uint16_t IconCursorID;
- };
- } // namespace rc
- } // namespace llvm
- #endif
|