OLD | NEW |
1 #ifndef SkRecordPattern_DEFINED | 1 #ifndef SkRecordPattern_DEFINED |
2 #define SkRecordPattern_DEFINED | 2 #define SkRecordPattern_DEFINED |
3 | 3 |
4 #include "SkTLogic.h" | 4 #include "SkTLogic.h" |
5 | 5 |
6 namespace SkRecords { | 6 namespace SkRecords { |
7 | 7 |
8 // First, some matchers. These match a single command in the SkRecord, | 8 // First, some matchers. These match a single command in the SkRecord, |
9 // and may hang onto some data from it. If so, you can get the data by calling
.get(). | 9 // and may hang onto some data from it. If so, you can get the data by calling
.get(). |
10 | 10 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 template <typename A, typename B> | 78 template <typename A, typename B> |
79 struct Or { | 79 struct Or { |
80 template <typename T> | 80 template <typename T> |
81 bool operator()(T* ptr) { return A()(ptr) || B()(ptr); } | 81 bool operator()(T* ptr) { return A()(ptr) || B()(ptr); } |
82 }; | 82 }; |
83 | 83 |
84 // Matches if any of A, B or C does. Stores nothing. | 84 // Matches if any of A, B or C does. Stores nothing. |
85 template <typename A, typename B, typename C> | 85 template <typename A, typename B, typename C> |
86 struct Or3 : Or<A, Or<B, C> > {}; | 86 struct Or3 : Or<A, Or<B, C> > {}; |
87 | 87 |
88 // We'll use this to choose which implementation of Star suits each Matcher. | 88 // Star is a special matcher that greedily matches Matcher 0 or more times. Sto
res nothing. |
89 SK_CREATE_TYPE_DETECTOR(type); | 89 template <typename Matcher> |
90 | 90 struct Star { |
91 // Star is a special matcher that matches Matcher 0 or more times _greedily_ in
the SkRecord. | |
92 // This version stores nothing. It's enabled when Matcher stores nothing. | |
93 template <typename Matcher, typename = void> | |
94 class Star { | |
95 public: | |
96 void reset() {} | |
97 | |
98 template <typename T> | 91 template <typename T> |
99 bool operator()(T* ptr) { return Matcher()(ptr); } | 92 bool operator()(T* ptr) { return Matcher()(ptr); } |
100 }; | 93 }; |
101 | 94 |
102 // This version stores a list of matches. It's enabled if Matcher stores someth
ing. | |
103 template <typename Matcher> | |
104 class Star<Matcher, SK_WHEN(HasType_type<Matcher>, void)> { | |
105 public: | |
106 typedef SkTDArray<typename Matcher::type*> type; | |
107 type* get() { return &fMatches; } | |
108 | |
109 void reset() { fMatches.rewind(); } | |
110 | |
111 template <typename T> | |
112 bool operator()(T* ptr) { | |
113 Matcher matcher; | |
114 if (matcher(ptr)) { | |
115 fMatches.push(matcher.get()); | |
116 return true; | |
117 } | |
118 return false; | |
119 } | |
120 | |
121 private: | |
122 type fMatches; | |
123 }; | |
124 | |
125 | |
126 // Cons builds a list of Matchers. | 95 // Cons builds a list of Matchers. |
127 // It first matches Matcher (something from above), then Pattern (another Cons o
r Nil). | 96 // It first matches Matcher (something from above), then Pattern (another Cons o
r Nil). |
128 // | 97 // |
129 // This is the main entry point to pattern matching, and so provides a couple of
extra API bits: | 98 // This is the main entry point to pattern matching, and so provides a couple of
extra API bits: |
130 // - search scans through the record to look for matches; | 99 // - search scans through the record to look for matches; |
131 // - first, second, and third return the data stored by their respective matche
rs in the pattern. | 100 // - first, second, and third return the data stored by their respective matche
rs in the pattern. |
132 // | 101 // |
133 // These Cons build lists analogously to Lisp's "cons". See Pattern# for the "l
ist" equivalent. | 102 // These Cons build lists analogously to Lisp's "cons". See Pattern# for the "l
ist" equivalent. |
134 template <typename Matcher, typename Pattern> | 103 template <typename Matcher, typename Pattern> |
135 class Cons { | 104 class Cons { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 if (record->mutate<bool>(i, fHead)) { | 137 if (record->mutate<bool>(i, fHead)) { |
169 return i+1; | 138 return i+1; |
170 } | 139 } |
171 } | 140 } |
172 return 0; | 141 return 0; |
173 } | 142 } |
174 | 143 |
175 // If head is a Star, walk i until it doesn't match. | 144 // If head is a Star, walk i until it doesn't match. |
176 template <typename T> | 145 template <typename T> |
177 unsigned matchHead(Star<T>*, SkRecord* record, unsigned i) { | 146 unsigned matchHead(Star<T>*, SkRecord* record, unsigned i) { |
178 fHead.reset(); | |
179 while (i < record->count()) { | 147 while (i < record->count()) { |
180 if (!record->mutate<bool>(i, fHead)) { | 148 if (!record->mutate<bool>(i, fHead)) { |
181 return i; | 149 return i; |
182 } | 150 } |
183 i++; | 151 i++; |
184 } | 152 } |
185 return 0; | 153 return 0; |
186 } | 154 } |
187 | 155 |
188 Matcher fHead; | 156 Matcher fHead; |
(...skipping 17 matching lines...) Expand all Loading... |
206 | 174 |
207 template <typename A, typename B> | 175 template <typename A, typename B> |
208 struct Pattern2 : Cons<A, Pattern1<B> > {}; | 176 struct Pattern2 : Cons<A, Pattern1<B> > {}; |
209 | 177 |
210 template <typename A, typename B, typename C> | 178 template <typename A, typename B, typename C> |
211 struct Pattern3 : Cons<A, Pattern2<B, C> > {}; | 179 struct Pattern3 : Cons<A, Pattern2<B, C> > {}; |
212 | 180 |
213 } // namespace SkRecords | 181 } // namespace SkRecords |
214 | 182 |
215 #endif//SkRecordPattern_DEFINED | 183 #endif//SkRecordPattern_DEFINED |
OLD | NEW |