forked from OSchip/llvm-project
217 lines
7.3 KiB
C++
217 lines
7.3 KiB
C++
//===-- 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; // 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<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, 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
|