1 /* 2 * Copyright 2020 Google LLC 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SKSL_DEHYDRATOR 9 #define SKSL_DEHYDRATOR 10 11 #include "include/core/SkSpan.h" 12 #include "include/private/SkSLModifiers.h" 13 #include "include/private/SkSLSymbol.h" 14 #include "include/private/SkTHash.h" 15 #include "src/sksl/SkSLOutputStream.h" 16 #include "src/sksl/SkSLStringStream.h" 17 18 #include <set> 19 #include <unordered_map> 20 #include <vector> 21 22 namespace SkSL { 23 24 class AnyConstructor; 25 class Expression; 26 struct Program; 27 class ProgramElement; 28 class Statement; 29 class Symbol; 30 class SymbolTable; 31 32 /** 33 * Converts SkSL objects into a binary file. See binary_format.md for a description of the file 34 * format. 35 */ 36 class Dehydrator { 37 public: Dehydrator()38 Dehydrator() { 39 fSymbolMap.emplace_back(); 40 } 41 ~Dehydrator()42 ~Dehydrator() { 43 SkASSERT(fSymbolMap.size() == 1); 44 } 45 46 void write(const Program& program); 47 48 void write(const SymbolTable& symbols); 49 50 void write(const std::vector<std::unique_ptr<ProgramElement>>& elements); 51 52 void finish(OutputStream& out); 53 54 // Inserts line breaks at meaningful offsets. 55 const char* prefixAtOffset(size_t byte); 56 57 private: writeS8(int32_t i)58 void writeS8(int32_t i) { 59 SkASSERT(i >= -128 && i <= 127); 60 fBody.write8(i); 61 } 62 writeCommand(int32_t c)63 void writeCommand(int32_t c) { 64 fCommandBreaks.add(fBody.bytesWritten()); 65 fBody.write8(c); 66 } 67 writeU8(int32_t i)68 void writeU8(int32_t i) { 69 SkASSERT(i >= 0 && i <= 255); 70 fBody.write8(i); 71 } 72 writeS16(int32_t i)73 void writeS16(int32_t i) { 74 SkASSERT(i >= -32768 && i <= 32767); 75 fBody.write16(i); 76 } 77 writeU16(int32_t i)78 void writeU16(int32_t i) { 79 SkASSERT(i >= 0 && i <= 65535); 80 fBody.write16(i); 81 } 82 writeS32(int64_t i)83 void writeS32(int64_t i) { 84 SkASSERT(i >= -2147483648LL && i <= 2147483647); 85 fBody.write32(i); 86 } 87 writeU32(int64_t i)88 void writeU32(int64_t i) { 89 SkASSERT(i >= 0 && i <= 4294967295); 90 fBody.write32(i); 91 } 92 allocSymbolId(const Symbol * s)93 void allocSymbolId(const Symbol* s) { 94 SkASSERT(!symbolId(s)); 95 fSymbolMap.back()[s] = fNextId++; 96 } 97 98 void writeId(const Symbol* s); 99 symbolId(const Symbol * s)100 uint16_t symbolId(const Symbol* s) { 101 for (const auto& symbols : fSymbolMap) { 102 auto found = symbols.find(s); 103 if (found != symbols.end()) { 104 return found->second; 105 } 106 } 107 return 0; 108 } 109 110 void write(Layout l); 111 112 void write(Modifiers m); 113 114 void write(std::string_view s); 115 116 void write(std::string s); 117 118 void write(const ProgramElement& e); 119 120 void write(const Expression* e); 121 122 void write(const Statement* s); 123 124 void write(const Symbol& s); 125 126 void writeExpressionSpan(const SkSpan<const std::unique_ptr<Expression>>& span); 127 128 uint16_t fNextId = 1; 129 130 StringStream fStringBuffer; 131 132 StringStream fBody; 133 134 std::unordered_map<std::string, int> fStrings; 135 136 std::vector<std::unordered_map<const Symbol*, int>> fSymbolMap; 137 SkTHashSet<size_t> fStringBreaks; 138 SkTHashSet<size_t> fCommandBreaks; 139 size_t fStringBufferStart; 140 size_t fCommandStart; 141 142 friend class AutoDehydratorSymbolTable; 143 }; 144 145 } // namespace SkSL 146 147 #endif 148