diff options
author | mtklein <mtklein@chromium.org> | 2015-11-19 08:53:27 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-11-19 08:53:27 -0800 |
commit | 24e7db8b2ea663f8fe4d7bbfa1d686fd643990bb (patch) | |
tree | 9cbb16e3fc5e4ed8df7301f92bf1bafcee07dedd /src/core/SkRecordPattern.h | |
parent | 4222e19aeaf72ccfb61f83f4fe41010750161c74 (diff) |
Modernize SkRecordPattern.h
- Fold Or, Or3, Or4 into one flexible Or.
- Fold Pattern1...Pattern7 into one flexible Pattern.
- Rename Star Greedy
Still fighting with a flexible get<N>() method instead of first, second, third, etc.
BUG=skia:
Review URL: https://codereview.chromium.org/1465443002
Diffstat (limited to 'src/core/SkRecordPattern.h')
-rw-r--r-- | src/core/SkRecordPattern.h | 109 |
1 files changed, 39 insertions, 70 deletions
diff --git a/src/core/SkRecordPattern.h b/src/core/SkRecordPattern.h index d9568b360a..9493bbfaf7 100644 --- a/src/core/SkRecordPattern.h +++ b/src/core/SkRecordPattern.h @@ -80,44 +80,48 @@ struct Not { bool operator()(T* ptr) { return !Matcher()(ptr); } }; -// Matches if either of A or B does. Stores nothing. -template <typename A, typename B> +// Matches if any of First or Rest... does. Stores nothing. +template <typename First, typename... Rest> struct Or { template <typename T> - bool operator()(T* ptr) { return A()(ptr) || B()(ptr); } + bool operator()(T* ptr) { return First()(ptr) || Or<Rest...>()(ptr); } +}; +template <typename First> +struct Or<First> { + template <typename T> + bool operator()(T* ptr) { return First()(ptr); } }; -// Matches if any of A, B or C does. Stores nothing. -template <typename A, typename B, typename C> -struct Or3 : Or<A, Or<B, C> > {}; - -// Matches if any of A, B, C or D does. Stores nothing. -template <typename A, typename B, typename C, typename D> -struct Or4 : Or<A, Or<B, Or<C, D> > > {}; -// Star is a special matcher that greedily matches Matcher 0 or more times. Stores nothing. +// Greedy is a special matcher that greedily matches Matcher 0 or more times. Stores nothing. template <typename Matcher> -struct Star { +struct Greedy { template <typename T> bool operator()(T* ptr) { return Matcher()(ptr); } }; -// Cons builds a list of Matchers. -// It first matches Matcher (something from above), then Pattern (another Cons or Nil). +// Pattern matches each of its matchers in order. // // This is the main entry point to pattern matching, and so provides a couple of extra API bits: // - search scans through the record to look for matches; -// - first, second, and third return the data stored by their respective matchers in the pattern. -// -// These Cons build lists analogously to Lisp's "cons". See Pattern# for the "list" equivalent. -template <typename Matcher, typename Pattern> -class Cons { +// - first, second, third, ... return the data stored by their respective matchers in the pattern. + +template <typename... Matchers> class Pattern; + +template <> class Pattern<> { public: - // If this pattern matches the SkRecord starting at i, + // Bottoms out recursion. Just return whatever i the front decided on. + int match(SkRecord*, int i) { return i; } +}; + +template <typename First, typename... Rest> +class Pattern<First, Rest...> { +public: + // If this pattern matches the SkRecord starting from i, // return the index just past the end of the pattern, otherwise return 0. SK_ALWAYS_INLINE int match(SkRecord* record, int i) { - i = this->matchHead(&fHead, record, i); - return i == 0 ? 0 : fTail.match(record, i); + i = this->matchFirst(&fFirst, record, i); + return i > 0 ? fRest.match(record, i) : 0; } // Starting from *end, walk through the SkRecord to find the first span matching this pattern. @@ -132,31 +136,29 @@ public: return false; } - // Once either match or search has succeeded, access the stored data of the first, second, - // or third matcher in this pattern. Add as needed for longer patterns. - // T is checked statically at compile time; no casting is involved. It's just an API wart. - template <typename T> T* first() { return fHead.get(); } - template <typename T> T* second() { return fTail.fHead.get(); } - template <typename T> T* third() { return fTail.fTail.fHead.get(); } - template <typename T> T* fourth() { return fTail.fTail.fTail.fHead.get(); } + // TODO: some sort of smart get<i>() + template <typename T> T* first() { return fFirst.get(); } + template <typename T> T* second() { return fRest.template first<T>(); } + template <typename T> T* third() { return fRest.template second<T>(); } + template <typename T> T* fourth() { return fRest.template third<T>(); } private: - // If head isn't a Star, try to match at i once. + // If first isn't a Greedy, try to match at i once. template <typename T> - int matchHead(T*, SkRecord* record, int i) { + int matchFirst(T* first, SkRecord* record, int i) { if (i < record->count()) { - if (record->mutate<bool>(i, fHead)) { + if (record->mutate<bool>(i, *first)) { return i+1; } } return 0; } - // If head is a Star, walk i until it doesn't match. + // If first is a Greedy, walk i until it doesn't match. template <typename T> - int matchHead(Star<T>*, SkRecord* record, int i) { + int matchFirst(Greedy<T>* first, SkRecord* record, int i) { while (i < record->count()) { - if (!record->mutate<bool>(i, fHead)) { + if (!record->mutate<bool>(i, *first)) { return i; } i++; @@ -164,43 +166,10 @@ private: return 0; } - Matcher fHead; - Pattern fTail; - - // All Cons are friends with each other. This lets first, second, and third work. - template <typename, typename> friend class Cons; + First fFirst; + Pattern<Rest...> fRest; }; -// Nil is the end of every pattern Cons chain. -struct Nil { - // Bottoms out recursion down the fTail chain. Just return whatever i the front decided on. - int match(SkRecord*, int i) { return i; } -}; - -// These Pattern# types are syntax sugar over Cons and Nil, just to help eliminate some of the -// template noise. Use these if you can. Feel free to add more for longer patterns. -// All types A, B, C, ... are Matchers. -template <typename A> -struct Pattern1 : Cons<A, Nil> {}; - -template <typename A, typename B> -struct Pattern2 : Cons<A, Pattern1<B> > {}; - -template <typename A, typename B, typename C> -struct Pattern3 : Cons<A, Pattern2<B, C> > {}; - -template <typename A, typename B, typename C, typename D> -struct Pattern4 : Cons<A, Pattern3<B, C, D> > {}; - -template <typename A, typename B, typename C, typename D, typename E> -struct Pattern5 : Cons<A, Pattern4<B, C, D, E> > {}; - -template <typename A, typename B, typename C, typename D, typename E, typename F> -struct Pattern6 : Cons<A, Pattern5<B, C, D, E, F> > {}; - -template <typename A, typename B, typename C, typename D, typename E, typename F, typename G> -struct Pattern7 : Cons<A, Pattern6<B, C, D, E, F, G> > {}; - } // namespace SkRecords #endif//SkRecordPattern_DEFINED |