blob: db097e348f021f6f0d533779439bffbb2a2056f2 [file] [log] [blame]
/*
* Copyright 2020 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_DEHYDRATOR
#define SKSL_DEHYDRATOR
#include "include/core/SkTypes.h"
#include "include/private/SkTFitsIn.h"
#include "include/private/SkTHash.h"
#include "src/sksl/SkSLStringStream.h"
#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <string_view>
#include <unordered_map>
#include <utility>
#include <vector>
template <typename T> class SkSpan;
namespace SkSL {
class Expression;
class OutputStream;
class ProgramElement;
class Statement;
class Symbol;
class SymbolTable;
struct Layout;
struct Modifiers;
struct Program;
/**
* Converts SkSL objects into a binary file. See binary_format.md for a description of the file
* format.
*/
class Dehydrator {
public:
Dehydrator() {
fSymbolMap.emplace_back();
}
~Dehydrator() {
SkASSERT(fSymbolMap.size() == 1);
}
void write(const Program& program);
void write(const SymbolTable& symbols);
void write(const std::vector<std::unique_ptr<ProgramElement>>& elements);
void finish(OutputStream& out);
// Inserts line breaks at meaningful offsets.
const char* prefixAtOffset(size_t byte);
private:
void writeS8(int32_t i) {
SkASSERT(SkTFitsIn<int8_t>(i));
fBody.write8(i);
}
void writeCommand(int32_t c) {
fCommandBreaks.add(fBody.bytesWritten());
fBody.write8(c);
}
void writeU8(int32_t i) {
SkASSERT(SkTFitsIn<uint8_t>(i));
fBody.write8(i);
}
void writeS16(int32_t i) {
SkASSERT(SkTFitsIn<int16_t>(i));
fBody.write16(i);
}
void writeU16(int32_t i) {
SkASSERT(SkTFitsIn<uint16_t>(i));
fBody.write16(i);
}
void writeS32(int64_t i) {
SkASSERT(SkTFitsIn<int32_t>(i));
fBody.write32(i);
}
void writeU32(int64_t i) {
SkASSERT(SkTFitsIn<uint32_t>(i));
fBody.write32(i);
}
void allocSymbolId(const Symbol* s) {
SkASSERT(!symbolId(s));
fSymbolMap.back()[s] = fNextId++;
}
void writeId(const Symbol* s);
uint16_t symbolId(const Symbol* s) {
for (const auto& symbols : fSymbolMap) {
auto found = symbols.find(s);
if (found != symbols.end()) {
return found->second;
}
}
return 0;
}
void write(Layout l);
void write(Modifiers m);
void write(std::string_view s);
void write(std::string s);
void write(const ProgramElement& e);
void write(const Expression* e);
void write(const Statement* s);
void write(const Symbol& s);
void writeExpressionSpan(const SkSpan<const std::unique_ptr<Expression>>& span);
uint16_t fNextId = 1;
StringStream fStringBuffer;
StringStream fBody;
std::unordered_map<std::string, int> fStrings;
std::vector<std::unordered_map<const Symbol*, int>> fSymbolMap;
SkTHashSet<size_t> fStringBreaks;
SkTHashSet<size_t> fCommandBreaks;
size_t fStringBufferStart;
size_t fCommandStart;
friend class AutoDehydratorSymbolTable;
};
} // namespace SkSL
#endif