14344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/*
24344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Copyright (C) 2016 The Android Open Source Project
34344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
44344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Licensed under the Apache License, Version 2.0 (the "License");
54344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * you may not use this file except in compliance with the License.
64344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * You may obtain a copy of the License at
74344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
84344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *      http://www.apache.org/licenses/LICENSE-2.0
94344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
104344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Unless required by applicable law or agreed to in writing, software
114344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * distributed under the License is distributed on an "AS IS" BASIS,
124344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * See the License for the specific language governing permissions and
144344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * limitations under the License.
154344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim */
164344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
174344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/** \file
184344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Templates used to declare parameters.
194344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim */
204344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim#ifndef C2PARAM_DEF_H_
214344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim#define C2PARAM_DEF_H_
224344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
234344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim#include <type_traits>
244344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
254344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim#include <C2Param.h>
264344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
274344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// \addtogroup Parameters
284344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// @{
294344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
304344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/* ======================== UTILITY TEMPLATES FOR PARAMETER DEFINITIONS ======================== */
314344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
324344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// \addtogroup internal
334344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// @{
344344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
354344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// Helper class that checks if a type has equality and inequality operators.
364344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimstruct C2_HIDE _C2Comparable_impl
374344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim{
384344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<typename S, typename=decltype(S() == S())>
394344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    static std::true_type TestEqual(int);
404344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<typename>
414344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    static std::false_type TestEqual(...);
424344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
434344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<typename S, typename=decltype(S() != S())>
444344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    static std::true_type TestNotEqual(int);
454344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<typename>
464344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    static std::false_type TestNotEqual(...);
474344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim};
484344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
494344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/**
504344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Helper template that returns if a type has equality and inequality operators.
514344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
524344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Use as _C2Comparable<typename S>::value.
534344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim */
544344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtemplate<typename S>
554344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimstruct C2_HIDE _C2Comparable
564344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    : public std::integral_constant<bool, decltype(_C2Comparable_impl::TestEqual<S>(0))::value
574344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim                        || decltype(_C2Comparable_impl::TestNotEqual<S>(0))::value> {
584344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim};
594344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
604344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim///  Helper class that checks if a type has a CORE_INDEX constant.
614344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimstruct C2_HIDE _C2CoreIndexHelper_impl
624344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim{
634344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<typename S, int=S::CORE_INDEX>
644344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    static std::true_type TestCoreIndex(int);
654344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<typename>
664344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    static std::false_type TestCoreIndex(...);
674344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim};
684344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
69587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnar/// Macro that defines and thus overrides a type's CORE_INDEX for a setting
70587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnar#define _C2_CORE_INDEX_OVERRIDE(coreIndex) \
71587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnarpublic: \
72587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnar    enum : uint32_t { CORE_INDEX = coreIndex };
734344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
744344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
75587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnar/// Helper template that adds a CORE_INDEX to a type if it does not have one (for testing)
764344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtemplate<typename S, int CoreIndex>
77587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnarstruct C2_HIDE _C2AddCoreIndex : public S {
78587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnar    _C2_CORE_INDEX_OVERRIDE(CoreIndex)
79587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnar};
804344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
814344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/**
824344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \brief Helper class to check struct requirements for parameters.
834344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
844344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Features:
854344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *  - verify default constructor, no virtual methods, and no equality operators.
864344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *  - expose PARAM_TYPE, and non-flex FLEX_SIZE.
874344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim */
884344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtemplate<typename S, int CoreIndex, unsigned TypeFlags>
894344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimstruct C2_HIDE _C2StructCheck {
904344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    static_assert(
914344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            std::is_default_constructible<S>::value, "C2 structure must have default constructor");
924344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    static_assert(!std::is_polymorphic<S>::value, "C2 structure must not have virtual methods");
934344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    static_assert(!_C2Comparable<S>::value, "C2 structure must not have operator== or !=");
944344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
954344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimpublic:
964344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    enum : uint32_t {
974344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        PARAM_TYPE = CoreIndex | TypeFlags
984344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    };
994344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
1004344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimprotected:
1014344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    enum : uint32_t {
10289f1966353272db3ba08eba936652e94dcab7289Lajos Molnar        FLEX_SIZE = 0,
1034344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    };
1044344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim};
1054344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
1064344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// Helper class that checks if a type has an integer FLEX_SIZE member.
1074344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimstruct C2_HIDE _C2Flexible_impl {
1084344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// specialization for types that have a FLEX_SIZE member
1094344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<typename S, unsigned=S::FLEX_SIZE>
1104344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    static std::true_type TestFlexSize(int);
1114344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<typename>
1124344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    static std::false_type TestFlexSize(...);
1134344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim};
1144344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
1154344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// Helper template that returns if a type has an integer FLEX_SIZE member.
1164344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtemplate<typename S>
1174344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimstruct C2_HIDE _C2Flexible
1184344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    : public std::integral_constant<bool, decltype(_C2Flexible_impl::TestFlexSize<S>(0))::value> {
1194344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim};
1204344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
1214344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// Macro to test if a type is flexible (has a FLEX_SIZE member).
1224344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim#define IF_FLEXIBLE(S) ENABLE_IF(_C2Flexible<S>::value)
1234344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// Shorthand for std::enable_if
1244344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim#define ENABLE_IF(cond) typename std::enable_if<cond>::type
1254344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
12689f1966353272db3ba08eba936652e94dcab7289Lajos Molnartemplate<typename T, typename V=void>
12789f1966353272db3ba08eba936652e94dcab7289Lajos Molnarstruct C2_HIDE _c2_enable_if_type {
12889f1966353272db3ba08eba936652e94dcab7289Lajos Molnar    typedef V type;
12989f1966353272db3ba08eba936652e94dcab7289Lajos Molnar};
13089f1966353272db3ba08eba936652e94dcab7289Lajos Molnar
1314344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// Helper template that exposes the flexible subtype of a struct.
1324344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtemplate<typename S, typename E=void>
1334344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimstruct C2_HIDE _C2FlexHelper {
1344344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    typedef void FlexType;
1354344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    enum : uint32_t { FLEX_SIZE = 0 };
1364344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim};
1374344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
13889f1966353272db3ba08eba936652e94dcab7289Lajos Molnar/// Specialization for flexible types. This only works if _FlexMemberType is public.
1394344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtemplate<typename S>
1404344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimstruct C2_HIDE _C2FlexHelper<S,
14189f1966353272db3ba08eba936652e94dcab7289Lajos Molnar        typename _c2_enable_if_type<typename S::_FlexMemberType>::type> {
14289f1966353272db3ba08eba936652e94dcab7289Lajos Molnar    typedef typename _C2FlexHelper<typename S::_FlexMemberType>::FlexType FlexType;
14389f1966353272db3ba08eba936652e94dcab7289Lajos Molnar    enum : uint32_t { FLEX_SIZE = _C2FlexHelper<typename S::_FlexMemberType>::FLEX_SIZE };
1444344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim};
1454344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
1464344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// Specialization for flex arrays.
1474344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtemplate<typename S>
1484344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimstruct C2_HIDE _C2FlexHelper<S[],
1494344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        typename std::enable_if<std::is_void<typename _C2FlexHelper<S>::FlexType>::value>::type> {
1504344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    typedef S FlexType;
1514344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    enum : uint32_t { FLEX_SIZE = sizeof(S) };
1524344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim};
1534344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
1544344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/**
1554344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \brief Helper class to check flexible struct requirements and add common operations.
1564344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
1574344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Features:
1581cbff72e1f2998f175fe23b79737e4cdb8ddd33aLajos Molnar *  - expose CORE_INDEX and FieldList (this is normally inherited from the struct, but flexible
1594344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *    structs cannot be base classes and thus inherited from)
1604344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *  - disable copy assignment and construction (TODO: this is already done in the FLEX macro for the
1614344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *    flexible struct, so may not be needed here)
1624344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim */
1634344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtemplate<typename S, int ParamIndex, unsigned TypeFlags>
1644344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimstruct C2_HIDE _C2FlexStructCheck :
1654344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim// add flexible flag as _C2StructCheck defines PARAM_TYPE
1664344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        public _C2StructCheck<S, ParamIndex | C2Param::CoreIndex::IS_FLEX_FLAG, TypeFlags> {
1674344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimpublic:
1684344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    enum : uint32_t {
1694344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        /// \hideinitializer
1704344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        CORE_INDEX = ParamIndex | C2Param::CoreIndex::IS_FLEX_FLAG, ///< flexible struct core-index
1714344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    };
1724344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
1731cbff72e1f2998f175fe23b79737e4cdb8ddd33aLajos Molnar    inline static const std::vector<C2FieldDescriptor> FieldList() { return S::FieldList(); }
1744344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
1754344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    // default constructor needed because of the disabled copy constructor
1764344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline _C2FlexStructCheck() = default;
1774344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
1784344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimprotected:
1794344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    // cannot copy flexible params
1804344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    _C2FlexStructCheck(const _C2FlexStructCheck<S, ParamIndex, TypeFlags> &) = delete;
1814344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    _C2FlexStructCheck& operator= (const _C2FlexStructCheck<S, ParamIndex, TypeFlags> &) = delete;
1824344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
1834344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    // constants used for helper methods
1844344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    enum : uint32_t {
1854344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        /// \hideinitializer
1864344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        FLEX_SIZE = _C2FlexHelper<S>::FLEX_SIZE, ///< size of flexible type
1874344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        /// \hideinitializer
1884344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        MAX_SIZE = (uint32_t)std::min((size_t)UINT32_MAX, SIZE_MAX), // TODO: is this always u32 max?
1894344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        /// \hideinitializer
1904344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        BASE_SIZE = sizeof(S) + sizeof(C2Param), ///< size of the base param
1914344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    };
1924344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
1934344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// returns the allocated size of this param with flexCount, or 0 if it would overflow.
1944344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline static size_t CalcSize(size_t flexCount, size_t size = BASE_SIZE) {
1954344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        if (flexCount <= (MAX_SIZE - size) / S::FLEX_SIZE) {
1964344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            return size + S::FLEX_SIZE * flexCount;
1974344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        }
1984344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        return 0;
1994344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    }
2004344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
2014344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// dynamic new operator usable for params of type S
2024344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline void* operator new(size_t size, size_t flexCount) noexcept {
2034344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        // TODO: assert(size == BASE_SIZE);
2044344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        size = CalcSize(flexCount, size);
2054344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        if (size > 0) {
2064344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            return ::operator new(size);
2074344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        }
2084344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        return nullptr;
2094344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    }
2104344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim};
2114344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
2124344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// Define From() cast operators for params.
2134344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim#define DEFINE_CAST_OPERATORS(_Type) \
2144344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline static _Type* From(C2Param *other) { \
2154344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        return (_Type*)C2Param::IfSuitable( \
2164344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim                other, sizeof(_Type), _Type::PARAM_TYPE, _Type::FLEX_SIZE, \
2174344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim                (_Type::PARAM_TYPE & T::Index::DIR_UNDEFINED) != T::Index::DIR_UNDEFINED); \
2184344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    } \
2194344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline static const _Type* From(const C2Param *other) { \
2204344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        return const_cast<const _Type*>(From(const_cast<C2Param *>(other))); \
2214344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    } \
2224344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline static _Type* From(std::nullptr_t) { return nullptr; } \
2234344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
2244344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/**
2254344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Define flexible allocators (AllocShared or AllocUnique) for flexible params.
22646b790622fc4e1d90966f41f5e7f5ee3a3b1ca0aLajos Molnar *  - P::AllocXyz(flexCount, args...): allocate for given flex-count. This maps to
22746b790622fc4e1d90966f41f5e7f5ee3a3b1ca0aLajos Molnar *          T(flexCount, args...)\
22846b790622fc4e1d90966f41f5e7f5ee3a3b1ca0aLajos Molnar *
22946b790622fc4e1d90966f41f5e7f5ee3a3b1ca0aLajos Molnar * Clang does not support args... followed by templated param as args... eats it. Hence,
23046b790622fc4e1d90966f41f5e7f5ee3a3b1ca0aLajos Molnar * provide specializations where the initializer replaces the flexCount.
23146b790622fc4e1d90966f41f5e7f5ee3a3b1ca0aLajos Molnar *
23246b790622fc4e1d90966f41f5e7f5ee3a3b1ca0aLajos Molnar * Specializations that deduce flexCount:
23346b790622fc4e1d90966f41f5e7f5ee3a3b1ca0aLajos Molnar *  - P::AllocXyz(T[], args...): allocate for size of (and with) init array.
23446b790622fc4e1d90966f41f5e7f5ee3a3b1ca0aLajos Molnar *  - P::AllocXyz(std::initializer_list<T>, args...): allocate for size of (and with) initializer
23546b790622fc4e1d90966f41f5e7f5ee3a3b1ca0aLajos Molnar *            list.
23646b790622fc4e1d90966f41f5e7f5ee3a3b1ca0aLajos Molnar *  - P::AllocXyz(std::vector<T>, args...): allocate for size of (and with) init vector.
23746b790622fc4e1d90966f41f5e7f5ee3a3b1ca0aLajos Molnar *  These specializations map to T(flexCount = size-of-init, args..., init)
2384344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim */
2394344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim#define DEFINE_FLEXIBLE_ALLOC(_Type, S, ptr, Ptr) \
2404344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<typename ...Args> \
2414344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline static std::ptr##_ptr<_Type> Alloc##Ptr(size_t flexCount, const Args(&... args)) { \
2424344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        return std::ptr##_ptr<_Type>(new(flexCount) _Type(flexCount, args...)); \
2434344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    } \
24446b790622fc4e1d90966f41f5e7f5ee3a3b1ca0aLajos Molnar    template<typename ...Args, typename U=typename S::FlexType> \
24546b790622fc4e1d90966f41f5e7f5ee3a3b1ca0aLajos Molnar    inline static std::ptr##_ptr<_Type> Alloc##Ptr( \
24646b790622fc4e1d90966f41f5e7f5ee3a3b1ca0aLajos Molnar            const std::initializer_list<U> &init, const Args(&... args)) { \
24746b790622fc4e1d90966f41f5e7f5ee3a3b1ca0aLajos Molnar        return std::ptr##_ptr<_Type>(new(init.size()) _Type(init.size(), args..., init)); \
2484344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    } \
2494344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<typename ...Args, typename U=typename S::FlexType> \
2504344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline static std::ptr##_ptr<_Type> Alloc##Ptr( \
25146b790622fc4e1d90966f41f5e7f5ee3a3b1ca0aLajos Molnar            const std::vector<U> &init, const Args(&... args)) { \
2524344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        return std::ptr##_ptr<_Type>(new(init.size()) _Type(init.size(), args..., init)); \
2534344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    } \
25446b790622fc4e1d90966f41f5e7f5ee3a3b1ca0aLajos Molnar    template<typename ...Args, typename U=typename S::FlexType, unsigned N> \
25546b790622fc4e1d90966f41f5e7f5ee3a3b1ca0aLajos Molnar    inline static std::ptr##_ptr<_Type> Alloc##Ptr(const U(&init)[N], const Args(&... args)) { \
25646b790622fc4e1d90966f41f5e7f5ee3a3b1ca0aLajos Molnar        return std::ptr##_ptr<_Type>(new(N) _Type(N, args..., init)); \
25746b790622fc4e1d90966f41f5e7f5ee3a3b1ca0aLajos Molnar    } \
2584344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
2594344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/**
2604344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Define flexible methods AllocShared, AllocUnique and flexCount.
2614344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim */
2624344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim#define DEFINE_FLEXIBLE_METHODS(_Type, S) \
2634344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    DEFINE_FLEXIBLE_ALLOC(_Type, S, shared, Shared) \
2644344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    DEFINE_FLEXIBLE_ALLOC(_Type, S, unique, Unique) \
2654344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline size_t flexCount() const { \
2664344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        static_assert(sizeof(_Type) == _Type::BASE_SIZE, "incorrect BASE_SIZE"); \
2674344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        size_t sz = this->size(); \
2684344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        if (sz >= sizeof(_Type)) { \
2694344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            return (sz - sizeof(_Type)) / _Type::FLEX_SIZE; \
2704344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        } \
2714344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        return 0; \
2724344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    } \
2734344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
2744344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// Mark flexible member variable and make structure flexible.
2754344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim#define FLEX(cls, m) \
2764344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    C2_DO_NOT_COPY(cls) \
2774344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimprivate: \
2784344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    C2PARAM_MAKE_FRIENDS \
2794344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /** \if 0 */ \
2804344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<typename, typename> friend struct _C2FlexHelper; \
2814344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimpublic: \
28289f1966353272db3ba08eba936652e94dcab7289Lajos Molnar    typedef decltype(m) _FlexMemberType; \
28389f1966353272db3ba08eba936652e94dcab7289Lajos Molnar    /* default constructor with flexCount */ \
28489f1966353272db3ba08eba936652e94dcab7289Lajos Molnar    inline cls(size_t) : cls() {} \
28589f1966353272db3ba08eba936652e94dcab7289Lajos Molnar    /* constexpr static _FlexMemberType cls::* flexMember = &cls::m; */ \
28689f1966353272db3ba08eba936652e94dcab7289Lajos Molnar    typedef typename _C2FlexHelper<_FlexMemberType>::FlexType FlexType; \
2874344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    static_assert(\
2884344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            !std::is_void<FlexType>::value, \
2894344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            "member is not flexible, or a flexible array of a flexible type"); \
29089f1966353272db3ba08eba936652e94dcab7289Lajos Molnar    enum : uint32_t { FLEX_SIZE = _C2FlexHelper<_FlexMemberType>::FLEX_SIZE }; \
2914344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /** \endif */ \
2924344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
2934344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// @}
2944344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
2954344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/**
2964344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Global-parameter template.
2974344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
2984344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Base template to define a global setting/tuning or info based on a structure and
2994344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * an optional ParamIndex. Global parameters are not tied to a port (input or output).
3004344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
3014344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Parameters wrap structures by prepending a (parameter) header. The fields of the wrapped
3024344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * structure can be accessed directly, and constructors and potential public methods are also
3034344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * wrapped.
3044344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
3054344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \tparam T param type C2Setting, C2Tuning or C2Info
3064344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \tparam S wrapped structure
3074344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \tparam ParamIndex optional parameter index override. Must be specified for base/reused
3084344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * structures.
3094344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim */
3104344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtemplate<typename T, typename S, int ParamIndex=S::CORE_INDEX, class Flex=void>
311587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnarstruct C2_HIDE C2GlobalParam : public T, public S,
3124344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        public _C2StructCheck<S, ParamIndex, T::PARAM_KIND | T::Type::DIR_GLOBAL> {
313587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnar    _C2_CORE_INDEX_OVERRIDE(ParamIndex)
3144344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimprivate:
3154344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    typedef C2GlobalParam<T, S, ParamIndex> _Type;
3164344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
3174344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimpublic:
3184344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Wrapper around base structure's constructor.
3194344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<typename ...Args>
3204344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline C2GlobalParam(const Args(&... args)) : T(sizeof(_Type), _Type::PARAM_TYPE), S(args...) { }
3214344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
3224344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    DEFINE_CAST_OPERATORS(_Type)
3234344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim};
3244344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
3254344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/**
3264344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Global-parameter template for flexible structures.
3274344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
3284344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Base template to define a global setting/tuning or info based on a flexible structure and
3294344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * an optional ParamIndex. Global parameters are not tied to a port (input or output).
3304344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
3314344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \tparam T param type C2Setting, C2Tuning or C2Info
3324344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \tparam S wrapped flexible structure
3334344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \tparam ParamIndex optional parameter index override. Must be specified for base/reused
3344344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *         structures.
3354344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
3364344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Parameters wrap structures by prepending a (parameter) header. The fields and methods of flexible
3374344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * structures can be accessed via the m member variable; however, the constructors of the structure
3384344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * are wrapped directly. (This is because flexible types cannot be subclassed.)
3394344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim */
3404344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtemplate<typename T, typename S, int ParamIndex>
3414344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimstruct C2_HIDE C2GlobalParam<T, S, ParamIndex, IF_FLEXIBLE(S)>
3424344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    : public T, public _C2FlexStructCheck<S, ParamIndex, T::PARAM_KIND | T::Type::DIR_GLOBAL> {
3434344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimprivate:
3444344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    typedef C2GlobalParam<T, S, ParamIndex> _Type;
3454344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
3464344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Wrapper around base structure's constructor.
3474344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<typename ...Args>
3484344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline C2GlobalParam(size_t flexCount, const Args(&... args))
3494344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        : T(_Type::CalcSize(flexCount), _Type::PARAM_TYPE), m(flexCount, args...) { }
3504344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
3514344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimpublic:
3524344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    S m; ///< wrapped flexible structure
3534344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
3544344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    DEFINE_FLEXIBLE_METHODS(_Type, S)
3554344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    DEFINE_CAST_OPERATORS(_Type)
3564344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim};
3574344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
3584344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/**
3594344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Port-parameter template.
3604344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
3614344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Base template to define a port setting/tuning or info based on a structure and
3624344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * an optional ParamIndex. Port parameters are tied to a port (input or output), but not to a
3634344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * specific stream.
3644344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
3654344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \tparam T param type C2Setting, C2Tuning or C2Info
3664344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \tparam S wrapped structure
3674344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \tparam ParamIndex optional parameter index override. Must be specified for base/reused
3684344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *         structures.
3694344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
3704344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Parameters wrap structures by prepending a (parameter) header. The fields of the wrapped
3714344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * structure can be accessed directly, and constructors and potential public methods are also
3724344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * wrapped.
3734344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
3744344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * There are 3 flavors of port parameters: unspecified, input and output. Parameters with
3754344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * unspecified port expose a setPort method, and add an initial port parameter to the constructor.
3764344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim */
3774344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtemplate<typename T, typename S, int ParamIndex=S::CORE_INDEX, class Flex=void>
378587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnarstruct C2_HIDE C2PortParam : public T, public S,
3794344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        private _C2StructCheck<S, ParamIndex, T::PARAM_KIND | T::Index::DIR_UNDEFINED> {
380587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnar    _C2_CORE_INDEX_OVERRIDE(ParamIndex)
3814344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimprivate:
3824344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    typedef C2PortParam<T, S, ParamIndex> _Type;
3834344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
3844344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimpublic:
3854344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Default constructor.
3864344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline C2PortParam() : T(sizeof(_Type), _Type::PARAM_TYPE) { }
3874344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<typename ...Args>
3884344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Wrapper around base structure's constructor while specifying port/direction.
3894344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline C2PortParam(bool _output, const Args(&... args))
3904344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        : T(sizeof(_Type), _output ? output::PARAM_TYPE : input::PARAM_TYPE), S(args...) { }
3914344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Set port/direction.
3924344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline void setPort(bool output) { C2Param::setPort(output); }
3934344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
3944344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    DEFINE_CAST_OPERATORS(_Type)
3954344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
3964344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Specialization for an input port parameter.
397587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnar    struct input : public T, public S,
3984344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            public _C2StructCheck<S, ParamIndex, T::PARAM_KIND | T::Index::DIR_INPUT> {
399587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnar        _C2_CORE_INDEX_OVERRIDE(ParamIndex)
4004344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        /// Wrapper around base structure's constructor.
4014344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        template<typename ...Args>
4024344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        inline input(const Args(&... args)) : T(sizeof(_Type), input::PARAM_TYPE), S(args...) { }
4034344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
4044344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        DEFINE_CAST_OPERATORS(input)
4054344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
4064344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    };
4074344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
4084344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Specialization for an output port parameter.
409587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnar    struct output : public T, public S,
4104344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            public _C2StructCheck<S, ParamIndex, T::PARAM_KIND | T::Index::DIR_OUTPUT> {
411587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnar        _C2_CORE_INDEX_OVERRIDE(ParamIndex)
4124344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        /// Wrapper around base structure's constructor.
4134344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        template<typename ...Args>
4144344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        inline output(const Args(&... args)) : T(sizeof(_Type), output::PARAM_TYPE), S(args...) { }
4154344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
4164344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        DEFINE_CAST_OPERATORS(output)
4174344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    };
4184344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim};
4194344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
4204344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/**
4214344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Port-parameter template for flexible structures.
4224344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
4234344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Base template to define a port setting/tuning or info based on a flexible structure and
4244344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * an optional ParamIndex. Port parameters are tied to a port (input or output), but not to a
4254344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * specific stream.
4264344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
4274344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \tparam T param type C2Setting, C2Tuning or C2Info
4284344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \tparam S wrapped flexible structure
4294344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \tparam ParamIndex optional parameter index override. Must be specified for base/reused
4304344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *         structures.
4314344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
4324344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Parameters wrap structures by prepending a (parameter) header. The fields and methods of flexible
4334344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * structures can be accessed via the m member variable; however, the constructors of the structure
4344344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * are wrapped directly. (This is because flexible types cannot be subclassed.)
4354344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
4364344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * There are 3 flavors of port parameters: unspecified, input and output. Parameters with
4374344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * unspecified port expose a setPort method, and add an initial port parameter to the constructor.
4384344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim */
4394344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtemplate<typename T, typename S, int ParamIndex>
4404344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimstruct C2_HIDE C2PortParam<T, S, ParamIndex, IF_FLEXIBLE(S)>
4414344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    : public T, public _C2FlexStructCheck<S, ParamIndex, T::PARAM_KIND | T::Type::DIR_UNDEFINED> {
4424344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimprivate:
4434344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    typedef C2PortParam<T, S, ParamIndex> _Type;
4444344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
4454344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Default constructor for basic allocation: new(flexCount) P.
4464344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline C2PortParam(size_t flexCount) : T(_Type::CalcSize(flexCount), _Type::PARAM_TYPE) { }
4474344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<typename ...Args>
4484344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Wrapper around base structure's constructor while also specifying port/direction.
4494344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline C2PortParam(size_t flexCount, bool _output, const Args(&... args))
4504344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        : T(_Type::CalcSize(flexCount), _output ? output::PARAM_TYPE : input::PARAM_TYPE),
4514344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim          m(flexCount, args...) { }
4524344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
4534344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimpublic:
4544344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Set port/direction.
4554344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline void setPort(bool output) { C2Param::setPort(output); }
4564344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
4574344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    S m; ///< wrapped flexible structure
4584344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
4594344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    DEFINE_FLEXIBLE_METHODS(_Type, S)
4604344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    DEFINE_CAST_OPERATORS(_Type)
4614344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
4624344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Specialization for an input port parameter.
4634344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    struct input : public T,
4644344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            public _C2FlexStructCheck<S, ParamIndex, T::PARAM_KIND | T::Index::DIR_INPUT> {
4654344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    private:
4664344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        /// Wrapper around base structure's constructor while also specifying port/direction.
4674344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        template<typename ...Args>
4684344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        inline input(size_t flexCount, const Args(&... args))
4694344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            : T(_Type::CalcSize(flexCount), input::PARAM_TYPE), m(flexCount, args...) { }
4704344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
4714344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    public:
4724344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        S m; ///< wrapped flexible structure
4734344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
4744344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        DEFINE_FLEXIBLE_METHODS(input, S)
4754344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        DEFINE_CAST_OPERATORS(input)
4764344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    };
4774344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
4784344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Specialization for an output port parameter.
4794344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    struct output : public T,
4804344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            public _C2FlexStructCheck<S, ParamIndex, T::PARAM_KIND | T::Index::DIR_OUTPUT> {
4814344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    private:
4824344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        /// Wrapper around base structure's constructor while also specifying port/direction.
4834344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        template<typename ...Args>
4844344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        inline output(size_t flexCount, const Args(&... args))
4854344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            : T(_Type::CalcSize(flexCount), output::PARAM_TYPE), m(flexCount, args...) { }
4864344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
4874344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    public:
4884344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        S m; ///< wrapped flexible structure
4894344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
4904344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        DEFINE_FLEXIBLE_METHODS(output, S)
4914344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        DEFINE_CAST_OPERATORS(output)
4924344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    };
4934344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim};
4944344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
4954344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/**
4964344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Stream-parameter template.
4974344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
4984344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Base template to define a stream setting/tuning or info based on a structure and
4994344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * an optional ParamIndex. Stream parameters are tied to a specific stream on a port (input or
5004344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * output).
5014344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
5024344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \tparam T param type C2Setting, C2Tuning or C2Info
5034344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \tparam S wrapped structure
5044344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \tparam ParamIndex optional paramter index override. Must be specified for base/reused
5054344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *         structures.
5064344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
5074344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Parameters wrap structures by prepending a (parameter) header. The fields of the wrapped
5084344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * structure can be accessed directly, and constructors and potential public methods are also
5094344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * wrapped.
5104344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
5114344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * There are 3 flavors of stream parameters: unspecified port, input and output. All of these expose
5124344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * a setStream method and an extra initial streamID parameter for the constructor. Moreover,
5134344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * parameters with unspecified port expose a setPort method, and add an additional initial port
5144344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * parameter to the constructor.
5154344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim */
5164344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtemplate<typename T, typename S, int ParamIndex=S::CORE_INDEX, class Flex=void>
517587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnarstruct C2_HIDE C2StreamParam : public T, public S,
5184344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        private _C2StructCheck<S, ParamIndex,
5194344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim                T::PARAM_KIND | T::Index::IS_STREAM_FLAG | T::Index::DIR_UNDEFINED> {
520587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnar    _C2_CORE_INDEX_OVERRIDE(ParamIndex)
5214344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimprivate:
5224344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    typedef C2StreamParam<T, S, ParamIndex> _Type;
5234344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
5244344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimpublic:
5254344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Default constructor. Port/direction and stream-ID is undefined.
5264344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline C2StreamParam() : T(sizeof(_Type), _Type::PARAM_TYPE) { }
5274344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Wrapper around base structure's constructor while also specifying port/direction and
5284344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// stream-ID.
5294344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<typename ...Args>
5304344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline C2StreamParam(bool _output, unsigned stream, const Args(&... args))
5314344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        : T(sizeof(_Type), _output ? output::PARAM_TYPE : input::PARAM_TYPE, stream),
5324344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim          S(args...) { }
5334344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Set port/direction.
5344344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline void setPort(bool output) { C2Param::setPort(output); }
5354344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Set stream-id. \retval true if the stream-id was successfully set.
5364344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline bool setStream(unsigned stream) { return C2Param::setStream(stream); }
5374344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
5384344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    DEFINE_CAST_OPERATORS(_Type)
5394344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
5404344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Specialization for an input stream parameter.
541587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnar    struct input : public T, public S,
5424344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            public _C2StructCheck<S, ParamIndex,
5434344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim                    T::PARAM_KIND | T::Index::IS_STREAM_FLAG | T::Type::DIR_INPUT> {
544587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnar        _C2_CORE_INDEX_OVERRIDE(ParamIndex)
545587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnar
5464344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        /// Default constructor. Stream-ID is undefined.
5474344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        inline input() : T(sizeof(_Type), input::PARAM_TYPE) { }
5484344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        /// Wrapper around base structure's constructor while also specifying stream-ID.
5494344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        template<typename ...Args>
5504344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        inline input(unsigned stream, const Args(&... args))
5514344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            : T(sizeof(_Type), input::PARAM_TYPE, stream), S(args...) { }
5524344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        /// Set stream-id. \retval true if the stream-id was successfully set.
5534344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        inline bool setStream(unsigned stream) { return C2Param::setStream(stream); }
5544344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
5554344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        DEFINE_CAST_OPERATORS(input)
5564344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    };
5574344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
5584344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Specialization for an output stream parameter.
559587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnar    struct output : public T, public S,
5604344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            public _C2StructCheck<S, ParamIndex,
5614344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim                    T::PARAM_KIND | T::Index::IS_STREAM_FLAG | T::Type::DIR_OUTPUT> {
562587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnar        _C2_CORE_INDEX_OVERRIDE(ParamIndex)
563587c47f10c14b7d24efdf9f36bebc1d62c24bd49Lajos Molnar
5644344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        /// Default constructor. Stream-ID is undefined.
5654344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        inline output() : T(sizeof(_Type), output::PARAM_TYPE) { }
5664344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        /// Wrapper around base structure's constructor while also specifying stream-ID.
5674344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        template<typename ...Args>
5684344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        inline output(unsigned stream, const Args(&... args))
5694344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            : T(sizeof(_Type), output::PARAM_TYPE, stream), S(args...) { }
5704344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        /// Set stream-id. \retval true if the stream-id was successfully set.
5714344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        inline bool setStream(unsigned stream) { return C2Param::setStream(stream); }
5724344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
5734344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        DEFINE_CAST_OPERATORS(output)
5744344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    };
5754344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim};
5764344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
5774344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/**
5784344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Stream-parameter template for flexible structures.
5794344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
5804344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Base template to define a stream setting/tuning or info based on a flexible structure and
5814344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * an optional ParamIndex. Stream parameters are tied to a specific stream on a port (input or
5824344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * output).
5834344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
5844344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \tparam T param type C2Setting, C2Tuning or C2Info
5854344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \tparam S wrapped flexible structure
5864344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \tparam ParamIndex optional parameter index override. Must be specified for base/reused
5874344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *         structures.
5884344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
5894344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Parameters wrap structures by prepending a (parameter) header. The fields and methods of flexible
5904344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * structures can be accessed via the m member variable; however, the constructors of the structure
5914344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * are wrapped directly. (This is because flexible types cannot be subclassed.)
5924344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
5934344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * There are 3 flavors of stream parameters: unspecified port, input and output. All of these expose
5944344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * a setStream method and an extra initial streamID parameter for the constructor. Moreover,
5954344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * parameters with unspecified port expose a setPort method, and add an additional initial port
5964344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * parameter to the constructor.
5974344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim */
5984344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtemplate<typename T, typename S, int ParamIndex>
5994344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimstruct C2_HIDE C2StreamParam<T, S, ParamIndex, IF_FLEXIBLE(S)>
6004344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    : public T,
6014344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim      public _C2FlexStructCheck<S, ParamIndex,
6024344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim              T::PARAM_KIND | T::Index::IS_STREAM_FLAG | T::Index::DIR_UNDEFINED> {
6034344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimprivate:
6044344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    typedef C2StreamParam<T, S, ParamIndex> _Type;
6054344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Default constructor. Port/direction and stream-ID is undefined.
6064344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline C2StreamParam(size_t flexCount) : T(_Type::CalcSize(flexCount), _Type::PARAM_TYPE, 0u) { }
6074344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Wrapper around base structure's constructor while also specifying port/direction and
6084344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// stream-ID.
6094344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<typename ...Args>
6104344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline C2StreamParam(size_t flexCount, bool _output, unsigned stream, const Args(&... args))
6114344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        : T(_Type::CalcSize(flexCount), _output ? output::PARAM_TYPE : input::PARAM_TYPE, stream),
6124344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim          m(flexCount, args...) { }
6134344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
6144344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimpublic:
6154344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    S m; ///< wrapped flexible structure
6164344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
6174344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Set port/direction.
6184344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline void setPort(bool output) { C2Param::setPort(output); }
6194344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Set stream-id. \retval true if the stream-id was successfully set.
6204344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline bool setStream(unsigned stream) { return C2Param::setStream(stream); }
6214344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
6224344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    DEFINE_FLEXIBLE_METHODS(_Type, S)
6234344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    DEFINE_CAST_OPERATORS(_Type)
6244344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
6254344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Specialization for an input stream parameter.
6264344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    struct input : public T,
6274344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            public _C2FlexStructCheck<S, ParamIndex,
6284344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim                    T::PARAM_KIND | T::Index::IS_STREAM_FLAG | T::Type::DIR_INPUT> {
6294344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    private:
6304344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        /// Default constructor. Stream-ID is undefined.
6314344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        inline input(size_t flexCount) : T(_Type::CalcSize(flexCount), input::PARAM_TYPE) { }
6324344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        /// Wrapper around base structure's constructor while also specifying stream-ID.
6334344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        template<typename ...Args>
6344344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        inline input(size_t flexCount, unsigned stream, const Args(&... args))
6354344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            : T(_Type::CalcSize(flexCount), input::PARAM_TYPE, stream), m(flexCount, args...) { }
6364344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
6374344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    public:
6384344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        S m; ///< wrapped flexible structure
6394344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
6404344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        /// Set stream-id. \retval true if the stream-id was successfully set.
6414344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        inline bool setStream(unsigned stream) { return C2Param::setStream(stream); }
6424344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
6434344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        DEFINE_FLEXIBLE_METHODS(input, S)
6444344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        DEFINE_CAST_OPERATORS(input)
6454344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    };
6464344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
6474344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Specialization for an output stream parameter.
6484344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    struct output : public T,
6494344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            public _C2FlexStructCheck<S, ParamIndex,
6504344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim                    T::PARAM_KIND | T::Index::IS_STREAM_FLAG | T::Type::DIR_OUTPUT> {
6514344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    private:
6524344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        /// Default constructor. Stream-ID is undefined.
6534344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        inline output(size_t flexCount) : T(_Type::CalcSize(flexCount), output::PARAM_TYPE) { }
6544344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        /// Wrapper around base structure's constructor while also specifying stream-ID.
6554344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        template<typename ...Args>
6564344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        inline output(size_t flexCount, unsigned stream, const Args(&... args))
6574344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            : T(_Type::CalcSize(flexCount), output::PARAM_TYPE, stream), m(flexCount, args...) { }
6584344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
6594344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    public:
6604344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        S m; ///< wrapped flexible structure
6614344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
6624344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        /// Set stream-id. \retval true if the stream-id was successfully set.
6634344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        inline bool setStream(unsigned stream) { return C2Param::setStream(stream); }
6644344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
6654344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        DEFINE_FLEXIBLE_METHODS(output, S)
6664344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        DEFINE_CAST_OPERATORS(output)
6674344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    };
6684344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim};
6694344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
6704344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/* ======================== SIMPLE VALUE PARAMETERS ======================== */
6714344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
6724344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/**
6734344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \ingroup internal
6744344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * A structure template encapsulating a single element with default constructors and no core-index.
6754344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim */
6764344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtemplate<typename T>
6774344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimstruct C2SimpleValueStruct {
6784344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    T value; ///< simple value of the structure
6794344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    // Default constructor.
6804344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline C2SimpleValueStruct() = default;
6814344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    // Constructor with an initial value.
6824344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline C2SimpleValueStruct(T value) : value(value) {}
6834344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    DEFINE_BASE_C2STRUCT(SimpleValue)
6844344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim};
6854344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
6864344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim// TODO: move this and next to some generic place
6874344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/**
6884344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Interface to a block of (mapped) memory containing an array of some type (T).
6894344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim */
6904344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtemplate<typename T>
6914344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimstruct C2MemoryBlock {
6924344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// \returns the number of elements in this block.
6934344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    virtual size_t size() const = 0;
6944344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// \returns a const pointer to the start of this block. Care must be taken to not read outside
6954344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// the block.
6964344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    virtual const T *data() const = 0; // TODO: should this be friend access only in some C2Memory module?
6974344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// \returns a pointer to the start of this block. Care must be taken to not read or write
6984344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// outside the block.
6995d68ad843c75e22a6163a9fe4941e8e861a1016eLajos Molnar    inline T *data() { return const_cast<T*>(const_cast<const C2MemoryBlock*>(this)->data()); }
7005d68ad843c75e22a6163a9fe4941e8e861a1016eLajos Molnar
7014344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimprotected:
7024344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    // TODO: for now it should never be deleted as C2MemoryBlock
7034344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    virtual ~C2MemoryBlock() = default;
7044344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim};
7054344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
7064344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/**
7074344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Interface to a block of memory containing a constant (constexpr) array of some type (T).
7084344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim */
7094344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtemplate<typename T>
7104344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimstruct C2ConstMemoryBlock : public C2MemoryBlock<T> {
7114344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    virtual const T * data() const { return _mData; }
7124344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    virtual size_t size() const { return _mSize; }
7134344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
7144344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Constructor.
7154344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<unsigned N>
7164344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline constexpr C2ConstMemoryBlock(const T(&init)[N]) : _mData(init), _mSize(N) {}
7174344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
7184344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimprivate:
7194344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    const T *_mData;
7204344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    const size_t _mSize;
7214344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim};
7224344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
7234344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// \addtogroup internal
7244344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// @{
7254344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
7264344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// Helper class to initialize flexible arrays with various initalizers.
7274344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimstruct _C2ValueArrayHelper {
7284344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    // char[]-s are used as null terminated strings, so the last element is never inited.
7294344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
7304344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Initialize a flexible array using a constexpr memory block.
7314344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<typename T>
7324344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    static void init(T(&array)[], size_t arrayLen, const C2MemoryBlock<T> &block) {
7334344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        // reserve last element for terminal 0 for strings
7344344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        if (arrayLen && std::is_same<T, char>::value) {
7354344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            --arrayLen;
7364344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        }
7374344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        if (block.data()) {
7384344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            memcpy(array, block.data(), std::min(arrayLen, block.size()) * sizeof(T));
7394344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        }
7404344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    }
7414344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
7424344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Initialize a flexible array using an initializer list.
7434344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<typename T>
7444344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    static void init(T(&array)[], size_t arrayLen, const std::initializer_list<T> &init) {
7454344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        size_t ix = 0;
7464344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        // reserve last element for terminal 0 for strings
7474344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        if (arrayLen && std::is_same<T, char>::value) {
7484344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            --arrayLen;
7494344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        }
7504344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        for (const T &item : init) {
7514344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            if (ix == arrayLen) {
7524344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim                break;
7534344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            }
7544344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            array[ix++] = item;
7554344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        }
7564344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    }
7574344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
7588849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar    /// Initialize a flexible array using a vector.
7598849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar    template<typename T>
7608849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar    static void init(T(&array)[], size_t arrayLen, const std::vector<T> &init) {
7618849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar        size_t ix = 0;
7628849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar        // reserve last element for terminal 0 for strings
7638849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar        if (arrayLen && std::is_same<T, char>::value) {
7648849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar            --arrayLen;
7658849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar        }
7668849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar        for (const T &item : init) {
7678849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar            if (ix == arrayLen) {
7688849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar                break;
7698849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar            }
7708849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar            array[ix++] = item;
7718849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar        }
7728849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar    }
7738849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar
7744344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Initialize a flexible array using another flexible array.
7754344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<typename T, unsigned N>
7764344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    static void init(T(&array)[], size_t arrayLen, const T(&str)[N]) {
7774344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        // reserve last element for terminal 0 for strings
7784344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        if (arrayLen && std::is_same<T, char>::value) {
7794344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim            --arrayLen;
7804344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        }
7814344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        if (arrayLen) {
78246b790622fc4e1d90966f41f5e7f5ee3a3b1ca0aLajos Molnar            memcpy(array, str, std::min(arrayLen, (size_t)N) * sizeof(T));
7834344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        }
7844344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    }
7854344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim};
7864344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
7874344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/**
7884344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Specialization for a flexible blob and string arrays. A structure template encapsulating a single
7894344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * flexible array member with default flexible constructors and no core-index. This type cannot be
7904344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * constructed on its own as it's size is 0.
7914344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
7924344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \internal This is different from C2SimpleArrayStruct<T[]> simply because its member has the name
7934344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * as value to reflect this is a single value.
7944344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim */
7954344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtemplate<typename T>
7964344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimstruct C2SimpleValueStruct<T[]> {
7974344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    static_assert(std::is_same<T, char>::value || std::is_same<T, uint8_t>::value,
7984344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim                  "C2SimpleValueStruct<T[]> is only for BLOB or STRING");
7994344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    T value[];
8004344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
8014344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline C2SimpleValueStruct() = default;
8024344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    DEFINE_BASE_C2STRUCT(SimpleValue)
8034344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    FLEX(C2SimpleValueStruct, value)
8044344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
8054344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimprivate:
8064344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline C2SimpleValueStruct(size_t flexCount, const C2MemoryBlock<T> &block) {
8074344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        _C2ValueArrayHelper::init(value, flexCount, block);
8084344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    }
8094344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
8104344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline C2SimpleValueStruct(size_t flexCount, const std::initializer_list<T> &init) {
8114344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        _C2ValueArrayHelper::init(value, flexCount, init);
8124344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    }
8134344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
8148849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar    inline C2SimpleValueStruct(size_t flexCount, const std::vector<T> &init) {
8158849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar        _C2ValueArrayHelper::init(value, flexCount, init);
8168849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar    }
8178849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar
8184344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<unsigned N>
8194344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline C2SimpleValueStruct(size_t flexCount, const T(&init)[N]) {
8204344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        _C2ValueArrayHelper::init(value, flexCount, init);
8214344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    }
8224344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim};
8234344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
8244344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// @}
8254344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
8264344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/**
8274344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * A structure template encapsulating a single flexible array element of a specific type (T) with
8284344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * default constructors and no core-index. This type cannot be constructed on its own as it's size
8294344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * is 0. Instead, it is meant to be used as a parameter, e.g.
8304344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
8314344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *   typedef C2StreamParam<C2Info, C2SimpleArrayStruct<C2MyFancyStruct>,
8324344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *           kParamIndexMyFancyArrayStreamParam> C2MyFancyArrayStreamInfo;
8334344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim */
8344344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtemplate<typename T>
8354344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimstruct C2SimpleArrayStruct {
8364344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    static_assert(!std::is_same<T, char>::value && !std::is_same<T, uint8_t>::value,
8374344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim                  "use C2SimpleValueStruct<T[]> is for BLOB or STRING");
8384344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
8394344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    T values[]; ///< array member
8404344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Default constructor
8414344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline C2SimpleArrayStruct() = default;
8424344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    DEFINE_BASE_FLEX_C2STRUCT(SimpleArray, values)
8434344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    //FLEX(C2SimpleArrayStruct, values)
8444344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
8454344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimprivate:
8464344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Construct from a C2MemoryBlock.
8474344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Used only by the flexible parameter allocators (AllocUnique & AllocShared).
8484344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline C2SimpleArrayStruct(size_t flexCount, const C2MemoryBlock<T> &block) {
8494344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        _C2ValueArrayHelper::init(values, flexCount, block);
8504344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    }
8514344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
8524344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Construct from an initializer list.
8534344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Used only by the flexible parameter allocators (AllocUnique & AllocShared).
8544344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline C2SimpleArrayStruct(size_t flexCount, const std::initializer_list<T> &init) {
8554344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        _C2ValueArrayHelper::init(values, flexCount, init);
8564344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    }
8574344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
8588849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar    /// Construct from an vector.
8598849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar    /// Used only by the flexible parameter allocators (AllocUnique & AllocShared).
8608849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar    inline C2SimpleArrayStruct(size_t flexCount, const std::vector<T> &init) {
8618849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar        _C2ValueArrayHelper::init(values, flexCount, init);
8628849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar    }
8638849f0398e866ce2af9b71be11023f85b2c6d0a2Lajos Molnar
8644344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Construct from another flexible array.
8654344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    /// Used only by the flexible parameter allocators (AllocUnique & AllocShared).
8664344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    template<unsigned N>
8674344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    inline C2SimpleArrayStruct(size_t flexCount, const T(&init)[N]) {
8684344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim        _C2ValueArrayHelper::init(values, flexCount, init);
8694344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim    }
8704344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim};
8714344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
8724344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/**
8734344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * \addtogroup simplevalue Simple value and array structures.
8744344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * @{
8754344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
8764344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Simple value structures.
8774344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
8784344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * Structures containing a single simple value. These can be reused to easily define simple
8794344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * parameters of various types:
8804344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
8814344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *   typedef C2PortParam<C2Tuning, C2Int32Value, kParamIndexMyIntegerPortParam>
8824344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *           C2MyIntegerPortParamTuning;
8834344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim *
8844344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim * They contain a single member (value or values) that is described as "value" or "values".
8855528a2a16628fec50ebb1f42b5fecf4589aa5233Lajos Molnar *
8865528a2a16628fec50ebb1f42b5fecf4589aa5233Lajos Molnar * These structures don't define a core index, and as such, they cannot be used in structure
8875528a2a16628fec50ebb1f42b5fecf4589aa5233Lajos Molnar * declarations. Use type[] instead, such as int32_t field[].
8884344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim */
8894344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// A 32-bit signed integer parameter in value, described as "value"
8904344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtypedef C2SimpleValueStruct<int32_t> C2Int32Value;
8914344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// A 32-bit signed integer array parameter in values, described as "values"
8924344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtypedef C2SimpleArrayStruct<int32_t> C2Int32Array;
8934344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// A 32-bit unsigned integer parameter in value, described as "value"
8944344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtypedef C2SimpleValueStruct<uint32_t> C2Uint32Value;
8954344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// A 32-bit unsigned integer array parameter in values, described as "values"
8964344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtypedef C2SimpleArrayStruct<uint32_t> C2Uint32Array;
8974344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// A 64-bit signed integer parameter in value, described as "value"
8984344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtypedef C2SimpleValueStruct<int64_t> C2Int64Value;
8994344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// A 64-bit signed integer array parameter in values, described as "values"
9004344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtypedef C2SimpleArrayStruct<int64_t> C2Int64Array;
9014344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// A 64-bit unsigned integer parameter in value, described as "value"
9024344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtypedef C2SimpleValueStruct<uint64_t> C2Uint64Value;
9034344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// A 64-bit unsigned integer array parameter in values, described as "values"
9044344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtypedef C2SimpleArrayStruct<uint64_t> C2Uint64Array;
9054344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// A float parameter in value, described as "value"
9064344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtypedef C2SimpleValueStruct<float> C2FloatValue;
9074344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// A float array parameter in values, described as "values"
9084344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtypedef C2SimpleArrayStruct<float> C2FloatArray;
9094344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// A blob flexible parameter in value, described as "value"
9104344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtypedef C2SimpleValueStruct<uint8_t[]> C2BlobValue;
9114344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// A string flexible parameter in value, described as "value"
9124344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtypedef C2SimpleValueStruct<char[]> C2StringValue;
9134344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
9144344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtemplate<typename T>
9151cbff72e1f2998f175fe23b79737e4cdb8ddd33aLajos Molnarconst std::vector<C2FieldDescriptor> C2SimpleValueStruct<T>::FieldList() {
9161cbff72e1f2998f175fe23b79737e4cdb8ddd33aLajos Molnar    return { DESCRIBE_C2FIELD(value, "value") };
9171cbff72e1f2998f175fe23b79737e4cdb8ddd33aLajos Molnar}
9184344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtemplate<typename T>
9191cbff72e1f2998f175fe23b79737e4cdb8ddd33aLajos Molnarconst std::vector<C2FieldDescriptor> C2SimpleValueStruct<T[]>::FieldList() {
9201cbff72e1f2998f175fe23b79737e4cdb8ddd33aLajos Molnar    return { DESCRIBE_C2FIELD(value, "value") };
9211cbff72e1f2998f175fe23b79737e4cdb8ddd33aLajos Molnar}
9224344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kimtemplate<typename T>
9231cbff72e1f2998f175fe23b79737e4cdb8ddd33aLajos Molnarconst std::vector<C2FieldDescriptor> C2SimpleArrayStruct<T>::FieldList() {
9241cbff72e1f2998f175fe23b79737e4cdb8ddd33aLajos Molnar    return { DESCRIBE_C2FIELD(values, "values") };
9251cbff72e1f2998f175fe23b79737e4cdb8ddd33aLajos Molnar}
9264344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
9274344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// @}
9284344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
9294344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim/// @}
9304344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim
9314344f091aebaf3aee3ff062a95a05273bd2b1c57Wonsik Kim#endif  // C2PARAM_DEF_H_
932