1731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar/*
2731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar * Copyright (C) 2018 The Android Open Source Project
3731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar *
4731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar * Licensed under the Apache License, Version 2.0 (the "License");
5731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar * you may not use this file except in compliance with the License.
6731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar * You may obtain a copy of the License at
7731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar *
8a0e1ab0c7ad9ce3334b16ca818eecf3a0b03928cLajos Molnar *      http://www.apache.org/licenses/LICENSE-2.0
9731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar *
10731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar * Unless required by applicable law or agreed to in writing, software
11731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar * distributed under the License is distributed on an "AS IS" BASIS,
12731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar * See the License for the specific language governing permissions and
14731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar * limitations under the License.
15731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar */
16731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
17731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar#ifndef C2UTILS_INTERFACE_HELPER_H_
18731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar#define C2UTILS_INTERFACE_HELPER_H_
19731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
20731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar#include <C2Component.h>
21731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar#include <util/C2InterfaceUtils.h>
22731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
23731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar#include <map>
24731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar#include <vector>
25731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
26731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar#include <stddef.h>
27731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
28731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar/**
29731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar * Interface Helper
30731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar */
31731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnarusing C2R = C2SettingResultsBuilder;
32731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
33731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnartemplate<typename T, bool E=std::is_enum<T>::value>
34731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnarstruct _c2_reduce_enum_to_underlying_type {
35731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    typedef T type;
36731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar};
37731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
38731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnartemplate<typename T>
39731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnarstruct _c2_reduce_enum_to_underlying_type<T, true> {
40731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    typedef typename std::underlying_type<T>::type type;
41731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar};
42731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
43731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar/**
44731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar * Helper class to implement parameter reflectors. This class is dynamic and is designed to be
45731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar * shared by multiple interfaces. This allows interfaces to add structure descriptors as needed.
46731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar */
47731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnarclass C2ReflectorHelper : public C2ParamReflector {
48731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnarpublic:
49731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    C2ReflectorHelper() = default;
50731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    virtual ~C2ReflectorHelper() = default;
51731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    virtual std::unique_ptr<C2StructDescriptor> describe(
52731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            C2Param::CoreIndex paramIndex) const override;
53731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
54731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    /**
55731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * Adds support for describing the given parameters.
56731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     *
57731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * \param Params types of codec 2.0 structs (or parameters) to describe
58731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     */
59731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    template<typename... Params>
60731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    C2_INLINE void addStructDescriptors() {
61731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        std::vector<C2StructDescriptor> structs;
6251ea56a991d6371e35c8d0bb5001e721cc63f8eeLajos Molnar        addStructDescriptors(structs, (_Tuple<Params...> *)nullptr);
63731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    }
64731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
65731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    /**
66731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * Adds support for describing a specific struct.
67731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     *
68731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * \param strukt descriptor for the struct that will be moved out.
69731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     */
70731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    void addStructDescriptor(C2StructDescriptor &&strukt);
71731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
72731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnarprivate:
7351ea56a991d6371e35c8d0bb5001e721cc63f8eeLajos Molnar    template<typename... Params>
7451ea56a991d6371e35c8d0bb5001e721cc63f8eeLajos Molnar    class C2_HIDE _Tuple { };
7551ea56a991d6371e35c8d0bb5001e721cc63f8eeLajos Molnar
76731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    /**
77731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * Adds support for describing the given descriptors.
78731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     *
79731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * \param structs List of structure descriptors to add support for
80731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     */
818274782aab7f743fc7bf83c344555db03f788a79Lajos Molnar    void addStructDescriptors(
8251ea56a991d6371e35c8d0bb5001e721cc63f8eeLajos Molnar            std::vector<C2StructDescriptor> &structs, _Tuple<> *);
83731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
84731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    /**
85731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * Utility method that adds support for describing the given descriptors in a recursive manner
86731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * one structure at a time using a list of structure descriptors temporary.
87731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     *
88731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * \param T the type of codec 2.0 struct to describe
89731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * \param Params rest of the structs
90731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * \param structs Temporary list of structure descriptors used to optimize the operation.
91731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     */
92731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    template<typename T, typename... Params>
93731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    C2_INLINE void addStructDescriptors(
9451ea56a991d6371e35c8d0bb5001e721cc63f8eeLajos Molnar            std::vector<C2StructDescriptor> &structs, _Tuple<T, Params...> *) {
95731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        structs.emplace_back((T*)nullptr);
9651ea56a991d6371e35c8d0bb5001e721cc63f8eeLajos Molnar        addStructDescriptors(structs, (_Tuple<Params...> *)nullptr);
97731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    }
98731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
99731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    mutable std::mutex _mMutex;
100731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    std::map<C2Param::CoreIndex, const C2StructDescriptor> _mStructs; ///< descriptors
101731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar};
102731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
103731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar/**
104731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar * Utility class that implements the codec 2.0 interface API-s for some parameters.
105731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar *
106731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar * This class must be subclassed.
107731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar */
108731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnarclass C2InterfaceHelper {
109731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnarpublic:
110731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    /**
111731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * Returns the base offset of a field at |offset| that could be part of an array or part of a
112731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * sub-structure.
113731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     *
114731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * This method does not do field size verification, e.g. if offset if obtained from a structure,
115731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * it will not stop at the structure boundary - this is okay, as we just want the base offset
116731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * here, which is the same.
117731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     */
118731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    static
119731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    size_t GetBaseOffset(const std::shared_ptr<C2ParamReflector> &reflector,
120731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                                C2Param::CoreIndex index, size_t offset);
121731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
122731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    /**
123731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * The interface helper class uses references to std::shared_ptr<T> config parameters.
124731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * Internally, these need to be generalized to std::shared_ptr<C2Param> refs, but the cast is
125731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * not allowed (as these are references). As such, this class never returns pointer to the
126731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * shared_ptrs.
127731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     */
128731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    struct ParamRef {
129731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        template<typename T, typename enable=
130731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                typename std::enable_if<std::is_convertible<T, C2Param>::value>::type>
131731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        inline C2_HIDE ParamRef(std::shared_ptr<T> &param)
132731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            : _mRef(reinterpret_cast<std::shared_ptr<C2Param>*>(&param)) { }
133731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
134731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        // used by comparison operator for containers
135731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        operator std::shared_ptr<C2Param> *() const { return _mRef; }
136731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
137731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /**
138731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * Returns a shared pointer to the parameter.
139731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         */
140731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        std::shared_ptr<C2Param> get() const { return *_mRef; }
141731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
142731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    private:
143731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        std::shared_ptr<C2Param> *_mRef;
144731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    };
145731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
146731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    /**
147731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * Field helper.
148731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     *
149731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * Contains additional information for the field: possible values, and currently supported
150731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * values.
151731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     */
152731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    class FieldHelper {
153731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    public:
154731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /**
155731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * Creates helper for a field with given possible values.
156731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         *
157731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \param param parameter reference. The parameter does not have to be initialized at this
158731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         *        point.
159731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \param field field identifier
160731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \param values possible values for the field
161731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         */
162731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        FieldHelper(const ParamRef &param, const _C2FieldId &field,
163731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                    std::unique_ptr<C2FieldSupportedValues> &&values);
164731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
165731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /**
166731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * Creates a param-field identifier for this field. This method is called after the
167731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * underlying parameter has been initialized.
168731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         *
169731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \aram index
170731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         *
171731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * @return C2ParamField
172731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         */
173731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        C2ParamField makeParamField(C2Param::Index index) const;
174731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
175731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /**
176731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * Sets the currently supported values for this field.
177731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         *
178731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \param values currently supported values that will be moved out
179731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         */
180731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        void setSupportedValues(std::unique_ptr<C2FieldSupportedValues> &&values);
181731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
182731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /**
183731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * Gets the currently supported values for this field. This defaults to the possible values
184731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * if currently supported values were never set.
185731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         */
186731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        const C2FieldSupportedValues *getSupportedValues() const;
187731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
188731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /**
189731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * Gets the possible values for this field.
190731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         */
191731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        const C2FieldSupportedValues *getPossibleValues() const;
192731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
193731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    protected:
194731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        // TODO: move to impl for safety
195731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        ParamRef mParam;
196731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        _C2FieldId mFieldId;
197731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        std::unique_ptr<C2FieldSupportedValues> mPossible;
198731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        std::unique_ptr<C2FieldSupportedValues> mSupported; ///< if different from possible
199731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    };
200731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
201731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    template<typename T>
202731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    struct C2_HIDE Param;
203731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    class ParamHelper;
204731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
205731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    /**
206731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * Factory is an interface to get the parameter helpers from a std::shared_ptr<T> &.
207731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     */
208731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    class Factory {
209731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        // \todo this may be already in ParamHelper
210731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        virtual std::shared_ptr<C2ParamReflector> getReflector() const = 0;
211731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
212731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        virtual std::shared_ptr<ParamHelper> getParamHelper(const ParamRef &param) const = 0;
213731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
214731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    public:
215731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        virtual ~Factory() = default;
216731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
217731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        template<typename T>
218731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        Param<T> get(std::shared_ptr<T> &param, std::shared_ptr<T> altValue = nullptr) const {
219731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            return Param<T>(getParamHelper(ParamRef(param)),
220731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                            altValue == nullptr ? param : altValue,
221731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                            getReflector());
222731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        }
223731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    };
224731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
225731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    /**
226731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * Typed field helper.
227731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     */
228731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    template<typename T>
2299fca24013957d2dfe99b4291f9f9297f720c7fa8Wonsik Kim    struct Field {
230731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /**
231731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * Constructor.
232731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         *
233731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \param helper helper for this field
234731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \param index  parameter index (this is needed as it is not available during parameter
235731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         *        construction) \todo remove
236731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         */
237731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        Field(std::shared_ptr<FieldHelper> helper, C2Param::Index index);
238731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
239731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        bool supportsAtAll(T value) const {
240731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            return C2FieldSupportedValuesHelper<T>(*_mHelper->getPossibleValues()).supports(value);
241731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        }
242731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
243731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        bool supportsNow(T value) const {
244731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            return C2FieldSupportedValuesHelper<T>(*_mHelper->getSupportedValues()).supports(value);
245731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        }
246731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
247731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /**
248731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * Creates a conflict resolution suggestion builder for this field.
249731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         */
250731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        C2ParamFieldValuesBuilder<T> shouldBe() const;
251731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
252731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /**
253731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * Creates a currently supported values builder for this field. This is only supported
254731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * for non-const fields to disallow setting supported values for dependencies.
255731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         */
256731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        C2ParamFieldValuesBuilder<T> mustBe();
257731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
258f67a2db1cf8b992fe0a731be5c7e05318ed0ad67Lajos Molnar        operator C2ParamField() const {
259f67a2db1cf8b992fe0a731be5c7e05318ed0ad67Lajos Molnar            return _mField;
260f67a2db1cf8b992fe0a731be5c7e05318ed0ad67Lajos Molnar        }
261f67a2db1cf8b992fe0a731be5c7e05318ed0ad67Lajos Molnar
262731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        // TODO
263731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        C2R validatePossible(const T &value __unused) const {
264731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            /// TODO
265731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            return C2R::Ok();
266731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        }
267731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
268731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    private:
269731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        std::shared_ptr<FieldHelper> _mHelper;
270731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        C2ParamField _mField;
271731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    };
272731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
273731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    class ParamHelper {
274731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    public:
275731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        ParamHelper(ParamRef param, C2StringLiteral name, C2StructDescriptor &&);
276731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        ParamHelper(ParamHelper &&);
277731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        ~ParamHelper();
278731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
279731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /**
280731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * Finds a field descriptor.
281731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         */
282731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        std::shared_ptr<FieldHelper> findField(size_t baseOffs, size_t baseSize) const;
283731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
2849556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        /// returns the parameter ref for this parameter
285731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        const ParamRef ref() const;
286731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
2879556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        /// returns the current value of this parameter as modifiable. The constness of this
2889556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        /// object determines the constness of the returned value.
289731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        std::shared_ptr<C2Param> value();
290731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
2919556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        /// returns the current value of this parameter as const
292731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        std::shared_ptr<const C2Param> value() const;
293731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
294731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /**
295731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * Performs a configuration change request for this parameter.
296731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         *
297731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \param value    the value that is being assigned to this parameter.
298731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         *                 This could be pointing to the current value of the
299731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         *                 parameter. This must not change.
300731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \param mayBlock whether blocking is allowed
301731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \param endValue the resulting value
3029556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar         * \param factory  parameter factory (to access dependencies)
303731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \param failures vector of failures to append any failures from this
304731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         *                 operation
305731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         *
306731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \retval C2_OK        configuration was successful
307731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \retval C2_BAD_VALUE value is incorrect (TBD)
308731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \retval C2_NO_MEMORY not enough memory to perform the assignment
309731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \retval C2_TIMED_OUT configuration timed out
310731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \retval C2_BLOCKING  configuration requires blocking to be allowed
311731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \retval C2_CORRUPTED interface is corrupted
312731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         */
313731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        c2_status_t trySet(
314731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                const C2Param *value, bool mayBlock,
315731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                bool *changed,
3169556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar                Factory &factory,
317731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                std::vector<std::unique_ptr<C2SettingResult>>* const failures);
318731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
3199556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        /// returns parameter indices that depend on this parameter
320731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        const std::vector<C2Param::Index> getDownDependencies() const;
321731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
3229556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        /// adds a dependent parameter
323731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        void addDownDependency(C2Param::Index index);
324731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
3259556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        /// returns that parameter refs for parameters that depend on this
326731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        const std::vector<ParamRef> getDependenciesAsRefs() const;
327731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
3289556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        /// returns and moves out stored struct descriptor
329731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        C2StructDescriptor retrieveStructDescriptor();
330731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
3319556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        /// returns the name of this parameter
3329556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        C2String name() const;
3339556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar
3349556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        /// returns the index of this parameter
335731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        C2Param::Index index() const;
336731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
3379556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        /// returns the parameter descriptor
3389556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        std::shared_ptr<const C2ParamDescriptor> getDescriptor() const;
3399556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar
3409556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        /**
3419556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar         * Validates param helper.
3429556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar         *
3439556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar         * For now, this fills field info for const params.
3449556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar         *
3459556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar         * \retval C2_CORRUPTED the parameter cannot be added as such
3469556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar         */
3479556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        c2_status_t validate(const std::shared_ptr<C2ParamReflector> &reflector);
348731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
349731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    protected:
350731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        typedef C2ParamDescriptor::attrib_t attrib_t;
351731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        attrib_t& attrib();
352731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
3539556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        /// sets the default value of this parameter
354731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        void setDefaultValue(std::shared_ptr<C2Param> default_);
355731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
3569556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        /// sets the setter method
357731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        void setSetter(std::function<C2R(const C2Param *, bool, bool *, Factory &)> setter);
358731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
3599556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        /// sets the getter method
360731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        void setGetter(std::function<std::shared_ptr<C2Param>(bool)> getter);
361731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
3629556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        /// sets the dependencies
363731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        void setDependencies(std::vector<C2Param::Index> indices, std::vector<ParamRef> refs);
364731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
3659556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        /// sets the fields and their supported values
3669556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        void setFields(std::vector<C2ParamFieldValues> &&fields);
367731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
3689556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        /// build this into a final ParamHelper object
369731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        std::shared_ptr<ParamHelper> build();
370731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
371731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        class Impl;
372731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        std::unique_ptr<Impl> mImpl;
373731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    };
374731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
375731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    /**
376731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * Typed parameter helper. This provides access to members as well as field helpers.
377731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     */
378731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    template<typename T>
379731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    struct C2_HIDE Param {
380731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        Param(
381731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                std::shared_ptr<ParamHelper> helper, std::shared_ptr<T> &param,
382731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                std::shared_ptr<C2ParamReflector> reflector)
383731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            : v(*param.get()),
384731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar              _mTypedParam(param),
385731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar              _mHelper(helper),
386731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar              _mReflector(reflector) { }
387731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
388731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        template<typename S>
3899556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        using FieldType = Field<
3909556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar                typename _c2_reduce_enum_to_underlying_type<
3919556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar                        typename std::remove_const<
3929556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar                                typename std::remove_extent<S>::type>::type>::type>;
393731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
394731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        template<typename S>
395731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        FieldType<S> F(S &field) {
396731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            size_t offs = (uintptr_t)&field - (uintptr_t)&get();
397731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            // this must fall either within sizeof(T) + FLEX_SIZE or param->size()
398731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            // size_t size = sizeof(field);
399731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            // mParam may be null
400731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            size_t baseSize = sizeof(typename std::remove_extent<S>::type);
4014f6b9cc507dffa5667a644abcdd75ce0a124442cLajos Molnar            size_t baseOffs = GetBaseOffset(
4024f6b9cc507dffa5667a644abcdd75ce0a124442cLajos Molnar                    _mReflector, T::CORE_INDEX, offs - sizeof(C2Param));
4034f6b9cc507dffa5667a644abcdd75ce0a124442cLajos Molnar            if (~baseOffs == 0) {
4044f6b9cc507dffa5667a644abcdd75ce0a124442cLajos Molnar                // C2_LOG(FATAL) << "unknown field at offset " << offs << " size " << sizeof(S)
4054f6b9cc507dffa5667a644abcdd75ce0a124442cLajos Molnar                //       << " base-size " << baseSize;
4064f6b9cc507dffa5667a644abcdd75ce0a124442cLajos Molnar                // __builtin_trap();
4074f6b9cc507dffa5667a644abcdd75ce0a124442cLajos Molnar            } else {
4084f6b9cc507dffa5667a644abcdd75ce0a124442cLajos Molnar                baseOffs += sizeof(C2Param);
4094f6b9cc507dffa5667a644abcdd75ce0a124442cLajos Molnar            }
410731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
411731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            std::shared_ptr<FieldHelper> helper = _mHelper->findField(baseOffs, baseSize);
412731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            return FieldType<S>(helper, _mTypedParam->index());
413731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        }
414731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
415731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        // const Param have const Fields; however, remove const from S
416731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        template<typename S>
417731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        const FieldType<S> F(S &field) const {
418731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            return const_cast<const FieldType<S>>(const_cast<Param *>(this)->F(field));
419731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        }
420731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
421731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /// Returns a const ref value of this const param.
422731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        const T &get() const {
423731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            return *_mTypedParam.get();
424731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        }
425731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
426731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /// Returns a modifiable ref value of this non-const param.
427731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        T &set() {
428731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            return *_mTypedParam.get();
429731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        }
430731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
431731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /// Const-reference to the value.s
432731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        T const &v;
433731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
434731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    private:
435731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        std::shared_ptr<T> _mTypedParam;
436731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        std::shared_ptr<ParamHelper> _mHelper;
437731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        std::shared_ptr<C2ParamReflector> _mReflector;
438731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    };
439731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
4409556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar    template<typename T>
4419556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar    using C2P = Param<T>;
4429556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar
443731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    /**
444731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * Templated move builder class for a parameter helper.
445731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     */
446731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    template<typename T>
447731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    class C2_HIDE ParamBuilder : private ParamHelper {
448731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    public:
449731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /** Construct the parameter builder from minimal info required. */
450731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        ParamBuilder(std::shared_ptr<T> &param, C2StringLiteral name)
451731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            : ParamHelper(param, name, C2StructDescriptor((T*)nullptr)),
452731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar              mTypedParam(&param) {
453731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            attrib() = attrib_t::IS_PERSISTENT;
454731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        }
455731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
456731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /** Makes this parameter required. */
457731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        inline ParamBuilder &required() {
458731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            attrib() |= attrib_t::IS_REQUIRED;
459731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            return *this;
460731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        }
461731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
462731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /** Makes this parameter transient (not persistent). */
463731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        inline ParamBuilder &transient() {
464731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            attrib() &= ~attrib_t::IS_PERSISTENT;
465731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            return *this;
466731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        }
467731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
468731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /** Makes this parameter hidden (not exposed in JAVA API). */
469731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        inline ParamBuilder &hidden() {
470731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            attrib() |= attrib_t::IS_HIDDEN;
471731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            return *this;
472731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        }
473731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
474731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /** Makes this parameter internal (not exposed to query/settings). */
475731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        inline ParamBuilder &internal() {
476731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            attrib() |= attrib_t::IS_INTERNAL;
477731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            return *this;
478731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        }
479731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
480731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /** Adds default value. Must be added exactly once. */
481731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        inline ParamBuilder &withDefault(std::shared_ptr<T> default_) {
482731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            // CHECK(!mDefaultValue);
483731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            // WARN_IF(!default_); // could be nullptr if OOM
484731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            // technically, this could be in the parent
485731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            *mTypedParam = std::shared_ptr<T>(T::From(C2Param::Copy(*default_).release()));
486731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            setDefaultValue(default_);
487731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            std::shared_ptr<T> *typedParam = mTypedParam;
488731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            setGetter([typedParam](bool) -> std::shared_ptr<C2Param> {
489731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                return std::static_pointer_cast<C2Param>(*typedParam);
490731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            });
491731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            return *this;
492731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        }
493731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
494731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /** Adds default value. Must be added exactly once. */
495731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        inline ParamBuilder &withDefault(T *default_) {
496731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            return withDefault(std::shared_ptr<T>(default_));
497731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        }
498731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
499731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /** Adds all fields to this parameter with their possible values. */
500731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        inline ParamBuilder &withFields(std::vector<C2ParamFieldValues> &&fields_) {
5019556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar            setFields(std::move(fields_));
502731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            return *this;
503731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        }
504731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
505731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /**
506731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * Adds a constant value (also as default). Must be added exactly once.
507731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         *
508731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * Const parameters by definition have no dependencies.
509731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         */
510731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        inline ParamBuilder &withConstValue(std::shared_ptr<T> default_) {
511731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            attrib() |= attrib_t::IS_CONST;
5129556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar            setSetter([default_](
5139556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar                    const C2Param *value, bool mayBlock __unused, bool *changed, Factory &) -> C2R {
514731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                *changed = false;
515731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                const T *typedValue = T::From(value);
516731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                if (typedValue == nullptr) {
517731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                    return C2R::Corrupted(); // TODO BadValue/Invalid. This should not happen here.
518731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                }
519731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                if (*typedValue != *default_) {
520731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                    return C2R::Corrupted(); // TODO ReadOnly(*default_);
521731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                }
522731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                *changed = false;
523731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                return C2R::Ok();
524731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            });
525731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            return withDefault(default_);
526731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        }
527731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
528731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /** Adds constant value (also as default). Must be added exactly once. */
529731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        inline ParamBuilder &withConstValue(T *default_) {
530731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            return withConstValue(std::shared_ptr<T>(default_));
531731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        }
532731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
533731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /**
534731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * Use a strict setter.
535731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         *
536731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \param fn   strict setter
537731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \param deps dependencies (references)
538731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         */
539731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        template<typename ... Deps>
540731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        inline ParamBuilder &withSetter(
541731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                C2R (*fn)(bool, const C2P<T> &, C2P<T> &, const C2P<Deps> &...),
542731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                std::shared_ptr<Deps>& ... deps) {
543731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            attrib() |= attrib_t::IS_STRICT;
544731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            std::shared_ptr<T> *typedParam = mTypedParam;
5459556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar            setSetter([typedParam, fn, &deps...](
5469556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar                    const C2Param *value, bool mayBlock, bool *changed, Factory &factory) -> C2R {
547731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                *changed = false;
548731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                const T *typedValue = T::From(value);
549731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                if (typedValue == nullptr) {
550731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                    return C2R::Corrupted(); // TODO BadValue/Invalid. This should not happen here.
551731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                }
552731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                // Do copy-on-change for parameters in this helper so change can be detected by
553731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                // a change of the pointer. Do this by working on a proposed value.
554731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                std::shared_ptr<T> proposedValue =
555731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                    std::shared_ptr<T>(T::From(C2Param::Copy(*value).release()));
556731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                if (proposedValue == nullptr) {
557731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                    return C2R::NoMemory(value->index());
558731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                }
5599556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar                C2P<T> oldValue = factory.get(*typedParam);
560731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                // Get a parameter helper with value pointing to proposedValue
5619556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar                C2P<T> helper = factory.get(*typedParam, proposedValue);
5629556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar                C2R result = fn(mayBlock, oldValue, helper, factory.get(deps)...);
563731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
564731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                // If value changed, copy result to current value
565731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                if (helper.get() != *typedParam->get()) {
566731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                    *typedParam = proposedValue;
567731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                    *changed = true;
568731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                }
569731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                return result;
570731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            });
571731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            setDependencies(std::vector<C2Param::Index>{ deps->index()... },
572731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                            std::vector<ParamRef>{ ParamRef(deps)... });
573731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            return *this;
574731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        }
575731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
576731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /**
577731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * Use a non-strict setter.
578731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         *
579731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \param fn   non-strict setter
580731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \param deps dependencies (references)
581731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         */
582731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        template<typename ... Deps>
583731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        inline ParamBuilder &withSetter(
584731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                C2R (*fn)(bool, C2P<T> &, const C2P<Deps> &...), std::shared_ptr<Deps>& ... deps) {
585731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            std::shared_ptr<T> *typedParam = mTypedParam;
5869556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar            setSetter([typedParam, fn, &deps...](
5879556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar                    const C2Param *value, bool mayBlock, bool *changed, Factory &factory) -> C2R {
588731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                *changed = false;
589731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                const T *typedValue = T::From(value);
590731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                if (typedValue == nullptr) {
591731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                    return C2R::Corrupted(); // TODO BadValue/Invalid. This should not happen here.
592731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                }
593731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                // Do copy-on-change for parameters in this helper so change can be detected by
594731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                // a change of the pointer. Do this by working on a proposed value.
595731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                std::shared_ptr<T> proposedValue =
596731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                    std::shared_ptr<T>(T::From(C2Param::Copy(*value).release()));
597731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                if (proposedValue == nullptr) {
598731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                    return C2R::NoMemory(value->index());
599731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                }
600731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                // Get a parameter helper with value pointing to proposedValue
6019556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar                C2P<T> helper = factory.get(*typedParam, proposedValue);
6029556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar                C2R result = fn(mayBlock, helper, factory.get(deps)...);
603731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
604731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                // If value changed, copy result to current value
605731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                if (helper.get() != *typedParam->get()) {
606731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                    *typedParam = proposedValue;
607731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                    *changed = true;
608731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                }
609731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                return result;
610731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            });
611731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            setDependencies(std::vector<C2Param::Index>{ deps->index()... },
612731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                            std::vector<ParamRef>{ ParamRef(deps)... });
613731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            return *this;
614731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        }
615731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
616731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        /**
617731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * Marks this a calculated (read-only) field.
618731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         *
619731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \param fn   non-strict setter (calculator)
620731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         * \param deps dependencies (references)
621731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar         */
622731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        template<typename ... Deps>
623731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        inline ParamBuilder &calculatedAs(
624731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar                C2R (*fn)(bool, C2P<T> &, const C2P<Deps> &...), std::shared_ptr<Deps>& ... deps) {
625731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            attrib() |= attrib_t::IS_READ_ONLY;
6268274782aab7f743fc7bf83c344555db03f788a79Lajos Molnar            return withSetter(fn, std::forward<decltype(deps)>(deps)...);
627731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        }
628731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
629731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        inline std::shared_ptr<ParamHelper> build() {
630731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            return ParamHelper::build();
631731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        }
632731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
633731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    protected:
634731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        std::shared_ptr<T> *mTypedParam;
635731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    };
636731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
6379556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar    template<typename T>
6389556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar    static ParamBuilder<T> DefineParam(std::shared_ptr<T> &param, C2StringLiteral name) {
6399556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar        return ParamBuilder<T>(param, name);
6409556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar    }
6419556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar
642731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnarpublic:
643731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    c2_status_t query(
644731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            const std::vector<C2Param*> &stackParams,
645731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            const std::vector<C2Param::Index> &heapParamIndices,
646731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            c2_blocking_t mayBlock,
647731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            std::vector<std::unique_ptr<C2Param>>* const heapParams) const;
648731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
649567d452560fc8a36f08ee9d259904d8067b70fcaLajos Molnar    /**
650567d452560fc8a36f08ee9d259904d8067b70fcaLajos Molnar     * Helper implementing config calls as well as other configuration updates.
651567d452560fc8a36f08ee9d259904d8067b70fcaLajos Molnar     *
652567d452560fc8a36f08ee9d259904d8067b70fcaLajos Molnar     * \param params
653567d452560fc8a36f08ee9d259904d8067b70fcaLajos Molnar     * \param mayBlock
654567d452560fc8a36f08ee9d259904d8067b70fcaLajos Molnar     * \param failures
655567d452560fc8a36f08ee9d259904d8067b70fcaLajos Molnar     * \param updateParams if true, the updated parameter values are copied back into the arguments
656567d452560fc8a36f08ee9d259904d8067b70fcaLajos Molnar     *                     passed in |params|
657567d452560fc8a36f08ee9d259904d8067b70fcaLajos Molnar     * \param changes      pointed to a vector to receive settings with their values changed. If not
658567d452560fc8a36f08ee9d259904d8067b70fcaLajos Molnar     *                     null, settings with their values changed are added to this.
659567d452560fc8a36f08ee9d259904d8067b70fcaLajos Molnar     * \return result from config
660567d452560fc8a36f08ee9d259904d8067b70fcaLajos Molnar     */
661731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    c2_status_t config(
6629556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar            const std::vector<C2Param*> &params, c2_blocking_t mayBlock,
6639556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar            std::vector<std::unique_ptr<C2SettingResult>>* const failures,
664567d452560fc8a36f08ee9d259904d8067b70fcaLajos Molnar            bool updateParams = true,
6659556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar            std::vector<std::shared_ptr<C2Param>> *changes = nullptr);
666731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
6679556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar    c2_status_t querySupportedParams(
6689556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar            std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const;
669731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
670731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    c2_status_t querySupportedValues(
671731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            std::vector<C2FieldSupportedValuesQuery> &fields, c2_blocking_t mayBlock) const;
672731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
673731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    std::shared_ptr<C2ReflectorHelper> getReflector() {
674731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        return mReflector;
675731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    }
676731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
677731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnarprivate:
678731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    void setInterfaceAddressBounds(uintptr_t start, uintptr_t end) {
679731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        // TODO: exclude this helper
680731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        (void)start;
681731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        (void)end;
682731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    }
683731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
684731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnarprotected:
685731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    std::shared_ptr<C2ReflectorHelper> mReflector;
6869556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar    struct FactoryImpl;
6879556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar    std::shared_ptr<FactoryImpl> _mFactory;
688731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
6899556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar    C2InterfaceHelper(std::shared_ptr<C2ReflectorHelper> reflector);
690731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
6919556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar    /**
6929556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar     * Adds a parameter to this interface.
6939556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar     * \note This method CHECKs.
6949556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar     *
6959556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar     * \param param parameter to add.
6969556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar     */
6979556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar    void addParameter(std::shared_ptr<ParamHelper> param);
698731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
6999556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar    /**
7009556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar     * Returns the dependency index for a parameter.
7019556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar     *
7029556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar     * \param ix the index of the parameter
7039556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar     */
7049556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar    size_t getDependencyIndex(C2Param::Index ix) const;
705731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
7069fca24013957d2dfe99b4291f9f9297f720c7fa8Wonsik Kim    virtual ~C2InterfaceHelper() = default;
7079fca24013957d2dfe99b4291f9f9297f720c7fa8Wonsik Kim
708731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    /**
709731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * Sets subclass instance's address and size.
710731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     *
711731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     * \todo allow subclass to specify parameter address range directly (e.g. do not assume that
712731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     *       they are local to the subclass instance)
713731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     *
7149556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar     * \param T type of the derived instance
7159556908781ead9a85000091e97d8df76a060a3a3Lajos Molnar     * \param instance pointer to the derived instance
716731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar     */
717731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    template<typename T>
718731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    inline C2_HIDE void setDerivedInstance(T *instance) {
719731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar        setInterfaceAddressBounds((uintptr_t)instance, (uintptr_t)(instance + 1));
720731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    }
721731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
722731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    C2_DO_NOT_COPY(C2InterfaceHelper);
723731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar};
724731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
725731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar/**
726731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar * Creates a C2ParamFieldValuesBuilder class for a field of a parameter
727731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar *
728731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar * \param spParam a configuration parameter in an interface class subclassed from C2InterfaceHelper.
729731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar * \param field   a field of such parameter
730731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar */
731731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar#define C2F(spParam, field) \
732731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar    C2ParamFieldValuesBuilder< \
733731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar            typename _c2_reduce_enum_to_underlying_type< \
7344368da47147829593cad97293d9d698fbc911effLajos Molnar                    typename std::remove_reference< \
7354368da47147829593cad97293d9d698fbc911effLajos Molnar                            typename std::remove_extent< \
7364368da47147829593cad97293d9d698fbc911effLajos Molnar                                    decltype(spParam->field)>::type>::type>::type>( \
7374368da47147829593cad97293d9d698fbc911effLajos Molnar                                            C2ParamField(spParam.get(), &spParam->field))
738731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar
739731ddf6772e099ce0eef38d6113714a08bb60301Lajos Molnar#endif  // C2UTILS_INTERFACE_HELPER_H_
740