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 #ifdef SKSL_STANDALONE 12 13 #include "include/core/SkSpan.h" 14 #include "include/private/SkSLModifiers.h" 15 #include "include/private/SkSLSymbol.h" 16 #include "include/private/SkTHash.h" 17 #include "src/sksl/SkSLOutputStream.h" 18 #include "src/sksl/SkSLStringStream.h" 19 20 #include <set> 21 #include <unordered_map> 22 #include <vector> 23 24 namespace SkSL { 25 26 class AnyConstructor; 27 class Expression; 28 class ProgramElement; 29 class Statement; 30 class Symbol; 31 class SymbolTable; 32 33 // The file has the structure: 34 // 35 // uint16 total string length 36 // string data 37 // symboltable 38 // elements 39 class Dehydrator { 40 public: Dehydrator()41 Dehydrator() { 42 fSymbolMap.emplace_back(); 43 } 44 ~Dehydrator()45 ~Dehydrator() { 46 SkASSERT(fSymbolMap.size() == 1); 47 } 48 49 void write(const SymbolTable& symbols); 50 51 void write(const std::vector<std::unique_ptr<ProgramElement>>& elements); 52 53 void finish(OutputStream& out); 54 55 // Inserts line breaks at meaningful offsets. 56 const char* prefixAtOffset(size_t byte); 57 58 private: writeS8(int32_t i)59 void writeS8(int32_t i) { 60 SkASSERT(i >= -128 && i <= 127); 61 fBody.write8(i); 62 } 63 writeCommand(int32_t c)64 void writeCommand(int32_t c) { 65 fCommandBreaks.add(fBody.bytesWritten()); 66 fBody.write8(c); 67 } 68 writeU8(int32_t i)69 void writeU8(int32_t i) { 70 SkASSERT(i >= 0 && i <= 255); 71 fBody.write8(i); 72 } 73 writeS16(int32_t i)74 void writeS16(int32_t i) { 75 SkASSERT(i >= -32768 && i <= 32767); 76 fBody.write16(i); 77 } 78 writeU16(int32_t i)79 void writeU16(int32_t i) { 80 SkASSERT(i >= 0 && i <= 65535); 81 fBody.write16(i); 82 } 83 writeS32(int64_t i)84 void writeS32(int64_t i) { 85 SkASSERT(i >= -2147483648 && i <= 2147483647); 86 fBody.write32(i); 87 } 88 writeId(const Symbol * s)89 void writeId(const Symbol* s) { 90 if (!symbolId(s, false)) { 91 fSymbolMap.back()[s] = fNextId++; 92 } 93 this->writeU16(symbolId(s)); 94 } 95 96 uint16_t symbolId(const Symbol* s, bool required = true) { 97 for (const auto& symbols : fSymbolMap) { 98 auto found = symbols.find(s); 99 if (found != symbols.end()) { 100 return found->second; 101 } 102 } 103 SkASSERT(!required); 104 return 0; 105 } 106 107 void write(Layout l); 108 109 void write(Modifiers m); 110 111 void write(skstd::string_view s); 112 113 void write(String s); 114 115 void write(const ProgramElement& e); 116 117 void write(const Expression* e); 118 119 void write(const Statement* s); 120 121 void write(const Symbol& s); 122 123 void writeExpressionSpan(const SkSpan<const std::unique_ptr<Expression>>& span); 124 125 uint16_t fNextId = 1; 126 127 StringStream fStringBuffer; 128 129 StringStream fBody; 130 131 std::unordered_map<String, int> fStrings; 132 133 std::vector<std::unordered_map<const Symbol*, int>> fSymbolMap; 134 SkTHashSet<size_t> fStringBreaks; 135 SkTHashSet<size_t> fCommandBreaks; 136 size_t fStringBufferStart; 137 size_t fCommandStart; 138 139 friend class AutoDehydratorSymbolTable; 140 }; 141 142 } // namespace 143 144 #endif 145 146 #endif 147