129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/*
229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * Copyright (C) 2016 The Android Open Source Project
329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * Licensed under the Apache License, Version 2.0 (the "License");
529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * you may not use this file except in compliance with the License.
629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * You may obtain a copy of the License at
729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      http://www.apache.org/licenses/LICENSE-2.0
929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
1029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * Unless required by applicable law or agreed to in writing, software
1129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * distributed under the License is distributed on an "AS IS" BASIS,
1229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * See the License for the specific language governing permissions and
1429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * limitations under the License.
1529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar */
1629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
1729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#ifndef C2PARAM_H_
1829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#define C2PARAM_H_
1929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
2029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#include <C2.h>
2129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
2229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#include <stdbool.h>
2329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#include <stdint.h>
2429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
2529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#include <algorithm>
2629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#include <list>
2729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#include <string>
2829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#include <type_traits>
2929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
3029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#define C2_PACK __attribute__((packed))
3129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
3229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarnamespace android {
3329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
3429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/// \addtogroup Parameters
3529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/// @{
3629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
3729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/// \defgroup internal Internal helpers.
3829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
3929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/*!
4029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * \file
4129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * PARAMETERS: SETTINGs, TUNINGs, and INFOs
4229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * ===
4329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
4429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * These represent miscellaneous control and metadata information and are likely copied into
4529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * kernel space. Therefore, these are C-like structures designed to carry just a small amount of
4629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * information. We are using C++ to be able to add constructors, as well as non-virtual and class
4729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * methods.
4829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
4929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * ==Specification details:
5029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
5129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * Restrictions:
5229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *   - must be POD struct, e.g. no vtable (no virtual destructor)
5329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *   - must have the same size in 64-bit and 32-bit mode (no size_t)
5429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *   - as such, no pointer members
5529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
5629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * Behavior:
5729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * - Params can be global (not related to input or output), related to input or output,
5829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *   or related to an input/output stream.
5929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * - All params are queried/set using a unique param index, which incorporates a potential stream
6029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *   index and/or port.
6129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * - Querying (supported) params MUST never fail.
6229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * - All params MUST have default values.
6329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * - If some fields have "unsupported" or "invalid" values during setting, this SHOULD be
6429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *   communicated to the app.
6529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *   a) Ideally, this should be avoided.  When setting parameters, in general, component should do
6629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *     "best effort" to apply all settings. It should change "invalid/unsupported" values to the
6729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *     nearest supported values.
6829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *   - This is communicated to the client by changing the source values in tune()/
6929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *     configure().
7029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *   b) If falling back to a supported value is absolutely impossible, the component SHALL return
7129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *     an error for the specific setting, but should continue to apply other settings.
7229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *     TODO: this currently may result in unintended results.
7329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
7429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * **NOTE:** unlike OMX, params are not versioned. Instead, a new struct with new base index
7529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * SHALL be added as new versions are required.
7629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
7729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * The proper subtype (Setting, Info or Param) is incorporated into the class type. Define structs
7829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * to define multiple subtyped versions of related parameters.
7929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
8029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * ==Implementation details:
8129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
8229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * - Use macros to define parameters
8329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * - All parameters must have a default constructor
8429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *   - This is only used for instantiating the class in source (e.g. will not be used
8529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *     when building a parameter by the framework from key/value pairs.)
8629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar */
8729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
8829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/// \ingroup internal
8929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarstruct _C2ParamManipulator;
9029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
9129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/**
9229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * Parameter base class.
9329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar */
9429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarstruct C2Param {
9529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // param index encompasses the following:
9629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    //
9729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // - type (setting, tuning, info, struct)
9829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // - vendor extension flag
9929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // - flexible parameter flag
10029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // - direction (global, input, output)
10129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // - stream flag
10229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // - stream ID (usually 0)
10329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    //
10429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // layout:
10529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    //
10629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    //      +------+-----+---+------+--------+----|------+--------------+
10729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    //      | kind | dir | - |stream|streamID|flex|vendor|  base index  |
10829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    //      +------+-----+---+------+--------+----+------+--------------+
10929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    //  bit: 31..30 29.28       25   24 .. 17  16    15   14    ..     0
11029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    //
11129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarpublic:
11229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /**
11329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * C2Param kinds, usable as bitmaps.
11429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     */
11529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    enum Kind : uint32_t {
11629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        NONE    = 0,
11729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        STRUCT  = (1 << 0),
11829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        INFO    = (1 << 1),
11929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        SETTING = (1 << 2),
12029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        TUNING  = (1 << 3) | SETTING, // tunings are settings
12129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    };
12229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
12329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /**
12429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * base index (including the vendor extension bit) is a global index for
12529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * C2 parameter structs. (e.g. the same indices cannot be reused for different
12629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * structs for different components).
12729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     */
12829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    struct BaseIndex {
12929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    protected:
13029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        enum : uint32_t {
13129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            kTypeMask      = 0xC0000000,
13229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            kTypeStruct    = 0x00000000,
13329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            kTypeTuning    = 0x40000000,
13429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            kTypeSetting   = 0x80000000,
13529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            kTypeInfo      = 0xC0000000,
13629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
13729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            kDirMask       = 0x30000000,
13829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            kDirGlobal     = 0x20000000,
13929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            kDirUndefined  = 0x30000000, // MUST have all bits set
14029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            kDirInput      = 0x00000000,
14129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            kDirOutput     = 0x10000000,
14229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
14329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            kStreamFlag    = 0x02000000,
14429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            kStreamIdMask  = 0x01FE0000,
14529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            kStreamIdShift = 17,
14629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            kStreamIdMax   = kStreamIdMask >> kStreamIdShift,
14729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            kStreamMask    = kStreamFlag | kStreamIdMask,
14829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
14929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            kFlexibleFlag  = 0x00010000,
15029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            kVendorFlag    = 0x00008000,
15129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            kParamMask     = 0x0000FFFF,
15229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            kBaseMask      = kParamMask | kFlexibleFlag,
15329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        };
15429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
15529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    public:
15629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        enum : uint32_t {
15729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            kVendorStart = kVendorFlag, ///< vendor structs SHALL start after this
15829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            _kFlexibleFlag = kFlexibleFlag, // TODO: this is only needed for testing
15929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        };
16029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
16129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        /// constructor/conversion from uint32_t
16229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline BaseIndex(uint32_t index) : mIndex(index) { }
16329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
16429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        // no conversion from uint64_t
16529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline BaseIndex(uint64_t index) = delete;
16629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
16729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        /// returns true iff this is a vendor extension parameter
16829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline bool isVendor() const { return mIndex & kVendorFlag; }
16929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
17029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        /// returns true iff this is a flexible parameter (with variable size)
17129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline bool isFlexible() const { return mIndex & kFlexibleFlag; }
17229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
17329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        /// returns the base type: the index for the underlying struct
17429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline unsigned int baseIndex() const { return mIndex & kBaseMask; }
17529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
17629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        /// returns the param index for the underlying struct
17729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline unsigned int paramIndex() const { return mIndex & kParamMask; }
17829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
17929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        DEFINE_FIELD_BASED_COMPARISON_OPERATORS(BaseIndex, mIndex)
18029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
18129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    protected:
18229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        uint32_t mIndex;
18329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    };
18429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
18529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /**
18629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * type encompasses the parameter kind (tuning, setting, info), whether the
18729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * parameter is global, input or output, and whether it is for a stream.
18829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     */
18929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    struct Type : public BaseIndex {
19029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        /// returns true iff this is a global parameter (not for input nor output)
19129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline bool isGlobal() const { return (mIndex & kDirMask) == kDirGlobal; }
19229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        /// returns true iff this is an input or input stream parameter
19329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline bool forInput() const { return (mIndex & kDirMask) == kDirInput; }
19429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        /// returns true iff this is an output or output stream parameter
19529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline bool forOutput() const { return (mIndex & kDirMask) == kDirOutput; }
19629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
19729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        /// returns true iff this is a stream parameter
19829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline bool forStream() const { return mIndex & kStreamFlag; }
19929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        /// returns true iff this is a port (input or output) parameter
20029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline bool forPort() const   { return !forStream() && !isGlobal(); }
20129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
20229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        /// returns the parameter type: the parameter index without the stream ID
20329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline uint32_t type() const { return mIndex & (~kStreamIdMask); }
20429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
20529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        /// return the kind of this param
20629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline Kind kind() const {
20729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            switch (mIndex & kTypeMask) {
20829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar                case kTypeStruct: return STRUCT;
20929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar                case kTypeInfo: return INFO;
21029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar                case kTypeSetting: return SETTING;
21129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar                case kTypeTuning: return TUNING;
21229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar                default: return NONE; // should not happen
21329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            }
21429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        }
21529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
21629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        /// constructor/conversion from uint32_t
21729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline Type(uint32_t index) : BaseIndex(index) { }
21829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
21929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        // no conversion from uint64_t
22029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline Type(uint64_t index) = delete;
22129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
22229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    private:
22329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        friend struct C2Param;   // for setPort()
22429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        friend struct C2Tuning;  // for kTypeTuning
22529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        friend struct C2Setting; // for kTypeSetting
22629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        friend struct C2Info;    // for kTypeInfo
22729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        // for kDirGlobal
22829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        template<typename T, typename S, int I, class F> friend struct C2GlobalParam;
22929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        template<typename T, typename S, int I, class F> friend struct C2PortParam;   // for kDir*
23029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        template<typename T, typename S, int I, class F> friend struct C2StreamParam; // for kDir*
23129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        friend struct _C2ParamInspector; // for testing
23229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
23329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        /**
23429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar         * Sets the port/stream direction.
23529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar         * @return true on success, false if could not set direction (e.g. it is global param).
23629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar         */
23729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline bool setPort(bool output) {
23829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            if (isGlobal()) {
23929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar                return false;
24029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            } else {
24129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar                mIndex = (mIndex & ~kDirMask) | (output ? kDirOutput : kDirInput);
24229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar                return true;
24329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            }
24429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        }
24529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    };
24629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
24729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /**
24829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * index encompasses all remaining information: basically the stream ID.
24929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     */
25029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    struct Index : public Type {
25129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        /// returns the index as uint32_t
25229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline operator uint32_t() const { return mIndex; }
25329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
25429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        /// constructor/conversion from uint32_t
25529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline Index(uint32_t index) : Type(index) { }
25629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
25729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        // no conversion from uint64_t
25829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline Index(uint64_t index) = delete;
25929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
26029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        /// returns the stream ID or ~0 if not a stream
26129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline unsigned stream() const {
26229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            return forStream() ? rawStream() : ~0U;
26329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        }
26429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
26529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    private:
26629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        friend struct C2Param;           // for setStream, makeStreamId, isValid
26729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        friend struct _C2ParamInspector; // for testing
26829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
26929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        /**
27029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar         * @return true if the type is valid, e.g. direction is not undefined AND
27129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar         * stream is 0 if not a stream param.
27229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar         */
27329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline bool isValid() const {
27429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            // there is no Type::isValid (even though some of this check could be
27529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            // performed on types) as this is only used on index...
27629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            return (forStream() ? rawStream() < kStreamIdMax : rawStream() == 0)
27729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar                    && (mIndex & kDirMask) != kDirUndefined;
27829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        }
27929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
28029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        /// returns the raw stream ID field
28129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline unsigned rawStream() const {
28229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            return (mIndex & kStreamIdMask) >> kStreamIdShift;
28329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        }
28429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
28529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        /// returns the streamId bitfield for a given |stream|. If stream is invalid,
28629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        /// returns an invalid bitfield.
28729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline static uint32_t makeStreamId(unsigned stream) {
28829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            // saturate stream ID (max value is invalid)
28929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            if (stream > kStreamIdMax) {
29029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar                stream = kStreamIdMax;
29129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            }
29229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            return (stream << kStreamIdShift) & kStreamIdMask;
29329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        }
29429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
29529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        /**
29629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar         * Sets the stream index.
29729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar         * \return true on success, false if could not set index (e.g. not a stream param).
29829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar         */
29929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        inline bool setStream(unsigned stream) {
30029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            if (forStream()) {
30129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar                mIndex = (mIndex & ~kStreamIdMask) | makeStreamId(stream);
30229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar                return this->stream() < kStreamIdMax;
30329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            }
30429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            return false;
30529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        }
30629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    };
30729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
30829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarpublic:
30929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // public getters for Index methods
31029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
31129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// returns true iff this is a vendor extension parameter
31229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline bool isVendor() const { return _mIndex.isVendor(); }
31329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// returns true iff this is a flexible parameter
31429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline bool isFlexible() const { return _mIndex.isFlexible(); }
31529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// returns true iff this is a global parameter (not for input nor output)
31629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline bool isGlobal() const { return _mIndex.isGlobal(); }
31729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// returns true iff this is an input or input stream parameter
31829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline bool forInput() const { return _mIndex.forInput(); }
31929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// returns true iff this is an output or output stream parameter
32029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline bool forOutput() const { return _mIndex.forOutput(); }
32129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
32229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// returns true iff this is a stream parameter
32329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline bool forStream() const { return _mIndex.forStream(); }
32429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// returns true iff this is a port (input or output) parameter
32529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline bool forPort() const   { return _mIndex.forPort(); }
32629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
32729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// returns the stream ID or ~0 if not a stream
32829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline unsigned stream() const { return _mIndex.stream(); }
32929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
33029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// returns the parameter type: the parameter index without the stream ID
33129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline uint32_t type() const { return _mIndex.type(); }
33229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
33329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// returns the kind of this parameter
33429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline Kind kind() const { return _mIndex.kind(); }
33529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
33629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// returns the size of the parameter or 0 if the parameter is invalid
33729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline size_t size() const { return _mSize; }
33829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
33929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// returns true iff the parameter is valid
34029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline operator bool() const { return _mIndex.isValid() && _mSize > 0; }
34129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
34229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// returns true iff the parameter is invalid
34329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline bool operator!() const { return !operator bool(); }
34429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
34529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // equality is done by memcmp (use equals() to prevent any overread)
34629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline bool operator==(const C2Param &o) const {
34729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        return equals(o) && memcmp(this, &o, _mSize) == 0;
34829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    }
34929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline bool operator!=(const C2Param &o) const { return !operator==(o); }
35029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
35129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// safe(r) type cast from pointer and size
35229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline static C2Param* From(void *addr, size_t len) {
35329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        // _mSize must fit into size
35429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        if (len < sizeof(_mSize) + offsetof(C2Param, _mSize)) {
35529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            return nullptr;
35629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        }
35729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        // _mSize must match length
35829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        C2Param *param = (C2Param*)addr;
35929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        if (param->_mSize != len) {
36029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            return nullptr;
36129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        }
36229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        return param;
36329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    }
36429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
36529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#if 0
36629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename P, class=decltype(C2Param(P()))>
36729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    P *As() { return P::From(this); }
36829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename P>
36929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    const P *As() const { return const_cast<const P*>(P::From(const_cast<C2Param*>(this))); }
37029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#endif
37129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
37229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarprotected:
37329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// sets the stream field. Returns true iff successful.
37429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline bool setStream(unsigned stream) {
37529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        return _mIndex.setStream(stream);
37629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    }
37729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
37829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// sets the port (direction). Returns true iff successful.
37929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline bool setPort(bool output) {
38029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        return _mIndex.setPort(output);
38129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    }
38229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
38329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarpublic:
38429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// invalidate this parameter. There is no recovery from this call; e.g. parameter
38529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// cannot be 'corrected' to be valid.
38629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline void invalidate() { _mSize = 0; }
38729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
38829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // if other is the same kind of (valid) param as this, copy it into this and return true.
38929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // otherwise, do not copy anything, and return false.
39029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline bool updateFrom(const C2Param &other) {
39129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        if (other._mSize == _mSize && other._mIndex == _mIndex && _mSize > 0) {
39229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            memcpy(this, &other, _mSize);
39329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            return true;
39429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        }
39529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        return false;
39629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    }
39729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
39829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarprotected:
39929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // returns |o| if it is a null ptr, or if can suitably be a param of given |type| (e.g. has
40029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // same type (ignoring stream ID), and size). Otherwise, returns null. If |checkDir| is false,
40129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // allow undefined or different direction (e.g. as constructed from C2PortParam() vs.
40229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // C2PortParam::input), but still require equivalent type (stream, port or global); otherwise,
40329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // return null.
40429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline static const C2Param* ifSuitable(
40529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            const C2Param* o, size_t size, Type type, size_t flexSize = 0, bool checkDir = true) {
40629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        if (o == nullptr || o->_mSize < size || (flexSize && ((o->_mSize - size) % flexSize))) {
40729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            return nullptr;
40829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        } else if (checkDir) {
40929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            return o->_mIndex.type() == type.mIndex ? o : nullptr;
41029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        } else if (o->_mIndex.isGlobal()) {
41129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            return nullptr;
41229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        } else {
41329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            return ((o->_mIndex.type() ^ type.mIndex) & ~Type::kDirMask) ? nullptr : o;
41429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        }
41529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    }
41629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
41729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// base constructor
41829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline C2Param(uint32_t paramSize, Index paramIndex)
41929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        : _mSize(paramSize),
42029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mIndex(paramIndex) {
42129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        if (paramSize > sizeof(C2Param)) {
42229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            memset(this + 1, 0, paramSize - sizeof(C2Param));
42329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        }
42429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    }
42529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
42629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// base constructor with stream set
42729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline C2Param(uint32_t paramSize, Index paramIndex, unsigned stream)
42829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        : _mSize(paramSize),
42929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mIndex(paramIndex | Index::makeStreamId(stream)) {
43029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        if (paramSize > sizeof(C2Param)) {
43129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            memset(this + 1, 0, paramSize - sizeof(C2Param));
43229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        }
43329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        if (!forStream()) {
43429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            invalidate();
43529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        }
43629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    }
43729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
43829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarprivate:
43929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    friend struct _C2ParamInspector; // for testing
44029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
44129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// returns the base type: the index for the underlying struct (for testing
44229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// as this can be gotten by the baseIndex enum)
44329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline uint32_t _baseIndex() const { return _mIndex.baseIndex(); }
44429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
44529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// returns true iff |o| has the same size and index as this. This performs the
44629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// basic check for equality.
44729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline bool equals(const C2Param &o) const {
44829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        return _mSize == o._mSize && _mIndex == o._mIndex;
44929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    }
45029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
45129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    uint32_t _mSize;
45229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    Index _mIndex;
45329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar};
45429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
45529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/// \ingroup internal
45629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/// allow C2Params access to private methods, e.g. constructors
45729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#define C2PARAM_MAKE_FRIENDS \
45829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename U, typename S, int I, class F> friend struct C2GlobalParam; \
45929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename U, typename S, int I, class F> friend struct C2PortParam; \
46029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename U, typename S, int I, class F> friend struct C2StreamParam; \
46129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
46229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/**
46329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * Setting base structure for component method signatures. Wrap constructors.
46429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar */
46529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarstruct C2Setting : public C2Param {
46629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarprotected:
46729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename ...Args>
46829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline C2Setting(const Args(&... args)) : C2Param(args...) { }
46929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarpublic: // TODO
47029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    enum : uint32_t { indexFlags = Type::kTypeSetting };
47129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar};
47229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
47329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/**
47429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * Tuning base structure for component method signatures. Wrap constructors.
47529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar */
47629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarstruct C2Tuning : public C2Setting {
47729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarprotected:
47829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename ...Args>
47929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline C2Tuning(const Args(&... args)) : C2Setting(args...) { }
48029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarpublic: // TODO
48129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    enum : uint32_t { indexFlags = Type::kTypeTuning };
48229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar};
48329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
48429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/**
48529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * Info base structure for component method signatures. Wrap constructors.
48629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar */
48729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarstruct C2Info : public C2Param {
48829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarprotected:
48929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename ...Args>
49029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline C2Info(const Args(&... args)) : C2Param(args...) { }
49129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarpublic: // TODO
49229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    enum : uint32_t { indexFlags = Type::kTypeInfo };
49329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar};
49429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
49529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/**
49629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * Structure uniquely specifying a field in an arbitrary structure.
49729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
49829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * \note This structure is used differently in C2FieldDescriptor to
49929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * identify array fields, such that _mSize is the size of each element. This is
50029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * because the field descriptor contains the array-length, and we want to keep
50129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * a relevant element size for variable length arrays.
50229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar */
50329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarstruct _C2FieldId {
50429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar//public:
50529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /**
50629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * Constructor used for C2FieldDescriptor that removes the array extent.
50729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     *
50829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * \param[in] offset pointer to the field in an object at address 0.
50929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     */
51029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename T, class B=typename std::remove_extent<T>::type>
51129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline _C2FieldId(T* offset)
51229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        : // offset is from "0" so will fit on 32-bits
51329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mOffset((uint32_t)(uintptr_t)(offset)),
51429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mSize(sizeof(B)) { }
51529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
51629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /**
51729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * Direct constructor from offset and size.
51829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     *
51929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * \param[in] offset offset of the field.
52029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * \param[in] size size of the field.
52129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     */
52229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline _C2FieldId(size_t offset, size_t size)
52329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        : _mOffset(offset), _mSize(size) {}
52429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
52529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /**
52629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * Constructor used to identify a field in an object.
52729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     *
52829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * \param U[type] pointer to the object that contains this field. This is needed in case the
52929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     *        field is in an (inherited) base class, in which case T will be that base class.
53029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * \param pm[im] member pointer to the field
53129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     */
53229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename R, typename T, typename U, typename B=typename std::remove_extent<R>::type>
53329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline _C2FieldId(U *, R T::* pm)
53429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        : _mOffset((uint32_t)(uintptr_t)(&(((U*)256)->*pm)) - 256u),
53529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mSize(sizeof(B)) { }
53629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
53729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /**
53829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * Constructor used to identify a field in an object.
53929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     *
54029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * \param U[type] pointer to the object that contains this field
54129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * \param pm[im] member pointer to the field
54229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     */
54329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename R, typename T, typename B=typename std::remove_extent<R>::type>
54429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline _C2FieldId(R T::* pm)
54529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        : _mOffset((uint32_t)(uintptr_t)(&(((T*)0)->*pm))),
54629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mSize(sizeof(B)) { }
54729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
54829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline bool operator==(const _C2FieldId &other) const {
54929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        return _mOffset == other._mOffset && _mSize == other._mSize;
55029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    }
55129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
55229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline bool operator<(const _C2FieldId &other) const {
55329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        return _mOffset < other._mOffset ||
55429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            // NOTE: order parent structure before sub field
55529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            (_mOffset == other._mOffset && _mSize > other._mSize);
55629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    }
55729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
55829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    DEFINE_OTHER_COMPARISON_OPERATORS(_C2FieldId)
55929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
56029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#if 0
56129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline uint32_t offset() const { return _mOffset; }
56229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline uint32_t size() const { return _mSize; }
56329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#endif
56429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
56529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#if defined(FRIEND_TEST)
56629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    friend void PrintTo(const _C2FieldId &d, ::std::ostream*);
56729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#endif
56829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
56929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarprivate:
57029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    uint32_t _mOffset; // offset of field
57129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    uint32_t _mSize;   // size of field
57229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar};
57329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
57429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/**
57529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * Structure uniquely specifying a field in a configuration
57629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar */
57729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarstruct C2ParamField {
57829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar//public:
57929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // TODO: fix what this is for T[] (for now size becomes T[1])
58029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename S, typename T>
58129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline C2ParamField(S* param, T* offset)
58229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        : _mIndex(param->index()),
58329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mFieldId(offset) {}
58429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
58529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename R, typename T, typename U>
58629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline C2ParamField(U *p, R T::* pm) : _mIndex(p->type()), _mFieldId(p, pm) { }
58729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
58829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline bool operator==(const C2ParamField &other) const {
58929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        return _mIndex == other._mIndex && _mFieldId == other._mFieldId;
59029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    }
59129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
59229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline bool operator<(const C2ParamField &other) const {
59329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        return _mIndex < other._mIndex ||
59429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            (_mIndex == other._mIndex && _mFieldId < other._mFieldId);
59529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    }
59629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
59729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    DEFINE_OTHER_COMPARISON_OPERATORS(C2ParamField)
59829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
59929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarprivate:
60029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    C2Param::Index _mIndex;
60129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    _C2FieldId _mFieldId;
60229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar};
60329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
60429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/**
60529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * A shared (union) representation of numeric values
60629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar */
60729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarclass C2Value {
60829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarpublic:
60929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// A union of supported primitive types.
61029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    union Primitive {
61129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        int32_t  i32;   ///< int32_t value
61229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        uint32_t u32;   ///< uint32_t value
61329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        int64_t  i64;   ///< int64_t value
61429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        uint64_t u64;   ///< uint64_t value
61529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        float    fp;    ///< float value
61629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
61729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        // constructors - implicit
61829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        Primitive(int32_t value)  : i32(value) { }
61929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        Primitive(uint32_t value) : u32(value) { }
62029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        Primitive(int64_t value)  : i64(value) { }
62129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        Primitive(uint64_t value) : u64(value) { }
62229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        Primitive(float value)    : fp(value)  { }
62329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
62429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        Primitive() : u64(0) { }
62529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
62629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    private:
62729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        friend class C2Value;
62829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        template<typename T> const T &ref() const;
62929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    };
63029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
63129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    enum Type {
63229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        NO_INIT,
63329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        INT32,
63429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        UINT32,
63529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        INT64,
63629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        UINT64,
63729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        FLOAT,
63829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    };
63929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
64029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename T> static constexpr Type typeFor();
64129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
64229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // constructors - implicit
64329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename T>
64429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    C2Value(T value)  : mType(typeFor<T>()),  mValue(value) { }
64529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
64629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    C2Value() : mType(NO_INIT) { }
64729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
64829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline Type type() const { return mType; }
64929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
65029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename T>
65129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline bool get(T *value) const {
65229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        if (mType == typeFor<T>()) {
65329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            *value = mValue.ref<T>();
65429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            return true;
65529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        }
65629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        return false;
65729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    }
65829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
65929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarprivate:
66029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    Type mType;
66129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    Primitive mValue;
66229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar};
66329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
66429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnartemplate<> const int32_t &C2Value::Primitive::ref<int32_t>() const { return i32; }
66529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnartemplate<> const int64_t &C2Value::Primitive::ref<int64_t>() const { return i64; }
66629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnartemplate<> const uint32_t &C2Value::Primitive::ref<uint32_t>() const { return u32; }
66729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnartemplate<> const uint64_t &C2Value::Primitive::ref<uint64_t>() const { return u64; }
66829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnartemplate<> const float &C2Value::Primitive::ref<float>() const { return fp; }
66929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
67029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnartemplate<> constexpr C2Value::Type C2Value::typeFor<int32_t>() { return INT32; }
67129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnartemplate<> constexpr C2Value::Type C2Value::typeFor<int64_t>() { return INT64; }
67229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnartemplate<> constexpr C2Value::Type C2Value::typeFor<uint32_t>() { return UINT32; }
67329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnartemplate<> constexpr C2Value::Type C2Value::typeFor<uint64_t>() { return UINT64; }
67429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnartemplate<> constexpr C2Value::Type C2Value::typeFor<float>() { return FLOAT; }
67529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
67629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/**
67729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * field descriptor. A field is uniquely defined by an index into a parameter.
67829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * (Note: Stream-id is not captured as a field.)
67929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
68029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * Ordering of fields is by offset. In case of structures, it is depth first,
68129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * with a structure taking an index just before and in addition to its members.
68229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar */
68329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarstruct C2FieldDescriptor {
68429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar//public:
68529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /** field types and flags
68629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * \note: only 32-bit and 64-bit fields are supported (e.g. no boolean, as that
68729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * is represented using INT32).
68829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     */
68929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    enum Type : uint32_t {
69029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        // primitive types
69129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        INT32   = C2Value::INT32,  ///< 32-bit signed integer
69229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        UINT32  = C2Value::UINT32, ///< 32-bit unsigned integer
69329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        INT64   = C2Value::INT64,  ///< 64-bit signed integer
69429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        UINT64  = C2Value::UINT64, ///< 64-bit signed integer
69529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        FLOAT   = C2Value::FLOAT,  ///< 32-bit floating point
69629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
69729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        // array types
69829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        STRING = 0x100, ///< fixed-size string (POD)
69929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        BLOB,           ///< blob. Blobs have no sub-elements and can be thought of as byte arrays;
70029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar                        ///< however, bytes cannot be individually addressed by clients.
70129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
70229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        // complex types
70329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        STRUCT_FLAG = 0x10000, ///< structs. Marked with this flag in addition to their baseIndex.
70429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    };
70529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
70629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    typedef std::pair<C2String, C2Value::Primitive> named_value_type;
70729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    typedef std::vector<const named_value_type> named_values_type;
70829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    //typedef std::pair<std::vector<C2String>, std::vector<C2Value::Primitive>> named_values_type;
70929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
71029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /**
71129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * Template specialization that returns the named values for a type.
71229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     *
71329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * \todo hide from client.
71429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     *
71529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * \return a vector of name-value pairs.
71629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     */
71729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename B>
71829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    static named_values_type namedValuesFor(const B &);
71929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
72029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline C2FieldDescriptor(uint32_t type, uint32_t length, C2StringLiteral name, size_t offset, size_t size)
72129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        : _mType((Type)type), _mLength(length), _mName(name), _mFieldId(offset, size) { }
72229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
72329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename T, class B=typename std::remove_extent<T>::type>
72429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline C2FieldDescriptor(const T* offset, const char *name)
72529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        : _mType(this->getType((B*)nullptr)),
72629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mLength(std::is_array<T>::value ? std::extent<T>::value : 1),
72729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mName(name),
72829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mNamedValues(namedValuesFor(*(B*)0)),
72929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mFieldId(offset) {}
73029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
73129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/*
73229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename T, typename B=typename std::remove_extent<T>::type>
73329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline C2FieldDescriptor<T, B, false>(T* offset, const char *name)
73429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        : _mType(this->getType((B*)nullptr)),
73529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mLength(std::is_array<T>::value ? std::extent<T>::value : 1),
73629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mName(name),
73729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mFieldId(offset) {}
73829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar*/
73929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
74029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// \deprecated
74129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename T, typename S, class B=typename std::remove_extent<T>::type>
74229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    constexpr inline C2FieldDescriptor(S*, T S::* field, const char *name)
74329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        : _mType(this->getType((B*)nullptr)),
74429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mLength(std::is_array<T>::value ? std::extent<T>::value : 1),
74529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mName(name),
74629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mFieldId(&(((S*)0)->*field)) {}
74729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
74829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// returns the type of this field
74929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline Type type() const { return _mType; }
75029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// returns the length of the field in case it is an array. Returns 0 for
75129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// T[] arrays, returns 1 for T[1] arrays as well as if the field is not an array.
75229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline size_t length() const { return _mLength; }
75329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// returns the name of the field
75429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline C2StringLiteral name() const { return _mName; }
75529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
75629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    const named_values_type &namedValues() const { return _mNamedValues; }
75729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
75829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#if defined(FRIEND_TEST)
75929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    friend void PrintTo(const C2FieldDescriptor &, ::std::ostream*);
76029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    friend bool operator==(const C2FieldDescriptor &, const C2FieldDescriptor &);
76129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    FRIEND_TEST(C2ParamTest_ParamFieldList, VerifyStruct);
76229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#endif
76329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
76429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarprivate:
76529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    const Type _mType;
76629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    const uint32_t _mLength; // the last member can be arbitrary length if it is T[] array,
76729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar                       // extending to the end of the parameter (this is marked with
76829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar                       // 0). T[0]-s are not fields.
76929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    const C2StringLiteral _mName;
77029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    const named_values_type _mNamedValues;
77129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
77229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    const _C2FieldId _mFieldId;   // field identifier (offset and size)
77329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
77429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // NOTE: We do not capture default value(s) here as that may depend on the component.
77529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // NOTE: We also do not capture bestEffort, as 1) this should be true for most fields,
77629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // 2) this is at parameter granularity.
77729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
77829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // type resolution
77929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline static Type getType(int32_t*)  { return INT32; }
78029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline static Type getType(uint32_t*) { return UINT32; }
78129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline static Type getType(int64_t*)  { return INT64; }
78229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline static Type getType(uint64_t*) { return UINT64; }
78329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline static Type getType(float*)    { return FLOAT; }
78429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline static Type getType(char*)     { return STRING; }
78529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline static Type getType(uint8_t*)  { return BLOB; }
78629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
78729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename T,
78829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar             class=typename std::enable_if<std::is_enum<T>::value>::type>
78929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline static Type getType(T*) {
79029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        typename std::underlying_type<T>::type underlying(0);
79129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        return getType(&underlying);
79229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    }
79329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
79429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // verify C2Struct by having a fieldList and a baseIndex.
79529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename T,
79629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar             class=decltype(T::baseIndex + 1), class=decltype(T::fieldList)>
79729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline static Type getType(T*) {
79829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        static_assert(!std::is_base_of<C2Param, T>::value, "cannot use C2Params as fields");
79929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        return (Type)(T::baseIndex | STRUCT_FLAG);
80029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    }
80129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar};
80229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
80329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#define DEFINE_NO_NAMED_VALUES_FOR(type) \
80429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnartemplate<> inline C2FieldDescriptor::named_values_type C2FieldDescriptor::namedValuesFor(const type &) { \
80529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    return named_values_type(); \
80629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar}
80729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
80829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar// We cannot subtype constructor for enumerated types so insted define no named values for
80929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar// non-enumerated integral types.
81029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos MolnarDEFINE_NO_NAMED_VALUES_FOR(int32_t)
81129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos MolnarDEFINE_NO_NAMED_VALUES_FOR(uint32_t)
81229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos MolnarDEFINE_NO_NAMED_VALUES_FOR(int64_t)
81329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos MolnarDEFINE_NO_NAMED_VALUES_FOR(uint64_t)
81429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos MolnarDEFINE_NO_NAMED_VALUES_FOR(uint8_t)
81529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos MolnarDEFINE_NO_NAMED_VALUES_FOR(char)
81629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos MolnarDEFINE_NO_NAMED_VALUES_FOR(float)
81729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
81829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/**
81929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * Describes the fields of a structure.
82029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar */
82129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarstruct C2StructDescriptor {
82229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarpublic:
82329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// Returns the parameter type
82429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline C2Param::BaseIndex baseIndex() const { return _mType.baseIndex(); }
82529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
82629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // Returns the number of fields in this param (not counting any recursive fields).
82729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // Must be at least 1 for valid params.
82829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline size_t numFields() const { return _mFields.size(); }
82929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
83029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // Returns the list of immediate fields (not counting any recursive fields).
83129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    typedef std::vector<const C2FieldDescriptor>::const_iterator field_iterator;
83229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline field_iterator cbegin() const { return _mFields.cbegin(); }
83329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline field_iterator cend() const { return _mFields.cend(); }
83429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
83529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    // only supplying const iterator - but these are needed for range based loops
83629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline field_iterator begin() const { return _mFields.cbegin(); }
83729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline field_iterator end() const { return _mFields.cend(); }
83829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
83929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename T>
84029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline C2StructDescriptor(T*)
84129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        : C2StructDescriptor(T::baseIndex, T::fieldList) { }
84229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
84329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline C2StructDescriptor(
84429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            C2Param::BaseIndex type,
84529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            std::initializer_list<const C2FieldDescriptor> fields)
84629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        : _mType(type), _mFields(fields) { }
84729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
84829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarprivate:
84929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    const C2Param::BaseIndex _mType;
85029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    const std::vector<const C2FieldDescriptor> _mFields;
85129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar};
85229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
85329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/**
85429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * Describes parameters for a component.
85529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar */
85629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarstruct C2ParamDescriptor {
85729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarpublic:
85829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /**
85929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * Returns whether setting this param is required to configure this component.
86029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * This can only be true for builtin params for platform-defined components (e.g. video and
86129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * audio encoders/decoders, video/audio filters).
86229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * For vendor-defined components, it can be true even for vendor-defined params,
86329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * but it is not recommended, in case the component becomes platform-defined.
86429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     */
86529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline bool isRequired() const { return _mIsRequired; }
86629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
86729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /**
86829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * Returns whether this parameter is persistent. This is always true for C2Tuning and C2Setting,
86929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * but may be false for C2Info. If true, this parameter persists across frames and applies to
87029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * the current and subsequent frames. If false, this C2Info parameter only applies to the
87129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * current frame and is not assumed to have the same value (or even be present) on subsequent
87229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     * frames, unless it is specified for those frames.
87329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     */
87429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline bool isPersistent() const { return _mIsPersistent; }
87529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
87629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// Returns the name of this param.
87729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// This defaults to the underlying C2Struct's name, but could be altered for a component.
87829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline C2String name() const { return _mName; }
87929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
88029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// Returns the parameter type
88129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /// \todo fix this
88229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline C2Param::Type type() const { return _mType; }
88329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
88429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename T>
88529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline C2ParamDescriptor(bool isRequired, C2StringLiteral name, const T*)
88629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        : _mIsRequired(isRequired),
88729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mIsPersistent(true),
88829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mName(name),
88929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mType(T::typeIndex) { }
89029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
89129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    inline C2ParamDescriptor(
89229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            bool isRequired, C2StringLiteral name, C2Param::Type type)
89329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        : _mIsRequired(isRequired),
89429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mIsPersistent(true),
89529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mName(name),
89629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          _mType(type) { }
89729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
89829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarprivate:
89929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    const bool _mIsRequired;
90029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    const bool _mIsPersistent;
90129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    const C2String _mName;
90229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    const C2Param::Type _mType;
90329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar};
90429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
90529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/// \ingroup internal
90629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/// Define a structure without baseIndex.
90729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#define DEFINE_C2STRUCT_NO_BASE(name) \
90829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarpublic: \
90929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    typedef C2##name##Struct _type; /**< type name shorthand */ \
91029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    const static std::initializer_list<const C2FieldDescriptor> fieldList; /**< structure fields */
91129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
91229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/// Define a structure with matching baseIndex.
91329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#define DEFINE_C2STRUCT(name) \
91429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarpublic: \
91529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    enum : uint32_t { baseIndex = kParamIndex##name }; \
91629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    DEFINE_C2STRUCT_NO_BASE(name)
91729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
91829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/// Define a flexible structure with matching baseIndex.
91929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#define DEFINE_FLEX_C2STRUCT(name, flexMember) \
92029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarpublic: \
92129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    FLEX(C2##name##Struct, flexMember) \
92229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    enum : uint32_t { baseIndex = kParamIndex##name | C2Param::BaseIndex::_kFlexibleFlag }; \
92329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    DEFINE_C2STRUCT_NO_BASE(name)
92429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
92529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/// \ingroup internal
92629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/// Describe a structure of a templated structure.
92729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#define DESCRIBE_TEMPLATED_C2STRUCT(strukt, list) \
92829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<> \
92929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    const std::initializer_list<const C2FieldDescriptor> strukt::fieldList = list;
93029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
93129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/// \deprecated
93229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/// Describe the fields of a structure using an initializer list.
93329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#define DESCRIBE_C2STRUCT(name, list) \
93429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    const std::initializer_list<const C2FieldDescriptor> C2##name##Struct::fieldList = list;
93529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
93629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/**
93729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * Describe a field of a structure.
93829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * These must be in order.
93929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
94029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * There are two ways to use this macro:
94129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
94229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *  ~~~~~~~~~~~~~ (.cpp)
94329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *  struct C2VideoWidthStruct {
94429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      int32_t mWidth;
94529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      C2VideoWidthStruct() {} // optional default constructor
94629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      C2VideoWidthStruct(int32_t _width) : mWidth(_width) {}
94729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
94829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      DEFINE_AND_DESCRIBE_C2STRUCT(VideoWidth)
94929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      C2FIELD(mWidth, "width")
95029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *  };
95129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *  ~~~~~~~~~~~~~
95229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
95329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *  ~~~~~~~~~~~~~ (.cpp)
95429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *  struct C2VideoWidthStruct {
95529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      int32_t mWidth;
95629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      C2VideoWidthStruct() = default; // optional default constructor
95729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      C2VideoWidthStruct(int32_t _width) : mWidth(_width) {}
95829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
95929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      DEFINE_C2STRUCT(VideoWidth)
96029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *  } C2_PACK;
96129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
96229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *  DESCRIBE_C2STRUCT(VideoWidth, {
96329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      C2FIELD(mWidth, "width")
96429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *  })
96529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *  ~~~~~~~~~~~~~
96629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
96729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *  For flexible structures (those ending in T[]), use the flexible macros:
96829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
96929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *  ~~~~~~~~~~~~~ (.cpp)
97029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *  struct C2VideoFlexWidthsStruct {
97129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      int32_t mWidths[];
97229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      C2VideoFlexWidthsStruct(); // must have a default constructor
97329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
97429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *  private:
97529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      // may have private constructors taking number of widths as the first argument
97629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      // This is used by the C2Param factory methods, e.g.
97729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      //   C2VideoFlexWidthsGlobalParam::alloc_unique(size_t, int32_t);
97829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      C2VideoFlexWidthsStruct(size_t flexCount, int32_t value) {
97929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *          for (size_t i = 0; i < flexCount; ++i) {
98029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *              mWidths[i] = value;
98129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *          }
98229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      }
98329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
98429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      // If the last argument is T[N] or std::initializer_list<T>, the flexCount will
98529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      // be automatically calculated and passed by the C2Param factory methods, e.g.
98629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      //   int widths[] = { 1, 2, 3 };
98729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      //   C2VideoFlexWidthsGlobalParam::alloc_unique(widths);
98829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      template<unsigned N>
98929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      C2VideoFlexWidthsStruct(size_t flexCount, const int32_t(&init)[N]) {
99029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *          for (size_t i = 0; i < flexCount; ++i) {
99129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *              mWidths[i] = init[i];
99229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *          }
99329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      }
99429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
99529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      DEFINE_AND_DESCRIBE_FLEX_C2STRUCT(VideoFlexWidths, mWidths)
99629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      C2FIELD(mWidths, "widths")
99729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *  };
99829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *  ~~~~~~~~~~~~~
99929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
100029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *  ~~~~~~~~~~~~~ (.cpp)
100129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *  struct C2VideoFlexWidthsStruct {
100229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      int32_t mWidths[];
100329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      C2VideoFlexWidthsStruct(); // must have a default constructor
100429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
100529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      DEFINE_FLEX_C2STRUCT(VideoFlexWidths, mWidths)
100629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *  } C2_PACK;
100729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
100829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *  DESCRIBE_C2STRUCT(VideoFlexWidths, {
100929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *      C2FIELD(mWidths, "widths")
101029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *  })
101129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *  ~~~~~~~~~~~~~
101229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
101329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar */
101429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#define C2FIELD(member, name) \
101529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar  C2FieldDescriptor(&((_type*)(nullptr))->member, name),
101629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
101729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/// \deprecated
101829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#define C2SOLE_FIELD(member, name) \
101929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar  C2FieldDescriptor(&_type::member, name, 0)
102029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
102129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/// Define a structure with matching baseIndex and start describing its fields.
102229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/// This must be at the end of the structure definition.
102329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#define DEFINE_AND_DESCRIBE_C2STRUCT(name) \
102429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    DEFINE_C2STRUCT(name) }  C2_PACK; \
102529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    const std::initializer_list<const C2FieldDescriptor> C2##name##Struct::fieldList = {
102629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
102729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/// Define a flexible structure with matching baseIndex and start describing its fields.
102829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/// This must be at the end of the structure definition.
102929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#define DEFINE_AND_DESCRIBE_FLEX_C2STRUCT(name, flexMember) \
103029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    DEFINE_FLEX_C2STRUCT(name, flexMember) } C2_PACK; \
103129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    const std::initializer_list<const C2FieldDescriptor> C2##name##Struct::fieldList = {
103229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
103329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/**
103429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * Parameter reflector class.
103529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
103629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * This class centralizes the description of parameter structures. This can be shared
103729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * by multiple components as describing a parameter does not imply support of that
103829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * parameter. However, each supported parameter and any dependent structures within
103929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * must be described by the parameter reflector provided by a component.
104029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar */
104129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarclass C2ParamReflector {
104229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarpublic:
104329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    /**
104429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     *  Describes a parameter structure.
104529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     *
104629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     *  \param[in] paramIndex the base index of the parameter structure
104729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     *
104829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     *  \return the description of the parameter structure
104929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     *  \retval nullptr if the parameter is not supported by this reflector
105029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     *
105129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     *  This methods shall not block and return immediately.
105229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     *
105329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     *  \note this class does not take a set of indices because we would then prefer
105429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     *  to also return any dependent structures, and we don't want this logic to be
105529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     *  repeated in each reflector. Alternately, this could just return a map of all
105629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     *  descriptions, but we want to conserve memory if client only wants the description
105729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     *  of a few indices.
105829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar     */
105929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::BaseIndex paramIndex) = 0;
106029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
106129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarprotected:
106229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    virtual ~C2ParamReflector() = default;
106329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar};
106429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
106529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/**
106629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * A useable supported values for a field.
106729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
106829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * This can be either a range or a set of values. The range can be linear or geometric with a
106929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * clear minimum and maximum value, and can have an optional step size or geometric ratio. Values
107029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * can optionally represent flags.
107129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
107229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * \note Do not use flags to represent bitfields. Use individual values or separate fields instead.
107329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar */
107429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnartemplate<typename T>
107529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarstruct C2TypedFieldSupportedValues {
107629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar//public:
107729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    enum Type {
107829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        RANGE,      ///< a numeric range that can be continuous or discrete
107929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        VALUES,     ///< a list of values
108029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        FLAGS       ///< a list of flags that can be OR-ed
108129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    };
108229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
108329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    Type type;
108429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
108529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    struct {
108629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        T min;
108729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        T max;
108829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        T step;
108929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        T nom;
109029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        T denom;
109129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    } range;
109229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    std::vector<T> values;
109329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
109429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    C2TypedFieldSupportedValues(T min, T max, T step = T(std::is_floating_point<T>::value ? 0 : 1))
109529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        : type(RANGE),
109629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          range{min, max, step, (T)1, (T)1} { }
109729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
109829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    C2TypedFieldSupportedValues(T min, T max, T nom, T den) :
109929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        type(RANGE),
110029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        range{min, max, (T)0, nom, den} { }
110129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
110229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    C2TypedFieldSupportedValues(bool flags, std::initializer_list<T> list) :
110329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        type(flags ? FLAGS : VALUES),
110429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        values(list) {}
110529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar};
110629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
110729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/**
110829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * Generic supported values for a field.
110929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
111029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * This can be either a range or a set of values. The range can be linear or geometric with a
111129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * clear minimum and maximum value, and can have an optional step size or geometric ratio. Values
111229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * can optionally represent flags.
111329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar *
111429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar * \note Do not use flags to represent bitfields. Use individual values or separate fields instead.
111529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar */
111629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnarstruct C2FieldSupportedValues {
111729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar//public:
111829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    enum Type {
111929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        RANGE,      ///< a numeric range that can be continuous or discrete
112029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        VALUES,     ///< a list of values
112129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        FLAGS       ///< a list of flags that can be OR-ed
112229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    };
112329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
112429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    Type type;
112529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
112629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    typedef C2Value::Primitive Primitive;
112729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
112829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    struct {
112929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        Primitive min;
113029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        Primitive max;
113129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        Primitive step;
113229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        Primitive nom;
113329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        Primitive denom;
113429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    } range;
113529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    std::vector<Primitive> values;
113629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
113729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename T>
113829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    C2FieldSupportedValues(T min, T max, T step = T(std::is_floating_point<T>::value ? 0 : 1))
113929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        : type(RANGE),
114029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          range{min, max, step, (T)1, (T)1} { }
114129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
114229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename T>
114329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    C2FieldSupportedValues(T min, T max, T nom, T den) :
114429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        type(RANGE),
114529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        range{min, max, (T)0, nom, den} { }
114629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
114729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename T>
114829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    C2FieldSupportedValues(bool flags, std::initializer_list<T> list)
114929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        : type(flags ? FLAGS : VALUES),
115029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          range{(T)0, (T)0, (T)0, (T)0, (T)0} {
115129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        for(T value : list) {
115229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            values.emplace_back(value);
115329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        }
115429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    }
115529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
115629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    template<typename T, typename E=decltype(C2FieldDescriptor::namedValuesFor(*(T*)0))>
115729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    C2FieldSupportedValues(bool flags, const T*)
115829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        : type(flags ? FLAGS : VALUES),
115929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar          range{(T)0, (T)0, (T)0, (T)0, (T)0} {
116029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar              C2FieldDescriptor::named_values_type named = C2FieldDescriptor::namedValuesFor(*(T*)0);
116129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        for (const C2FieldDescriptor::named_value_type &item : named) {
116229a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar            values.emplace_back(item.second);
116329a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar        }
116429a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar    }
116529a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar};
116629a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
116729a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar/// @}
116829a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
116929a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar}  // namespace android
117029a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar
117129a6ba9949e4127a9c6df2cc75033dbe97f501a9Lajos Molnar#endif  // C2PARAM_H_
1172