Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef C2UTILS_INTERFACE_HELPER_H_
     18 #define C2UTILS_INTERFACE_HELPER_H_
     19 
     20 #include <C2Component.h>
     21 #include <util/C2InterfaceUtils.h>
     22 
     23 #include <map>
     24 #include <vector>
     25 
     26 #include <stddef.h>
     27 
     28 /**
     29  * Interface Helper
     30  */
     31 using C2R = C2SettingResultsBuilder;
     32 
     33 template<typename T, bool E=std::is_enum<T>::value>
     34 struct _c2_reduce_enum_to_underlying_type {
     35     typedef T type;
     36 };
     37 
     38 template<typename T>
     39 struct _c2_reduce_enum_to_underlying_type<T, true> {
     40     typedef typename std::underlying_type<T>::type type;
     41 };
     42 
     43 /**
     44  * Helper class to implement parameter reflectors. This class is dynamic and is designed to be
     45  * shared by multiple interfaces. This allows interfaces to add structure descriptors as needed.
     46  */
     47 class C2ReflectorHelper : public C2ParamReflector {
     48 public:
     49     C2ReflectorHelper() = default;
     50     virtual ~C2ReflectorHelper() = default;
     51     virtual std::unique_ptr<C2StructDescriptor> describe(
     52             C2Param::CoreIndex paramIndex) const override;
     53 
     54     /**
     55      * Adds support for describing the given parameters.
     56      *
     57      * \param Params types of codec 2.0 structs (or parameters) to describe
     58      */
     59     template<typename... Params>
     60     C2_INLINE void addStructDescriptors() {
     61         std::vector<C2StructDescriptor> structs;
     62         addStructDescriptors(structs, (_Tuple<Params...> *)nullptr);
     63     }
     64 
     65     /**
     66      * Adds support for describing a specific struct.
     67      *
     68      * \param strukt descriptor for the struct that will be moved out.
     69      */
     70     void addStructDescriptor(C2StructDescriptor &&strukt);
     71 
     72 private:
     73     template<typename... Params>
     74     class C2_HIDE _Tuple { };
     75 
     76     /**
     77      * Adds support for describing the given descriptors.
     78      *
     79      * \param structs List of structure descriptors to add support for
     80      */
     81     void addStructDescriptors(
     82             std::vector<C2StructDescriptor> &structs, _Tuple<> *);
     83 
     84     /**
     85      * Utility method that adds support for describing the given descriptors in a recursive manner
     86      * one structure at a time using a list of structure descriptors temporary.
     87      *
     88      * \param T the type of codec 2.0 struct to describe
     89      * \param Params rest of the structs
     90      * \param structs Temporary list of structure descriptors used to optimize the operation.
     91      */
     92     template<typename T, typename... Params>
     93     C2_INLINE void addStructDescriptors(
     94             std::vector<C2StructDescriptor> &structs, _Tuple<T, Params...> *) {
     95         structs.emplace_back((T*)nullptr);
     96         addStructDescriptors(structs, (_Tuple<Params...> *)nullptr);
     97     }
     98 
     99     mutable std::mutex _mMutex;
    100     std::map<C2Param::CoreIndex, const C2StructDescriptor> _mStructs; ///< descriptors
    101 };
    102 
    103 /**
    104  * Utility class that implements the codec 2.0 interface API-s for some parameters.
    105  *
    106  * This class must be subclassed.
    107  */
    108 class C2InterfaceHelper {
    109 public:
    110     /**
    111      * Returns the base offset of a field at |offset| that could be part of an array or part of a
    112      * sub-structure.
    113      *
    114      * This method does not do field size verification, e.g. if offset if obtained from a structure,
    115      * it will not stop at the structure boundary - this is okay, as we just want the base offset
    116      * here, which is the same.
    117      */
    118     static
    119     size_t GetBaseOffset(const std::shared_ptr<C2ParamReflector> &reflector,
    120                                 C2Param::CoreIndex index, size_t offset);
    121 
    122     /**
    123      * The interface helper class uses references to std::shared_ptr<T> config parameters.
    124      * Internally, these need to be generalized to std::shared_ptr<C2Param> refs, but the cast is
    125      * not allowed (as these are references). As such, this class never returns pointer to the
    126      * shared_ptrs.
    127      */
    128     struct ParamRef {
    129         template<typename T, typename enable=
    130                 typename std::enable_if<std::is_convertible<T, C2Param>::value>::type>
    131         inline C2_HIDE ParamRef(std::shared_ptr<T> &param)
    132             : _mRef(reinterpret_cast<std::shared_ptr<C2Param>*>(&param)) { }
    133 
    134         // used by comparison operator for containers
    135         operator std::shared_ptr<C2Param> *() const { return _mRef; }
    136 
    137         /**
    138          * Returns a shared pointer to the parameter.
    139          */
    140         std::shared_ptr<C2Param> get() const { return *_mRef; }
    141 
    142     private:
    143         std::shared_ptr<C2Param> *_mRef;
    144     };
    145 
    146     /**
    147      * Field helper.
    148      *
    149      * Contains additional information for the field: possible values, and currently supported
    150      * values.
    151      */
    152     class FieldHelper {
    153     public:
    154         /**
    155          * Creates helper for a field with given possible values.
    156          *
    157          * \param param parameter reference. The parameter does not have to be initialized at this
    158          *        point.
    159          * \param field field identifier
    160          * \param values possible values for the field
    161          */
    162         FieldHelper(const ParamRef &param, const _C2FieldId &field,
    163                     std::unique_ptr<C2FieldSupportedValues> &&values);
    164 
    165         /**
    166          * Creates a param-field identifier for this field. This method is called after the
    167          * underlying parameter has been initialized.
    168          *
    169          * \aram index
    170          *
    171          * @return C2ParamField
    172          */
    173         C2ParamField makeParamField(C2Param::Index index) const;
    174 
    175         /**
    176          * Sets the currently supported values for this field.
    177          *
    178          * \param values currently supported values that will be moved out
    179          */
    180         void setSupportedValues(std::unique_ptr<C2FieldSupportedValues> &&values);
    181 
    182         /**
    183          * Gets the currently supported values for this field. This defaults to the possible values
    184          * if currently supported values were never set.
    185          */
    186         const C2FieldSupportedValues *getSupportedValues() const;
    187 
    188         /**
    189          * Gets the possible values for this field.
    190          */
    191         const C2FieldSupportedValues *getPossibleValues() const;
    192 
    193     protected:
    194         // TODO: move to impl for safety
    195         ParamRef mParam;
    196         _C2FieldId mFieldId;
    197         std::unique_ptr<C2FieldSupportedValues> mPossible;
    198         std::unique_ptr<C2FieldSupportedValues> mSupported; ///< if different from possible
    199     };
    200 
    201     template<typename T>
    202     struct C2_HIDE Param;
    203     class ParamHelper;
    204 
    205     /**
    206      * Factory is an interface to get the parameter helpers from a std::shared_ptr<T> &.
    207      */
    208     class Factory {
    209         // \todo this may be already in ParamHelper
    210         virtual std::shared_ptr<C2ParamReflector> getReflector() const = 0;
    211 
    212         virtual std::shared_ptr<ParamHelper> getParamHelper(const ParamRef &param) const = 0;
    213 
    214     public:
    215         virtual ~Factory() = default;
    216 
    217         template<typename T>
    218         Param<T> get(std::shared_ptr<T> &param, std::shared_ptr<T> altValue = nullptr) const {
    219             return Param<T>(getParamHelper(ParamRef(param)),
    220                             altValue == nullptr ? param : altValue,
    221                             getReflector());
    222         }
    223     };
    224 
    225     /**
    226      * Typed field helper.
    227      */
    228     template<typename T>
    229     struct Field {
    230         /**
    231          * Constructor.
    232          *
    233          * \param helper helper for this field
    234          * \param index  parameter index (this is needed as it is not available during parameter
    235          *        construction) \todo remove
    236          */
    237         Field(std::shared_ptr<FieldHelper> helper, C2Param::Index index);
    238 
    239         bool supportsAtAll(T value) const {
    240             return C2FieldSupportedValuesHelper<T>(*_mHelper->getPossibleValues()).supports(value);
    241         }
    242 
    243         bool supportsNow(T value) const {
    244             return C2FieldSupportedValuesHelper<T>(*_mHelper->getSupportedValues()).supports(value);
    245         }
    246 
    247         /**
    248          * Creates a conflict resolution suggestion builder for this field.
    249          */
    250         C2ParamFieldValuesBuilder<T> shouldBe() const;
    251 
    252         /**
    253          * Creates a currently supported values builder for this field. This is only supported
    254          * for non-const fields to disallow setting supported values for dependencies.
    255          */
    256         C2ParamFieldValuesBuilder<T> mustBe();
    257 
    258         operator C2ParamField() const {
    259             return _mField;
    260         }
    261 
    262         // TODO
    263         C2R validatePossible(const T &value __unused) const {
    264             /// TODO
    265             return C2R::Ok();
    266         }
    267 
    268     private:
    269         std::shared_ptr<FieldHelper> _mHelper;
    270         C2ParamField _mField;
    271     };
    272 
    273     class ParamHelper {
    274     public:
    275         ParamHelper(ParamRef param, C2StringLiteral name, C2StructDescriptor &&);
    276         ParamHelper(ParamHelper &&);
    277         ~ParamHelper();
    278 
    279         /**
    280          * Finds a field descriptor.
    281          */
    282         std::shared_ptr<FieldHelper> findField(size_t baseOffs, size_t baseSize) const;
    283 
    284         /// returns the parameter ref for this parameter
    285         const ParamRef ref() const;
    286 
    287         /// returns the current value of this parameter as modifiable. The constness of this
    288         /// object determines the constness of the returned value.
    289         std::shared_ptr<C2Param> value();
    290 
    291         /// returns the current value of this parameter as const
    292         std::shared_ptr<const C2Param> value() const;
    293 
    294         /**
    295          * Performs a configuration change request for this parameter.
    296          *
    297          * \param value    the value that is being assigned to this parameter.
    298          *                 This could be pointing to the current value of the
    299          *                 parameter. This must not change.
    300          * \param mayBlock whether blocking is allowed
    301          * \param endValue the resulting value
    302          * \param factory  parameter factory (to access dependencies)
    303          * \param failures vector of failures to append any failures from this
    304          *                 operation
    305          *
    306          * \retval C2_OK        configuration was successful
    307          * \retval C2_BAD_VALUE value is incorrect (TBD)
    308          * \retval C2_NO_MEMORY not enough memory to perform the assignment
    309          * \retval C2_TIMED_OUT configuration timed out
    310          * \retval C2_BLOCKING  configuration requires blocking to be allowed
    311          * \retval C2_CORRUPTED interface is corrupted
    312          */
    313         c2_status_t trySet(
    314                 const C2Param *value, bool mayBlock,
    315                 bool *changed,
    316                 Factory &factory,
    317                 std::vector<std::unique_ptr<C2SettingResult>>* const failures);
    318 
    319         /// returns parameter indices that depend on this parameter
    320         const std::vector<C2Param::Index> getDownDependencies() const;
    321 
    322         /// adds a dependent parameter
    323         void addDownDependency(C2Param::Index index);
    324 
    325         /// returns that parameter refs for parameters that depend on this
    326         const std::vector<ParamRef> getDependenciesAsRefs() const;
    327 
    328         /// returns and moves out stored struct descriptor
    329         C2StructDescriptor retrieveStructDescriptor();
    330 
    331         /// returns the name of this parameter
    332         C2String name() const;
    333 
    334         /// returns the index of this parameter
    335         C2Param::Index index() const;
    336 
    337         /// returns the parameter descriptor
    338         std::shared_ptr<const C2ParamDescriptor> getDescriptor() const;
    339 
    340         /**
    341          * Validates param helper.
    342          *
    343          * For now, this fills field info for const params.
    344          *
    345          * \retval C2_CORRUPTED the parameter cannot be added as such
    346          */
    347         c2_status_t validate(const std::shared_ptr<C2ParamReflector> &reflector);
    348 
    349     protected:
    350         typedef C2ParamDescriptor::attrib_t attrib_t;
    351         attrib_t& attrib();
    352 
    353         /// sets the default value of this parameter
    354         void setDefaultValue(std::shared_ptr<C2Param> default_);
    355 
    356         /// sets the setter method
    357         void setSetter(std::function<C2R(const C2Param *, bool, bool *, Factory &)> setter);
    358 
    359         /// sets the getter method
    360         void setGetter(std::function<std::shared_ptr<C2Param>(bool)> getter);
    361 
    362         /// sets the dependencies
    363         void setDependencies(std::vector<C2Param::Index> indices, std::vector<ParamRef> refs);
    364 
    365         /// sets the fields and their supported values
    366         void setFields(std::vector<C2ParamFieldValues> &&fields);
    367 
    368         /// build this into a final ParamHelper object
    369         std::shared_ptr<ParamHelper> build();
    370 
    371         class Impl;
    372         std::unique_ptr<Impl> mImpl;
    373     };
    374 
    375     /**
    376      * Typed parameter helper. This provides access to members as well as field helpers.
    377      */
    378     template<typename T>
    379     struct C2_HIDE Param {
    380         Param(
    381                 std::shared_ptr<ParamHelper> helper, std::shared_ptr<T> &param,
    382                 std::shared_ptr<C2ParamReflector> reflector)
    383             : v(*param.get()),
    384               _mTypedParam(param),
    385               _mHelper(helper),
    386               _mReflector(reflector) { }
    387 
    388         template<typename S>
    389         using FieldType = Field<
    390                 typename _c2_reduce_enum_to_underlying_type<
    391                         typename std::remove_const<
    392                                 typename std::remove_extent<S>::type>::type>::type>;
    393 
    394         template<typename S>
    395         FieldType<S> F(S &field) {
    396             size_t offs = (uintptr_t)&field - (uintptr_t)&get();
    397             // this must fall either within sizeof(T) + FLEX_SIZE or param->size()
    398             // size_t size = sizeof(field);
    399             // mParam may be null
    400             size_t baseSize = sizeof(typename std::remove_extent<S>::type);
    401             size_t baseOffs = GetBaseOffset(
    402                     _mReflector, T::CORE_INDEX, offs - sizeof(C2Param));
    403             if (~baseOffs == 0) {
    404                 // C2_LOG(FATAL) << "unknown field at offset " << offs << " size " << sizeof(S)
    405                 //       << " base-size " << baseSize;
    406                 // __builtin_trap();
    407             } else {
    408                 baseOffs += sizeof(C2Param);
    409             }
    410 
    411             std::shared_ptr<FieldHelper> helper = _mHelper->findField(baseOffs, baseSize);
    412             return FieldType<S>(helper, _mTypedParam->index());
    413         }
    414 
    415         // const Param have const Fields; however, remove const from S
    416         template<typename S>
    417         const FieldType<S> F(S &field) const {
    418             return const_cast<const FieldType<S>>(const_cast<Param *>(this)->F(field));
    419         }
    420 
    421         /// Returns a const ref value of this const param.
    422         const T &get() const {
    423             return *_mTypedParam.get();
    424         }
    425 
    426         /// Returns a modifiable ref value of this non-const param.
    427         T &set() {
    428             return *_mTypedParam.get();
    429         }
    430 
    431         /// Const-reference to the value.s
    432         T const &v;
    433 
    434     private:
    435         std::shared_ptr<T> _mTypedParam;
    436         std::shared_ptr<ParamHelper> _mHelper;
    437         std::shared_ptr<C2ParamReflector> _mReflector;
    438     };
    439 
    440     template<typename T>
    441     using C2P = Param<T>;
    442 
    443     /**
    444      * Templated move builder class for a parameter helper.
    445      */
    446     template<typename T>
    447     class C2_HIDE ParamBuilder : private ParamHelper {
    448     public:
    449         /** Construct the parameter builder from minimal info required. */
    450         ParamBuilder(std::shared_ptr<T> &param, C2StringLiteral name)
    451             : ParamHelper(param, name, C2StructDescriptor((T*)nullptr)),
    452               mTypedParam(&param) {
    453             attrib() = attrib_t::IS_PERSISTENT;
    454         }
    455 
    456         /** Makes this parameter required. */
    457         inline ParamBuilder &required() {
    458             attrib() |= attrib_t::IS_REQUIRED;
    459             return *this;
    460         }
    461 
    462         /** Makes this parameter transient (not persistent). */
    463         inline ParamBuilder &transient() {
    464             attrib() &= ~attrib_t::IS_PERSISTENT;
    465             return *this;
    466         }
    467 
    468         /** Makes this parameter hidden (not exposed in JAVA API). */
    469         inline ParamBuilder &hidden() {
    470             attrib() |= attrib_t::IS_HIDDEN;
    471             return *this;
    472         }
    473 
    474         /** Makes this parameter internal (not exposed to query/settings). */
    475         inline ParamBuilder &internal() {
    476             attrib() |= attrib_t::IS_INTERNAL;
    477             return *this;
    478         }
    479 
    480         /** Adds default value. Must be added exactly once. */
    481         inline ParamBuilder &withDefault(std::shared_ptr<T> default_) {
    482             // CHECK(!mDefaultValue);
    483             // WARN_IF(!default_); // could be nullptr if OOM
    484             // technically, this could be in the parent
    485             *mTypedParam = std::shared_ptr<T>(T::From(C2Param::Copy(*default_).release()));
    486             setDefaultValue(default_);
    487             std::shared_ptr<T> *typedParam = mTypedParam;
    488             setGetter([typedParam](bool) -> std::shared_ptr<C2Param> {
    489                 return std::static_pointer_cast<C2Param>(*typedParam);
    490             });
    491             return *this;
    492         }
    493 
    494         /** Adds default value. Must be added exactly once. */
    495         inline ParamBuilder &withDefault(T *default_) {
    496             return withDefault(std::shared_ptr<T>(default_));
    497         }
    498 
    499         /** Adds all fields to this parameter with their possible values. */
    500         inline ParamBuilder &withFields(std::vector<C2ParamFieldValues> &&fields_) {
    501             setFields(std::move(fields_));
    502             return *this;
    503         }
    504 
    505         /**
    506          * Adds a constant value (also as default). Must be added exactly once.
    507          *
    508          * Const parameters by definition have no dependencies.
    509          */
    510         inline ParamBuilder &withConstValue(std::shared_ptr<T> default_) {
    511             attrib() |= attrib_t::IS_CONST;
    512             setSetter([default_](
    513                     const C2Param *value, bool mayBlock __unused, bool *changed, Factory &) -> C2R {
    514                 *changed = false;
    515                 const T *typedValue = T::From(value);
    516                 if (typedValue == nullptr) {
    517                     return C2R::Corrupted(); // TODO BadValue/Invalid. This should not happen here.
    518                 }
    519                 if (*typedValue != *default_) {
    520                     return C2R::Corrupted(); // TODO ReadOnly(*default_);
    521                 }
    522                 *changed = false;
    523                 return C2R::Ok();
    524             });
    525             return withDefault(default_);
    526         }
    527 
    528         /** Adds constant value (also as default). Must be added exactly once. */
    529         inline ParamBuilder &withConstValue(T *default_) {
    530             return withConstValue(std::shared_ptr<T>(default_));
    531         }
    532 
    533         /**
    534          * Use a strict setter.
    535          *
    536          * \param fn   strict setter
    537          * \param deps dependencies (references)
    538          */
    539         template<typename ... Deps>
    540         inline ParamBuilder &withSetter(
    541                 C2R (*fn)(bool, const C2P<T> &, C2P<T> &, const C2P<Deps> &...),
    542                 std::shared_ptr<Deps>& ... deps) {
    543             attrib() |= attrib_t::IS_STRICT;
    544             std::shared_ptr<T> *typedParam = mTypedParam;
    545             setSetter([typedParam, fn, &deps...](
    546                     const C2Param *value, bool mayBlock, bool *changed, Factory &factory) -> C2R {
    547                 *changed = false;
    548                 const T *typedValue = T::From(value);
    549                 if (typedValue == nullptr) {
    550                     return C2R::Corrupted(); // TODO BadValue/Invalid. This should not happen here.
    551                 }
    552                 // Do copy-on-change for parameters in this helper so change can be detected by
    553                 // a change of the pointer. Do this by working on a proposed value.
    554                 std::shared_ptr<T> proposedValue =
    555                     std::shared_ptr<T>(T::From(C2Param::Copy(*value).release()));
    556                 if (proposedValue == nullptr) {
    557                     return C2R::NoMemory(value->index());
    558                 }
    559                 C2P<T> oldValue = factory.get(*typedParam);
    560                 // Get a parameter helper with value pointing to proposedValue
    561                 C2P<T> helper = factory.get(*typedParam, proposedValue);
    562                 C2R result = fn(mayBlock, oldValue, helper, factory.get(deps)...);
    563 
    564                 // If value changed, copy result to current value
    565                 if (helper.get() != *typedParam->get()) {
    566                     *typedParam = proposedValue;
    567                     *changed = true;
    568                 }
    569                 return result;
    570             });
    571             setDependencies(std::vector<C2Param::Index>{ deps->index()... },
    572                             std::vector<ParamRef>{ ParamRef(deps)... });
    573             return *this;
    574         }
    575 
    576         /**
    577          * Use a non-strict setter.
    578          *
    579          * \param fn   non-strict setter
    580          * \param deps dependencies (references)
    581          */
    582         template<typename ... Deps>
    583         inline ParamBuilder &withSetter(
    584                 C2R (*fn)(bool, C2P<T> &, const C2P<Deps> &...), std::shared_ptr<Deps>& ... deps) {
    585             std::shared_ptr<T> *typedParam = mTypedParam;
    586             setSetter([typedParam, fn, &deps...](
    587                     const C2Param *value, bool mayBlock, bool *changed, Factory &factory) -> C2R {
    588                 *changed = false;
    589                 const T *typedValue = T::From(value);
    590                 if (typedValue == nullptr) {
    591                     return C2R::Corrupted(); // TODO BadValue/Invalid. This should not happen here.
    592                 }
    593                 // Do copy-on-change for parameters in this helper so change can be detected by
    594                 // a change of the pointer. Do this by working on a proposed value.
    595                 std::shared_ptr<T> proposedValue =
    596                     std::shared_ptr<T>(T::From(C2Param::Copy(*value).release()));
    597                 if (proposedValue == nullptr) {
    598                     return C2R::NoMemory(value->index());
    599                 }
    600                 // Get a parameter helper with value pointing to proposedValue
    601                 C2P<T> helper = factory.get(*typedParam, proposedValue);
    602                 C2R result = fn(mayBlock, helper, factory.get(deps)...);
    603 
    604                 // If value changed, copy result to current value
    605                 if (helper.get() != *typedParam->get()) {
    606                     *typedParam = proposedValue;
    607                     *changed = true;
    608                 }
    609                 return result;
    610             });
    611             setDependencies(std::vector<C2Param::Index>{ deps->index()... },
    612                             std::vector<ParamRef>{ ParamRef(deps)... });
    613             return *this;
    614         }
    615 
    616         /**
    617          * Marks this a calculated (read-only) field.
    618          *
    619          * \param fn   non-strict setter (calculator)
    620          * \param deps dependencies (references)
    621          */
    622         template<typename ... Deps>
    623         inline ParamBuilder &calculatedAs(
    624                 C2R (*fn)(bool, C2P<T> &, const C2P<Deps> &...), std::shared_ptr<Deps>& ... deps) {
    625             attrib() |= attrib_t::IS_READ_ONLY;
    626             return withSetter(fn, std::forward<decltype(deps)>(deps)...);
    627         }
    628 
    629         inline std::shared_ptr<ParamHelper> build() {
    630             return ParamHelper::build();
    631         }
    632 
    633     protected:
    634         std::shared_ptr<T> *mTypedParam;
    635     };
    636 
    637     template<typename T>
    638     static ParamBuilder<T> DefineParam(std::shared_ptr<T> &param, C2StringLiteral name) {
    639         return ParamBuilder<T>(param, name);
    640     }
    641 
    642 public:
    643     c2_status_t query(
    644             const std::vector<C2Param*> &stackParams,
    645             const std::vector<C2Param::Index> &heapParamIndices,
    646             c2_blocking_t mayBlock,
    647             std::vector<std::unique_ptr<C2Param>>* const heapParams) const;
    648 
    649     /**
    650      * Helper implementing config calls as well as other configuration updates.
    651      *
    652      * \param params
    653      * \param mayBlock
    654      * \param failures
    655      * \param updateParams if true, the updated parameter values are copied back into the arguments
    656      *                     passed in |params|
    657      * \param changes      pointed to a vector to receive settings with their values changed. If not
    658      *                     null, settings with their values changed are added to this.
    659      * \return result from config
    660      */
    661     c2_status_t config(
    662             const std::vector<C2Param*> &params, c2_blocking_t mayBlock,
    663             std::vector<std::unique_ptr<C2SettingResult>>* const failures,
    664             bool updateParams = true,
    665             std::vector<std::shared_ptr<C2Param>> *changes = nullptr);
    666 
    667     c2_status_t querySupportedParams(
    668             std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const;
    669 
    670     c2_status_t querySupportedValues(
    671             std::vector<C2FieldSupportedValuesQuery> &fields, c2_blocking_t mayBlock) const;
    672 
    673     std::shared_ptr<C2ReflectorHelper> getReflector() {
    674         return mReflector;
    675     }
    676 
    677 private:
    678     void setInterfaceAddressBounds(uintptr_t start, uintptr_t end) {
    679         // TODO: exclude this helper
    680         (void)start;
    681         (void)end;
    682     }
    683 
    684 protected:
    685     std::shared_ptr<C2ReflectorHelper> mReflector;
    686     struct FactoryImpl;
    687     std::shared_ptr<FactoryImpl> _mFactory;
    688 
    689     C2InterfaceHelper(std::shared_ptr<C2ReflectorHelper> reflector);
    690 
    691     /**
    692      * Adds a parameter to this interface.
    693      * \note This method CHECKs.
    694      *
    695      * \param param parameter to add.
    696      */
    697     void addParameter(std::shared_ptr<ParamHelper> param);
    698 
    699     /**
    700      * Returns the dependency index for a parameter.
    701      *
    702      * \param ix the index of the parameter
    703      */
    704     size_t getDependencyIndex(C2Param::Index ix) const;
    705 
    706     virtual ~C2InterfaceHelper() = default;
    707 
    708     /**
    709      * Sets subclass instance's address and size.
    710      *
    711      * \todo allow subclass to specify parameter address range directly (e.g. do not assume that
    712      *       they are local to the subclass instance)
    713      *
    714      * \param T type of the derived instance
    715      * \param instance pointer to the derived instance
    716      */
    717     template<typename T>
    718     inline C2_HIDE void setDerivedInstance(T *instance) {
    719         setInterfaceAddressBounds((uintptr_t)instance, (uintptr_t)(instance + 1));
    720     }
    721 
    722     C2_DO_NOT_COPY(C2InterfaceHelper);
    723 };
    724 
    725 /**
    726  * Creates a C2ParamFieldValuesBuilder class for a field of a parameter
    727  *
    728  * \param spParam a configuration parameter in an interface class subclassed from C2InterfaceHelper.
    729  * \param field   a field of such parameter
    730  */
    731 #define C2F(spParam, field) \
    732     C2ParamFieldValuesBuilder< \
    733             typename _c2_reduce_enum_to_underlying_type< \
    734                     typename std::remove_reference< \
    735                             typename std::remove_extent< \
    736                                     decltype(spParam->field)>::type>::type>::type>( \
    737                                             C2ParamField(spParam.get(), &spParam->field))
    738 
    739 #endif  // C2UTILS_INTERFACE_HELPER_H_
    740