• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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