1c6ad06acefa096716f8dabed5342f9b89dc43dfemtklein/* 2c6ad06acefa096716f8dabed5342f9b89dc43dfemtklein * Copyright 2015 Google Inc. 3c6ad06acefa096716f8dabed5342f9b89dc43dfemtklein * 4c6ad06acefa096716f8dabed5342f9b89dc43dfemtklein * Use of this source code is governed by a BSD-style license that can be 5c6ad06acefa096716f8dabed5342f9b89dc43dfemtklein * found in the LICENSE file. 6c6ad06acefa096716f8dabed5342f9b89dc43dfemtklein */ 7c6ad06acefa096716f8dabed5342f9b89dc43dfemtklein 873fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org#ifndef SkRecordPattern_DEFINED 973fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org#define SkRecordPattern_DEFINED 1073fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 116b20a559968e1ed0d3aa4ecbd6ddda9e681b4f86Hal Canary#include "SkRecord.h" 1273fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org#include "SkTLogic.h" 1373fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 1473fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.orgnamespace SkRecords { 1573fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 1673fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org// First, some matchers. These match a single command in the SkRecord, 1773fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org// and may hang onto some data from it. If so, you can get the data by calling .get(). 1873fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 1973fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org// Matches a command of type T, and stores that command. 2073fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.orgtemplate <typename T> 2173fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.orgclass Is { 2273fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.orgpublic: 2396fcdcc219d2a0d3579719b84b28bede76efba64halcanary Is() : fPtr(nullptr) {} 2473fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 2573fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org typedef T type; 2673fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org type* get() { return fPtr; } 2773fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 28c71da1f6ed3a5e1a3eb2dd860b8129e1b423f9f4commit-bot@chromium.org bool operator()(T* ptr) { 2973fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org fPtr = ptr; 3073fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org return true; 3173fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org } 3273fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 3373fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org template <typename U> 34c71da1f6ed3a5e1a3eb2dd860b8129e1b423f9f4commit-bot@chromium.org bool operator()(U*) { 3596fcdcc219d2a0d3579719b84b28bede76efba64halcanary fPtr = nullptr; 3673fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org return false; 3773fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org } 3873fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 3973fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.orgprivate: 4073fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org type* fPtr; 4173fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org}; 4273fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 4373fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org// Matches any command that draws, and stores its paint. 4473fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.orgclass IsDraw { 4573fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.orgpublic: 4696fcdcc219d2a0d3579719b84b28bede76efba64halcanary IsDraw() : fPaint(nullptr) {} 4773fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 4873fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org typedef SkPaint type; 4973fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org type* get() { return fPaint; } 5073fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 5173fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org template <typename T> 52449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein SK_WHEN(T::kTags & kDraw_Tag, bool) operator()(T* draw) { 5373fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org fPaint = AsPtr(draw->paint); 5473fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org return true; 5573fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org } 5673fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 57449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein bool operator()(DrawDrawable*) { 58449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein static_assert(DrawDrawable::kTags & kDraw_Tag, ""); 5996fcdcc219d2a0d3579719b84b28bede76efba64halcanary fPaint = nullptr; 60449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein return true; 6173fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org } 6273fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 63449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein template <typename T> 64449d9b7e2d1b2e20963f18639c6e541ef953f069mtklein SK_WHEN(!(T::kTags & kDraw_Tag), bool) operator()(T* draw) { 6596fcdcc219d2a0d3579719b84b28bede76efba64halcanary fPaint = nullptr; 661b546462bb91e93cf2f033eb2dab53ec492b64abcommit-bot@chromium.org return false; 671b546462bb91e93cf2f033eb2dab53ec492b64abcommit-bot@chromium.org } 681b546462bb91e93cf2f033eb2dab53ec492b64abcommit-bot@chromium.org 6973fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.orgprivate: 7073fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org // Abstracts away whether the paint is always part of the command or optional. 7173fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org template <typename T> static T* AsPtr(SkRecords::Optional<T>& x) { return x; } 7273fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org template <typename T> static T* AsPtr(T& x) { return &x; } 7373fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 7473fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org type* fPaint; 7573fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org}; 7673fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 7773fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org// Matches if Matcher doesn't. Stores nothing. 7873fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.orgtemplate <typename Matcher> 7973fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.orgstruct Not { 8073fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org template <typename T> 81c71da1f6ed3a5e1a3eb2dd860b8129e1b423f9f4commit-bot@chromium.org bool operator()(T* ptr) { return !Matcher()(ptr); } 8273fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org}; 8373fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 8424e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein// Matches if any of First or Rest... does. Stores nothing. 8524e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtkleintemplate <typename First, typename... Rest> 8673fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.orgstruct Or { 8773fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org template <typename T> 8824e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein bool operator()(T* ptr) { return First()(ptr) || Or<Rest...>()(ptr); } 8924e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein}; 9024e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtkleintemplate <typename First> 9124e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtkleinstruct Or<First> { 9224e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein template <typename T> 9324e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein bool operator()(T* ptr) { return First()(ptr); } 9473fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org}; 9573fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 9699d6a9ee8b3516de892d118c71aa5e6e5c865efdmtklein 9724e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein// Greedy is a special matcher that greedily matches Matcher 0 or more times. Stores nothing. 9873fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.orgtemplate <typename Matcher> 9924e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtkleinstruct Greedy { 10073fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org template <typename T> 101888e4687d96b6af5b5c0efbcf05fcdc010ea8aa2commit-bot@chromium.org bool operator()(T* ptr) { return Matcher()(ptr); } 10273fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org}; 10373fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 10424e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein// Pattern matches each of its matchers in order. 10573fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org// 10673fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org// This is the main entry point to pattern matching, and so provides a couple of extra API bits: 10773fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org// - search scans through the record to look for matches; 10824e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein// - first, second, third, ... return the data stored by their respective matchers in the pattern. 10924e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein 11024e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtkleintemplate <typename... Matchers> class Pattern; 11124e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein 11224e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtkleintemplate <> class Pattern<> { 11373fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.orgpublic: 11424e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein // Bottoms out recursion. Just return whatever i the front decided on. 11524e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein int match(SkRecord*, int i) { return i; } 11624e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein}; 11724e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein 11824e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtkleintemplate <typename First, typename... Rest> 11924e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtkleinclass Pattern<First, Rest...> { 12024e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtkleinpublic: 12124e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein // If this pattern matches the SkRecord starting from i, 12273fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org // return the index just past the end of the pattern, otherwise return 0. 123c6ad06acefa096716f8dabed5342f9b89dc43dfemtklein SK_ALWAYS_INLINE int match(SkRecord* record, int i) { 12424e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein i = this->matchFirst(&fFirst, record, i); 12524e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein return i > 0 ? fRest.match(record, i) : 0; 12673fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org } 12773fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 12873fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org // Starting from *end, walk through the SkRecord to find the first span matching this pattern. 12973fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org // If there is no such span, return false. If there is, return true and set [*begin, *end). 130c6ad06acefa096716f8dabed5342f9b89dc43dfemtklein SK_ALWAYS_INLINE bool search(SkRecord* record, int* begin, int* end) { 13173fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org for (*begin = *end; *begin < record->count(); ++(*begin)) { 13273fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org *end = this->match(record, *begin); 13373fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org if (*end != 0) { 13473fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org return true; 13573fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org } 13673fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org } 13773fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org return false; 13873fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org } 13973fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 14024e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein // TODO: some sort of smart get<i>() 14124e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein template <typename T> T* first() { return fFirst.get(); } 14224e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein template <typename T> T* second() { return fRest.template first<T>(); } 14324e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein template <typename T> T* third() { return fRest.template second<T>(); } 14424e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein template <typename T> T* fourth() { return fRest.template third<T>(); } 14573fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 14673fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.orgprivate: 14724e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein // If first isn't a Greedy, try to match at i once. 14873fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org template <typename T> 14924e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein int matchFirst(T* first, SkRecord* record, int i) { 15073fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org if (i < record->count()) { 151343a63d082bda969d7e8a4e09ba850e931185269mtklein if (record->mutate(i, *first)) { 15273fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org return i+1; 15373fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org } 15473fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org } 15573fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org return 0; 15673fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org } 15773fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 15824e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein // If first is a Greedy, walk i until it doesn't match. 15973fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org template <typename T> 16024e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein int matchFirst(Greedy<T>* first, SkRecord* record, int i) { 16173fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org while (i < record->count()) { 162343a63d082bda969d7e8a4e09ba850e931185269mtklein if (!record->mutate(i, *first)) { 16373fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org return i; 16473fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org } 16573fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org i++; 16673fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org } 16773fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org return 0; 16873fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org } 16973fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 17024e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein First fFirst; 17124e7db8b2ea663f8fe4d7bbfa1d686fd643990bbmtklein Pattern<Rest...> fRest; 17273fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org}; 17373fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 17473fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org} // namespace SkRecords 17573fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org 17673fffeb83aab56bc8c2c5ce143ee9d132d64ac37commit-bot@chromium.org#endif//SkRecordPattern_DEFINED 177