2013-07-12 18:22:49 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2013 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*
|
|
|
|
*
|
2016-01-05 22:59:40 +00:00
|
|
|
* This header provides some of the helpers (like std::enable_if_t) which will
|
|
|
|
* become available with C++14 in the type_traits header (in the skstd
|
|
|
|
* namespace). This header also provides several Skia specific additions such
|
|
|
|
* as SK_WHEN and the sknonstd namespace.
|
2013-07-12 18:22:49 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef SkTLogic_DEFINED
|
|
|
|
#define SkTLogic_DEFINED
|
|
|
|
|
2017-10-18 15:30:56 +00:00
|
|
|
#include <array>
|
2015-09-07 19:45:52 +00:00
|
|
|
#include <stddef.h>
|
2015-08-05 19:09:57 +00:00
|
|
|
#include <stdint.h>
|
2016-01-05 22:59:40 +00:00
|
|
|
#include <type_traits>
|
|
|
|
#include <utility>
|
2015-08-05 19:09:57 +00:00
|
|
|
|
2015-08-28 14:09:20 +00:00
|
|
|
namespace skstd {
|
|
|
|
|
2016-01-05 22:59:40 +00:00
|
|
|
template <bool B> using bool_constant = std::integral_constant<bool, B>;
|
2015-09-07 19:45:52 +00:00
|
|
|
|
2016-01-05 22:59:40 +00:00
|
|
|
template <bool B, typename T, typename F> using conditional_t = typename std::conditional<B, T, F>::type;
|
|
|
|
template <bool B, typename T = void> using enable_if_t = typename std::enable_if<B, T>::type;
|
2015-08-28 14:09:20 +00:00
|
|
|
|
2016-01-05 22:59:40 +00:00
|
|
|
template <typename T> using remove_const_t = typename std::remove_const<T>::type;
|
|
|
|
template <typename T> using remove_volatile_t = typename std::remove_volatile<T>::type;
|
|
|
|
template <typename T> using remove_cv_t = typename std::remove_cv<T>::type;
|
2016-01-06 16:30:59 +00:00
|
|
|
template <typename T> using remove_pointer_t = typename std::remove_pointer<T>::type;
|
2016-01-05 22:59:40 +00:00
|
|
|
template <typename T> using remove_reference_t = typename std::remove_reference<T>::type;
|
|
|
|
template <typename T> using remove_extent_t = typename std::remove_extent<T>::type;
|
2015-08-28 14:09:20 +00:00
|
|
|
|
2016-01-05 22:59:40 +00:00
|
|
|
template <typename T> using add_const_t = typename std::add_const<T>::type;
|
|
|
|
template <typename T> using add_volatile_t = typename std::add_volatile<T>::type;
|
|
|
|
template <typename T> using add_cv_t = typename std::add_cv<T>::type;
|
|
|
|
template <typename T> using add_pointer_t = typename std::add_pointer<T>::type;
|
Use ::std for is_empty, is_class, add_xxx_reference, remove decay.
SkTLogic.h contains implemenetations of is_empty, is_class, decay,
decay_t, add_lvalue_reference, add_rvalue_reference, and
add_rvalue_reference_t. The declaration of is_class is only used by
is_empty. The current implementation of is_empty will not work
correctly with 'final'. The current implementation of
add_lvalue_reference does not support clarifications in c++17. No Skia
code is currently using decay, decay_t, add_rvalue_reference, and
add_rvalue_reference_t. In addition, there are no known issues with
any of these in ::std with any supported compiler.
The implementations of is_function and is_convertible are commented to
note why they are still present.
Review URL: https://codereview.chromium.org/1567123006
2016-01-08 19:05:09 +00:00
|
|
|
template <typename T> using add_lvalue_reference_t = typename std::add_lvalue_reference<T>::type;
|
2013-07-12 18:22:49 +00:00
|
|
|
|
2017-10-18 15:30:56 +00:00
|
|
|
template <typename T> using result_of_t = typename std::result_of<T>::type;
|
|
|
|
|
2016-03-08 16:35:23 +00:00
|
|
|
template <typename... T> using common_type_t = typename std::common_type<T...>::type;
|
|
|
|
|
2016-03-19 22:06:56 +00:00
|
|
|
// Chromium currently requires gcc 4.8.2 or a recent clang compiler, but uses libstdc++4.6.4.
|
|
|
|
// Note that Precise actually uses libstdc++4.6.3.
|
|
|
|
// Unfortunately, libstdc++ STL before libstdc++4.7 do not define std::underlying_type.
|
|
|
|
// Newer gcc and clang compilers have __underlying_type which does not depend on runtime support.
|
|
|
|
// See https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html for __GLIBCXX__ values.
|
|
|
|
// Unfortunately __GLIBCXX__ is a date, but no updates to versions before 4.7 are now anticipated.
|
|
|
|
#define SK_GLIBCXX_4_7_0 20120322
|
|
|
|
// Updates to versions before 4.7 but released after 4.7 was released.
|
|
|
|
#define SK_GLIBCXX_4_5_4 20120702
|
|
|
|
#define SK_GLIBCXX_4_6_4 20121127
|
|
|
|
#if defined(__GLIBCXX__) && (__GLIBCXX__ < SK_GLIBCXX_4_7_0 || \
|
|
|
|
__GLIBCXX__ == SK_GLIBCXX_4_5_4 || \
|
|
|
|
__GLIBCXX__ == SK_GLIBCXX_4_6_4)
|
|
|
|
template <typename T> struct underlying_type {
|
|
|
|
using type = __underlying_type(T);
|
|
|
|
};
|
|
|
|
#else
|
|
|
|
template <typename T> using underlying_type = std::underlying_type<T>;
|
|
|
|
#endif
|
|
|
|
template <typename T> using underlying_type_t = typename skstd::underlying_type<T>::type;
|
|
|
|
|
2017-10-18 15:30:56 +00:00
|
|
|
|
|
|
|
template <std::size_t... Ints> struct index_sequence {
|
|
|
|
using type = index_sequence;
|
|
|
|
using value_type = size_t;
|
|
|
|
static constexpr std::size_t size() noexcept { return sizeof...(Ints); }
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename S1, typename S2> struct make_index_sequence_combine;
|
|
|
|
template <size_t... I1, size_t... I2>
|
|
|
|
struct make_index_sequence_combine<skstd::index_sequence<I1...>, skstd::index_sequence<I2...>>
|
|
|
|
: skstd::index_sequence<I1..., (sizeof...(I1)+I2)...>
|
|
|
|
{ };
|
|
|
|
|
|
|
|
template <size_t N> struct make_index_sequence
|
|
|
|
: make_index_sequence_combine<typename skstd::make_index_sequence< N/2>::type,
|
|
|
|
typename skstd::make_index_sequence<N - N/2>::type>{};
|
|
|
|
template<> struct make_index_sequence<0> : skstd::index_sequence< >{};
|
|
|
|
template<> struct make_index_sequence<1> : skstd::index_sequence<0>{};
|
|
|
|
|
2015-08-28 14:09:20 +00:00
|
|
|
} // namespace skstd
|
|
|
|
|
|
|
|
// The sknonstd namespace contains things we would like to be proposed and feel std-ish.
|
|
|
|
namespace sknonstd {
|
|
|
|
|
|
|
|
// The name 'copy' here is fraught with peril. In this case it means 'append', not 'overwrite'.
|
|
|
|
// Alternate proposed names are 'propagate', 'augment', or 'append' (and 'add', but already taken).
|
|
|
|
// std::experimental::propagate_const already exists for other purposes in TSv2.
|
|
|
|
// These also follow the <dest, source> pattern used by boost.
|
|
|
|
template <typename D, typename S> struct copy_const {
|
2016-01-07 20:39:11 +00:00
|
|
|
using type = skstd::conditional_t<std::is_const<S>::value, skstd::add_const_t<D>, D>;
|
2013-07-12 18:22:49 +00:00
|
|
|
};
|
2015-08-28 14:09:20 +00:00
|
|
|
template <typename D, typename S> using copy_const_t = typename copy_const<D, S>::type;
|
2013-07-12 18:22:49 +00:00
|
|
|
|
2015-08-28 14:09:20 +00:00
|
|
|
template <typename D, typename S> struct copy_volatile {
|
2016-01-07 20:39:11 +00:00
|
|
|
using type = skstd::conditional_t<std::is_volatile<S>::value, skstd::add_volatile_t<D>, D>;
|
2013-07-12 18:22:49 +00:00
|
|
|
};
|
2015-08-28 14:09:20 +00:00
|
|
|
template <typename D, typename S> using copy_volatile_t = typename copy_volatile<D, S>::type;
|
2013-07-12 18:22:49 +00:00
|
|
|
|
2015-08-28 14:09:20 +00:00
|
|
|
template <typename D, typename S> struct copy_cv {
|
|
|
|
using type = copy_volatile_t<copy_const_t<D, S>, S>;
|
2014-04-28 16:19:45 +00:00
|
|
|
};
|
2015-08-28 14:09:20 +00:00
|
|
|
template <typename D, typename S> using copy_cv_t = typename copy_cv<D, S>::type;
|
|
|
|
|
|
|
|
// The name 'same' here means 'overwrite'.
|
|
|
|
// Alternate proposed names are 'replace', 'transfer', or 'qualify_from'.
|
|
|
|
// same_xxx<D, S> can be written as copy_xxx<remove_xxx_t<D>, S>
|
|
|
|
template <typename D, typename S> using same_const = copy_const<skstd::remove_const_t<D>, S>;
|
|
|
|
template <typename D, typename S> using same_const_t = typename same_const<D, S>::type;
|
|
|
|
template <typename D, typename S> using same_volatile =copy_volatile<skstd::remove_volatile_t<D>,S>;
|
|
|
|
template <typename D, typename S> using same_volatile_t = typename same_volatile<D, S>::type;
|
|
|
|
template <typename D, typename S> using same_cv = copy_cv<skstd::remove_cv_t<D>, S>;
|
|
|
|
template <typename D, typename S> using same_cv_t = typename same_cv<D, S>::type;
|
2014-04-28 16:19:45 +00:00
|
|
|
|
2015-08-28 14:09:20 +00:00
|
|
|
} // namespace sknonstd
|
2014-04-28 16:19:45 +00:00
|
|
|
|
2015-09-28 17:33:02 +00:00
|
|
|
// Just a pithier wrapper for enable_if_t.
|
|
|
|
#define SK_WHEN(condition, T) skstd::enable_if_t<!!(condition), T>
|
Add pattern matchers for SkRecord
This is a mid-level library for finding patterns of commands in an SkRecord. At the API level, it's a bit regex inspired. Some examples:
- Pattern1<Is<DrawRect>> matches a single DrawRect
- Pattern1<Star<Is<DrawRect>>> matches 0 or more DrawRects
- Pattern2<Is<ClipRect>, Is<DrawRect>> matches a single clip rect followed by a single draw rect
- Pattern3<Is<Save>, Star<IsDraw>, Is<Restore>> matches a single Save, followed by any number of Draws, followed by Restore
- Pattern1<Or<Is<DrawRect>, Is<ClipRect>>> matches a DrawRect or a ClipRect
- Pattern1<Not<Is<ClipRect>>> matches a command that's notClipRect.
Once you have a pattern, you can call .search() on it to step through ranges of matching commands. This means patterns can replace most of the custom iteration logic for optimization passes: the generic pattern searching steps through all the optimization candidates, which optimization-specific code further inspects and mutates.
SkRecordTraits is now unused. Bye bye!
Generated code and performance of SkRecordOpts is very similar to what it was before. (I had to use SK_ALWAYS_INLINE in a few places to make this so.)
BUG=skia:2378
R=fmalita@chromium.org, bungeman@google.com, mtklein@google.com
Author: mtklein@chromium.org
Review URL: https://codereview.chromium.org/263063002
git-svn-id: http://skia.googlecode.com/svn/trunk@14582 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-05-05 21:59:52 +00:00
|
|
|
|
2013-07-12 18:31:59 +00:00
|
|
|
#endif
|