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_UTILS_H_
     18 #define C2UTILS_INTERFACE_UTILS_H_
     19 
     20 #include <C2Param.h>
     21 #include <C2Work.h>
     22 
     23 #include <cmath>
     24 #include <iterator>
     25 #include <limits>
     26 #include <type_traits>
     27 
     28 /**
     29  * Helper class to map underlying types to C2Value types as well as to print field values. This is
     30  * generally the same as simply the underlying type except for characters (STRING) and bytes (BLOB).
     31  */
     32 template<typename T>
     33 struct C2_HIDE _C2FieldValueHelper {
     34     typedef T ValueType;
     35     inline static std::ostream& put(std::ostream &os, const C2Value::Primitive &p) {
     36         return os << p.ref<T>();
     37     }
     38 };
     39 
     40 template<>
     41 struct C2_HIDE _C2FieldValueHelper<uint8_t> {
     42     typedef uint32_t ValueType;
     43     static std::ostream& put(std::ostream &os, const C2Value::Primitive &p);
     44 };
     45 
     46 template<>
     47 struct C2_HIDE _C2FieldValueHelper<char> {
     48     typedef int32_t ValueType;
     49     static std::ostream& put(std::ostream &os, const C2Value::Primitive &p);
     50 };
     51 
     52 /**
     53  * Supported value range utility for a field of a given type.
     54  *
     55  * This mimics C2FieldSupportedValue for RANGE type.
     56  */
     57 template<typename T>
     58 class C2SupportedRange {
     59     typedef typename _C2FieldValueHelper<T>::ValueType ValueType;
     60 
     61 //private:
     62     constexpr static T MIN_VALUE = std::numeric_limits<T>::min();
     63     constexpr static T MAX_VALUE = std::numeric_limits<T>::max();
     64     constexpr static T MIN_STEP = std::is_floating_point<T>::value ? 0 : 1;
     65 
     66 public:
     67     /**
     68      * Constructs an empty range with no supported values.
     69      *
     70      * \note This is a specializated supported range representation that is only used for
     71      * this object - it is equivalent to the EMPTY type in C2FieldSupportedValues.
     72      */
     73     inline static constexpr C2SupportedRange<T> None() {
     74         return C2SupportedRange(MAX_VALUE, MIN_VALUE);
     75     }
     76 
     77     /**
     78      * Constructs a range with all values supported.
     79      */
     80     inline static constexpr C2SupportedRange<T> Any() {
     81         return C2SupportedRange(MIN_VALUE, MAX_VALUE);
     82     }
     83 
     84     /**
     85      * Constructs a range with a single supported value.
     86      *
     87      * \param value the sole supported value
     88      */
     89     inline static constexpr C2SupportedRange<T> EqualTo(T value) {
     90         return C2SupportedRange(value, value);
     91     }
     92 
     93     /**
     94      * Constructs a range with supported values greater than a given value.
     95      *
     96      * \param value the given value
     97      */
     98     inline static C2SupportedRange<T> GreaterThan(T value) {
     99         return (value == MAX_VALUE ? None() :
    100                 std::is_floating_point<T>::value ?
    101                         C2SupportedRange(std::nextafter(value, MAX_VALUE), MAX_VALUE) :
    102                         C2SupportedRange(value + MIN_STEP, MAX_VALUE));
    103     }
    104 
    105     /**
    106      * Constructs a range with supported values greater than or equal to a given value.
    107      *
    108      * \param value the given value
    109      */
    110     inline static constexpr C2SupportedRange<T> GreaterThanOrEqualTo(T value) {
    111         return C2SupportedRange(value, MAX_VALUE);
    112     }
    113 
    114     /**
    115      * Constructs a range with supported values greater than or equal to (aka not less than) a given
    116      * value.
    117      *
    118      * \param value the given value
    119      */
    120     inline static constexpr C2SupportedRange<T> NotLessThan(T value) {
    121         return GreaterThanOrEqualTo(value);
    122     }
    123 
    124     /**
    125      * Constructs a range with supported values less than or equal to a given value.
    126      *
    127      * \param value the given value
    128      */
    129     inline static constexpr C2SupportedRange<T> LessThanOrEqualTo(T value) {
    130         return C2SupportedRange(MIN_VALUE, value);
    131     }
    132 
    133     /**
    134      * Constructs a range with supported values less than or equal to (aka not greater than) a given
    135      * value.
    136      *
    137      * \param value the given value
    138      */
    139     inline static constexpr C2SupportedRange<T> NotGreaterThan(T value) {
    140         return LessThanOrEqualTo(value);
    141     }
    142 
    143     /**
    144      * Constructs a range with supported values less than a given value.
    145      *
    146      * \param value the given value
    147      */
    148     inline static C2SupportedRange<T> LessThan(T value) {
    149         return (value == MIN_VALUE ? None() :
    150                 std::is_floating_point<T>::value ?
    151                         C2SupportedRange(MIN_VALUE, std::nextafter(value, MIN_VALUE)) :
    152                         C2SupportedRange(MIN_VALUE, value - MIN_STEP));
    153     }
    154 
    155     /**
    156      * Constructs a continuous or arithmetic range between two values.
    157      *
    158      * \param min the lower value
    159      * \param max the higher value (if this is lower than |min| the range will be empty)
    160      * \param step the step of the arithmetic range. (If this is 0 for floating point types or 1 for
    161      *        integer types, the constructed range is continuous)
    162      */
    163     inline static constexpr
    164     C2SupportedRange<T> InRange(T min, T max, T step = MIN_STEP) {
    165         return C2SupportedRange(min, max, step);
    166     }
    167 
    168     /**
    169      * Constructs a range over a geometric series between two values.
    170      *
    171      * \param min the lower bound of the range. This value is always part of the constructed range
    172      *        as long as it is not greater than |max|.
    173      * \param max the upper bound of the range. This value is only part of the constructed
    174      *        range if it is part of the geometric series.
    175      * \param num the numerator of the geometric series.
    176      * \param denom the denominator of the geometric series.
    177      */
    178     inline static constexpr
    179     C2SupportedRange<T> InSeries(T min, T max, T num, T denom) {
    180         return C2SupportedRange(min, max, 0, num, denom);
    181     }
    182 
    183     /**
    184      * Constructs a range over a multiply-accumulate series between two values.
    185      *
    186      * \param min the lower bound of the range. This value is always part of the constructed range
    187      *        as long as it is not greater than |max|.
    188      * \param max the upper bound of the range. This value is only part of the constructed
    189      *        range if it is part of the series.
    190      * \param step the accumulator of the multiply-accumulate series
    191      * \param num the numerator of the multiply-accumulate series.
    192      * \param denom the denominator of the multiply-accumulate series.
    193      */
    194     inline static constexpr
    195     C2SupportedRange<T> InMacSeries(T min, T max, T step, T num, T denom) {
    196         return C2SupportedRange(min, max, step, num, denom);
    197     }
    198 
    199     /**
    200      * Constructs a range from a generic C2FieldSupportedValues object. This will be an empty
    201      * range if the supported values are not of RANGE type.
    202      *
    203      * \param values the supported values object
    204      */
    205     C2SupportedRange(const C2FieldSupportedValues &values);
    206 
    207     /**
    208      * Returns whether this range is empty.
    209      */
    210     inline constexpr bool isEmpty() const {
    211         return _mMin > _mMax;
    212     }
    213 
    214     /**
    215      * Returns whether this range is valid.
    216      *
    217      * Ranges are valid if they are continuous or monotonic.
    218      */
    219     inline constexpr bool isValid() const {
    220         // TODO: handle overflow or negative series
    221         return _mDenom > 0 && _mNum >= _mDenom && _mMin * (_mDenom - _mNum) < _mStep * _mDenom;
    222     }
    223 
    224     /**
    225      * Returns whether a value is part of this range.
    226      *
    227      * \param value the value to check.
    228      */
    229     bool contains(T value) const;
    230 
    231     /**
    232      * Returns a new range that is the intersection of this range and another, if it is
    233      * representable as a range object.
    234      *
    235      * \param limit the other range
    236      */
    237     C2SupportedRange<T> limitedTo(const C2SupportedRange<T> &limit) const;
    238 
    239     /**
    240      * Converts this object to a C2FieldSupportedValues object.
    241      */
    242     inline operator C2FieldSupportedValues() const {
    243         return C2FieldSupportedValues(_mMin, _mMax, _mStep, _mNum, _mDenom);
    244     }
    245 
    246     /**
    247      * Returns the lower bound and starting point of this range.
    248      */
    249     inline C2_HIDE constexpr T min() const   { return _mMin;   }
    250 
    251     /**
    252      * Returns the upper bound of this range.
    253      */
    254     inline C2_HIDE constexpr T max() const   { return _mMax;   }
    255 
    256     /**
    257      * Returns the step of this range.
    258      */
    259     inline C2_HIDE constexpr T step() const  { return _mStep;  }
    260 
    261     /**
    262      * Returns the numerator of this range.
    263      */
    264     inline C2_HIDE constexpr T num() const   { return _mNum;   }
    265 
    266     /**
    267      * Returns the denominator of this range.
    268      */
    269     inline C2_HIDE constexpr T denom() const { return _mDenom; }
    270 
    271 private:
    272     /**
    273      * Returns whether x[i...] is all values between _mMin and _mMax.
    274      */
    275     inline C2_HIDE constexpr bool isSimpleRange() const {
    276         return _mStep == MIN_STEP && _mNum == 1 && _mDenom == 1;
    277     }
    278 
    279     /**
    280      * Returns whether x[i...] is defined as such:
    281      * x[i + 1] = x[i] + _mStep, where _mStep > 0 and _mMin <= x[i] <= _mMax
    282      */
    283     inline C2_HIDE constexpr bool isArithmeticSeries() const {
    284         return _mStep > MIN_STEP && _mNum == 1 && _mDenom == 1;
    285     }
    286 
    287     /**
    288      * Returns whether x[i...] is defined as such:
    289      * x[i] = x[0] * (_mNum / _mDenom) ^ i (with rounding), where _mNum > _mDenom > 0 and x[0] > 0
    290      */
    291     inline C2_HIDE constexpr bool isGeometricSeries() const {
    292         return _mMin > 0 && _mStep == 0 && _mNum > _mDenom && _mDenom > 0;
    293     }
    294 
    295     /**
    296      * Returns whether x[i...] is defined as such:
    297      * x[i + 1] = x[i] * _mNum / _mDenom + _mStep (with rounding), while x[i + 1] > x[i], where
    298      * _mStep != 0, _mDenom > 0 and _mNum > 0
    299      */
    300     inline C2_HIDE constexpr bool isMacSeries() const {
    301         return _mStep != 0 && _mNum > 0 && _mDenom > 0;
    302     }
    303 
    304     /**
    305      * Constructs an arithmetic or continuous range.
    306      *
    307      * \param min the lower value
    308      * \param max the higher value (if this is lower than |min| the range will be empty)
    309      * \param step the step of the arithmetic range. (If this is 0 for floating point types or 1 for
    310      *        integer types, the constructed range is continuous)
    311      */
    312     constexpr C2_HIDE C2SupportedRange(T min, T max, T step = T(std::is_floating_point<T>::value ? 0 : 1))
    313         : _mMin(min), _mMax(max), _mStep(step), _mNum(1), _mDenom(1) { }
    314 
    315     /**
    316      * Constructs a range over a geomertic sor multiply-accumulate series.
    317      *
    318      * \param min the lower bound of the range. This value is always part of the constructed range
    319      *        as long as it is not greater than |max|.
    320      * \param max the upper bound of the range. This value is only part of the constructed
    321      *        range if it is part of the geometric series.
    322      * \param step the accumulator of the multiply-accumulate series. This is 0 for a pure geometric
    323      *        series
    324      * \param num the numerator of the geometric series.
    325      * \param denom the denominator of the geometric series.
    326      */
    327     constexpr C2_HIDE C2SupportedRange(T min, T max, T step, T num, T den)
    328         : _mMin(min), _mMax(max), _mStep(step), _mNum(num), _mDenom(den) { }
    329 
    330     T _mMin; ///< lower bound and starting point
    331     T _mMax; ///< upper bound
    332     T _mStep; ///< step of an arithmetic series (0 if continuous floating point range)
    333     T _mNum; ///< numerator of a geometric series
    334     T _mDenom; ///< denominator of a geometric series
    335 };
    336 
    337 /**
    338  * Ordered supported flag set for a field of a given type.
    339  */
    340 template<typename T>
    341 class C2SupportedFlags {
    342     typedef typename _C2FieldValueHelper<T>::ValueType ValueType;
    343 
    344 public:
    345     /**
    346      * Constructs an empty flag set.
    347      *
    348      * \note This is a specializated supported flags representation that is only used for
    349      * this object - it is equivalent to the EMPTY type in C2FieldSupportedValues.
    350      */
    351     static inline C2SupportedFlags<T> None() {
    352         return C2SupportedFlags(std::initializer_list<C2Value::Primitive>());
    353     }
    354 
    355     /**
    356      * Constructs a flags set of given flags.
    357      *
    358      * \param flags the ordered set of flags as an initializer list.
    359      * \param min minimum set of flags to be set.
    360      */
    361     static inline C2SupportedFlags<T> Flags(const std::initializer_list<T> flags, T min = T(0)) {
    362         return C2SupportedFlags(min, flags);
    363     }
    364 
    365     /**
    366      * Constructs a flags set of given flags.
    367      *
    368      * \param flags the ordered set of flags.
    369      * \param min minimum set of flags to be set.
    370      */
    371     static inline C2SupportedFlags<T> Flags(const std::vector<T> &flags, T min = T(0)) {
    372         return C2SupportedFlags(min, flags);
    373     }
    374 
    375     /**
    376      * Constructs a flag set from a generic C2FieldSupportedValues object. This will be an empty
    377      * set if the supported values are not of FLAGS type.
    378      *
    379      * \param values the supported values object
    380      */
    381     C2SupportedFlags<T>(const C2FieldSupportedValues &values) {
    382         if (values.type == C2FieldSupportedValues::FLAGS) {
    383             _mValues.insert(_mValues.end(), values.values.begin(), values.values.end());
    384         }
    385     }
    386 
    387     /**
    388      * Returns whether this set is empty.
    389      */
    390     constexpr bool isEmpty() const {
    391         return _mValues.empty();
    392     }
    393 
    394     /**
    395      * Returns whether a value is part of this set.
    396      *
    397      * \param value the value to check.
    398      */
    399     bool contains(T value) const;
    400 
    401     /**
    402      * Returns a new flag set that is the intersection of this set and another.
    403      *
    404      * \param limit the other value set
    405      */
    406     C2SupportedFlags<T> limitedTo(const C2SupportedFlags<T> &limit) const;
    407 
    408     /**
    409      * Converts this object to a C2FieldSupportedValues object.
    410      */
    411     operator C2FieldSupportedValues() const {
    412         return C2FieldSupportedValues(!isEmpty() /* flags */, _mValues);
    413     }
    414 
    415     /**
    416      * Returns the ordered set of flags of this object.
    417      */
    418     const std::vector<T> flags() const;
    419 
    420     /**
    421      * Returns the minimum set of flags for this object.
    422      */
    423     T min() const;
    424 
    425     /**
    426      * Clears this supported value set.
    427      */
    428     inline void clear() {
    429         _mValues.clear();
    430     }
    431 
    432 private:
    433     /**
    434      * Constructs a flag set directly from an internal representation.
    435      *
    436      * \param values a vector containing the minimum flag set followed by the set of flags
    437      */
    438     C2SupportedFlags(std::vector<C2Value::Primitive> &&values)
    439         : _mValues(values) {
    440     }
    441 
    442     /**
    443      * Constructs a flag set from a set of flags and a minimum flag set.
    444      *
    445      * \param flags the set
    446      */
    447     C2SupportedFlags(T min, const std::vector<T> &flags) {
    448         _mValues.emplace_back(min);
    449         for (T elem : flags) {
    450             _mValues.emplace_back(elem);
    451         }
    452     }
    453 
    454     /**
    455      * Constructs a flag set from a set of initializer list values and a minimum flag set
    456      *
    457      * \param flags the set
    458      */
    459     C2SupportedFlags(T min, const std::initializer_list<T> flags) {
    460         _mValues.emplace_back(min);
    461         for (T elem : flags) {
    462             _mValues.emplace_back(elem);
    463         }
    464     }
    465 
    466     std::vector<C2Value::Primitive> _mValues; ///< the minimum flag set followed by the set of flags
    467 };
    468 
    469 /**
    470  * Ordered supported value set for a field of a given type.
    471  */
    472 template<typename T>
    473 class C2SupportedValueSet {
    474     typedef typename _C2FieldValueHelper<T>::ValueType ValueType;
    475 
    476 public:
    477     /**
    478      * Constructs an empty value set.
    479      *
    480      * \note This is a specializated supported range representation that is only used for
    481      * this object - it is equivalent to the EMPTY type in C2FieldSupportedValues.
    482      */
    483     static inline C2SupportedValueSet<T> None() {
    484         return C2SupportedValueSet({ });
    485     }
    486 
    487     /**
    488      * Constructs a value set of given values.
    489      *
    490      * \param values the ordered set of values as an initializer list.
    491      */
    492     static inline C2SupportedValueSet<T> OneOf(const std::initializer_list<T> values) {
    493         return C2SupportedValueSet(values);
    494     }
    495 
    496     /**
    497      * Constructs a value set of given values.
    498      *
    499      * \param values the ordered set of values.
    500      */
    501     static inline C2SupportedValueSet<T> OneOf(const std::vector<T> &values) {
    502         return C2SupportedValueSet(values);
    503     }
    504 
    505     /**
    506      * Constructs a value set from a generic C2FieldSupportedValues object. This will be an empty
    507      * set if the supported values are not of VALUES type.
    508      *
    509      * \param values the supported values object
    510      */
    511     C2SupportedValueSet<T>(const C2FieldSupportedValues &values) {
    512         if (values.type == C2FieldSupportedValues::VALUES) {
    513             _mValues.insert(_mValues.end(), values.values.begin(), values.values.end());
    514         }
    515     }
    516 
    517     /**
    518      * Returns whether this range is empty.
    519      */
    520     constexpr bool isEmpty() const {
    521         return _mValues.empty();
    522     }
    523 
    524     /**
    525      * Returns whether a value is part of this set.
    526      *
    527      * \param value the value to check.
    528      */
    529     bool contains(T value) const;
    530 
    531     /**
    532      * Returns a new value set that is the intersection of this set and another.
    533      *
    534      * \param limit the other value set
    535      */
    536     C2SupportedValueSet<T> limitedTo(const C2SupportedValueSet<T> &limit) const;
    537 
    538     /**
    539      * Returns a new value set that is the intersection of this set and a value range.
    540      *
    541      * \param limit the other range
    542      */
    543     C2SupportedValueSet<T> limitedTo(const C2SupportedRange<T> &limit) const;
    544 
    545     /**
    546      * Returns a new value set that is the intersection of this set and a flag set.
    547      *
    548      * \param limit the other flag set
    549      */
    550     C2SupportedValueSet<T> limitedTo(const C2SupportedFlags<T> &limit) const;
    551 
    552     /**
    553      * Converts this object to a C2FieldSupportedValues object.
    554      */
    555     operator C2FieldSupportedValues() const {
    556         return C2FieldSupportedValues(false /* flags */, _mValues);
    557     }
    558 
    559     /**
    560      * Returns the ordered set of values of this object.
    561      */
    562     const std::vector<T> values() const;
    563 
    564     /**
    565      * Clears this supported value set.
    566      */
    567     inline void clear() {
    568         _mValues.clear();
    569     }
    570 
    571 private:
    572     /**
    573      * Constructs a value set from a set of C2Value::Primitive values.
    574      *
    575      * \param values the set
    576      */
    577     C2SupportedValueSet(std::vector<C2Value::Primitive> &&values)
    578         : _mValues(values) {
    579     }
    580 
    581     /**
    582      * Constructs a value set from a set of values.
    583      *
    584      * \param values the set
    585      */
    586     C2SupportedValueSet(const std::vector<T> &values) {
    587         for (T elem : values) {
    588             _mValues.emplace_back(elem);
    589         }
    590     }
    591 
    592     /**
    593      * Constructs a value set from a set of initializer list values
    594      *
    595      * \param values the set
    596      */
    597     C2SupportedValueSet(const std::initializer_list<T> values) {
    598         for (T elem : values) {
    599             _mValues.emplace_back(elem);
    600         }
    601     }
    602 
    603     std::vector<C2Value::Primitive> _mValues; ///< the supported set of values
    604 };
    605 
    606 /**
    607  * Helper class to handle C2FieldSupporteValues object for fields of various types.
    608  */
    609 template<typename T>
    610 class C2FieldSupportedValuesHelper;
    611 
    612 // templated operator must be predeclared for friend declaration
    613 template<typename T>
    614 std::ostream& operator<<(std::ostream& os, const C2FieldSupportedValuesHelper<T> &i);
    615 
    616 template<typename T>
    617 class C2FieldSupportedValuesHelper {
    618 public:
    619     /**
    620      * Creates a helper for a specific type from a generic C2FieldSupportedValues struct.
    621      */
    622     C2FieldSupportedValuesHelper(const C2FieldSupportedValues &values);
    623 
    624     // TRICKY: needed for std::unique_ptr<Impl> declaration
    625     ~C2FieldSupportedValuesHelper();
    626 
    627     // support copy constructor/operator
    628     C2FieldSupportedValuesHelper(const C2FieldSupportedValuesHelper &);
    629     C2FieldSupportedValuesHelper& operator=(const C2FieldSupportedValuesHelper &);
    630 
    631     bool supports(T value) const;
    632 
    633 private:
    634     // use pimpl as implementation may change in the future
    635     struct Impl;
    636     std::unique_ptr<Impl> _mImpl;
    637 
    638     friend std::ostream& operator<< <T>(std::ostream& os, const C2FieldSupportedValuesHelper<T> &i);
    639     //friend std::ostream& operator<<(std::ostream& os, const C2FieldSupportedValuesHelper &i);
    640 };
    641 
    642 /**
    643  * Builder for supported values for a field of a given type.
    644  *
    645  * This builder can be used to successively restrict the supported values for a field. Upon
    646  * creation, there are no supported values specified - which for this builder means that all
    647  * values are supported.
    648  */
    649 template<typename T>
    650 class C2ParamFieldValuesBuilder {
    651 public:
    652     /**
    653      * Creates a builder with no defined values - but implicitly any value allowed.
    654      */
    655     C2ParamFieldValuesBuilder(const C2ParamField &field);
    656 
    657     /**
    658      * Get C2ParamFieldValues from this builder.
    659      */
    660     operator C2ParamFieldValues() const;
    661 
    662     /**
    663      * Define the supported values as the currently supported values of this builder.
    664      */
    665     C2ParamFieldValuesBuilder<T> &any();
    666 
    667     /**
    668      * Restrict (and thus define) the supported values to none.
    669      *
    670      * \note This really should not be used from the builder as all params must have supported
    671      *       values, but is here in case this is really the case.
    672      */
    673     C2ParamFieldValuesBuilder<T> &none();
    674 
    675     /**
    676      * Restrict (and thus define) the supported values to |value| alone.
    677      */
    678     C2ParamFieldValuesBuilder<T> &equalTo(T value);
    679 
    680     /**
    681      * Restrict (and thus define) the supported values to values greater than |value|.
    682      */
    683     inline C2ParamFieldValuesBuilder<T> &greaterThan(T value) {
    684         return limitTo(C2SupportedRange<T>::GreaterThan(value));
    685     }
    686 
    687     /**
    688      * Restrict (and thus define) the supported values to values greater than or equal to |value|.
    689      */
    690     C2ParamFieldValuesBuilder<T> &greaterThanOrEqualTo(T value) {
    691         return limitTo(C2SupportedRange<T>::GreaterThanOrEqualTo(value));
    692     }
    693 
    694     /**
    695      * Restrict (and thus define) the supported values to values greater than or equal to |value|.
    696      */
    697     C2ParamFieldValuesBuilder<T> &notLessThan(T value) {
    698         return limitTo(C2SupportedRange<T>::NotLessThan(value));
    699     }
    700 
    701     /**
    702      * Restrict (and thus define) the supported values to values less than or equal to |value|.
    703      */
    704     C2ParamFieldValuesBuilder<T> &lessThanOrEqualTo(T value) {
    705         return limitTo(C2SupportedRange<T>::LessThanOrEqualTo(value));
    706     }
    707 
    708     /**
    709      * Restrict (and thus define) the supported values to values less than or equal to |value|.
    710      */
    711     C2ParamFieldValuesBuilder<T> &notGreaterThan(T value) {
    712         return limitTo(C2SupportedRange<T>::NotGreaterThan(value));
    713     }
    714 
    715     /**
    716      * Restrict (and thus define) the supported values to values less than |value|.
    717      */
    718     C2ParamFieldValuesBuilder<T> &lessThan(T value) {
    719         return limitTo(C2SupportedRange<T>::LessThan(value));
    720     }
    721 
    722     /**
    723      * Restrict (and thus define) the supported values to values in the range of [ |min|, |max| ]
    724      * with optional |step|.
    725      */
    726     C2ParamFieldValuesBuilder<T> &inRange(
    727             T min, T max, T step = std::is_floating_point<T>::value ? T(0) : T(1))  {
    728         return limitTo(C2SupportedRange<T>::InRange(min, max, step));
    729     }
    730 
    731     /**
    732      * Restrict (and thus define) the supported values to values in the geometric series starting
    733      * from |min| with factor |num| / |denom|, not greater than |max|.
    734      */
    735     C2ParamFieldValuesBuilder<T> &inSeries(T min, T max, T num, T denom) {
    736         return limitTo(C2SupportedRange<T>::InSeries(min, max, num, denom));
    737     }
    738 
    739     /**
    740      * Restrict (and thus define) the supported values to values in the multiply-accumulate series
    741      * starting from |min| with factor |num| / |denom| and |step|, not greater than |max|.
    742      */
    743     C2ParamFieldValuesBuilder<T> &inMacSeries(T min, T max, T step, T num, T denom) {
    744         return limitTo(C2SupportedRange<T>::InMacSeries(min, max, step, num, denom));
    745     }
    746 
    747     /**
    748      * Restrict (and thus define) the supported values to values in |values|.
    749      */
    750     C2ParamFieldValuesBuilder<T> &oneOf(const std::initializer_list<T> values) {
    751         return limitTo(C2SupportedValueSet<T>::OneOf(values));
    752     }
    753 
    754     /**
    755      * Restrict (and thus define) the supported values to values in |values|.
    756      */
    757     C2ParamFieldValuesBuilder<T> &oneOf(const std::vector<T> &values) {
    758         return limitTo(C2SupportedValueSet<T>::OneOf(values));
    759     }
    760 
    761     /**
    762      * Restrict (and thus define) the supported values to flags in |flags| with at least |min|
    763      * set.
    764      */
    765     C2ParamFieldValuesBuilder<T> &flags(const std::vector<T> &flags, T min = T(0)) {
    766         return limitTo(C2SupportedFlags<T>::Flags(flags, min));
    767     }
    768 
    769     /**
    770      * Restrict (and thus define) the supported values to flags in |values| with at least |min|
    771      * set.
    772      */
    773     C2ParamFieldValuesBuilder<T> &flags(const std::initializer_list<T> flags, T min = T(0)) {
    774         return limitTo(C2SupportedFlags<T>::Flags(flags, min));
    775     }
    776 
    777     virtual ~C2ParamFieldValuesBuilder();
    778 
    779     // support copy constructor/operator
    780     C2ParamFieldValuesBuilder(const C2ParamFieldValuesBuilder &);
    781     C2ParamFieldValuesBuilder& operator=(const C2ParamFieldValuesBuilder &);
    782 
    783 private:
    784     /**
    785      * Restrict (and thus define) the supported values to a value set.
    786      */
    787     C2ParamFieldValuesBuilder<T> &limitTo(const C2SupportedValueSet<T> &limit);
    788 
    789     /**
    790      * Restrict (and thus define) the supported values to a value set.
    791      */
    792     C2ParamFieldValuesBuilder<T> &limitTo(const C2SupportedFlags<T> &limit);
    793 
    794     /**
    795      * Restrict (and thus define) the supported values to a range.
    796      */
    797     C2ParamFieldValuesBuilder<T> &limitTo(const C2SupportedRange<T> &limit);
    798 
    799     struct Impl;
    800     std::unique_ptr<Impl> _mImpl;
    801 };
    802 
    803 /**
    804  * Builder for a list of setting conflicts.
    805  */
    806 class C2SettingConflictsBuilder {
    807 public:
    808     /**
    809      * Creates an empty list of setting conflicts.
    810      */
    811     C2SettingConflictsBuilder();
    812 
    813     /**
    814      * Creates a list containing a single setting conflict.
    815      */
    816     C2SettingConflictsBuilder(C2ParamFieldValues &&conflict);
    817 
    818     /**
    819      * Adds a conflict to the current list of conflicts and returns this
    820      */
    821     C2SettingConflictsBuilder& with(C2ParamFieldValues &&conflict);
    822 
    823     /**
    824      * Gets the current list of conflicts (and moves them out of this builder.)
    825      * (this is why it is not const)
    826      */
    827     std::vector<C2ParamFieldValues> retrieveConflicts();
    828 
    829     /**
    830      * Returns whether the current list is empty.
    831      */
    832     inline bool empty() const { return _mConflicts.empty(); }
    833 
    834     inline operator bool() const { return empty(); }
    835 
    836 private:
    837     std::vector<C2ParamFieldValues> _mConflicts;
    838 };
    839 
    840 /**
    841  * Setting result builder for a parameter.
    842  */
    843 struct C2SettingResultBuilder {
    844     /**
    845      * Creates a read-only setting result failure.
    846      *
    847      * This does not take FSV as only the current value of the field is supported.
    848      */
    849     static C2SettingResult ReadOnly(const C2ParamField &param);
    850 
    851     /**
    852      * Creates a bad-value or infoinformational bad-value setting result failure.
    853      *
    854      * This does not take FSV as the value is outside of the possible values. As such, there are no
    855      * conflicts for this case either.
    856      */
    857     static C2SettingResult BadValue(const C2ParamField &paramField, bool isInfo = false);
    858 
    859     /**
    860      * Creates a conflict (or informational conflict) setting result failure.
    861      *
    862      * This takes FSV so use paramFieldValues and optional conflicts.
    863      */
    864     static C2SettingResult Conflict(
    865             C2ParamFieldValues &&paramFieldValues, C2SettingConflictsBuilder &conflicts,
    866             bool isInfo = false);
    867 
    868     // TODO: retrieve results
    869 
    870 
    871 private:
    872     C2ParamField _mParamField;
    873     C2SettingResult _mResult;
    874 
    875     C2SettingResultBuilder(const C2SettingResultBuilder &) = delete;
    876 };
    877 
    878 /**
    879  * Setting results (PLURAL) builder.
    880  *
    881  * Setting results contain a failure status along with a list of failing fields or params.
    882  */
    883 struct C2SettingResultsBuilder {
    884     C2SettingResultsBuilder(const C2SettingResultsBuilder&) = delete;
    885     C2SettingResultsBuilder(C2SettingResultsBuilder&&) = default;
    886     C2SettingResultsBuilder &operator=(C2SettingResultsBuilder&&) = default;
    887 
    888     /** \returns (default) successful result with no details. */
    889     inline static C2SettingResultsBuilder Ok() {
    890         return C2SettingResultsBuilder(C2_OK);
    891     }
    892 
    893     /** \returns Interface is in bad state, with no further details. */
    894     inline static C2SettingResultsBuilder BadState() {
    895         return C2SettingResultsBuilder(C2_BAD_STATE);
    896     }
    897 
    898     /** \returns Interface connection timed out, with no further details. */
    899     inline static C2SettingResultsBuilder TimedOut() {
    900         return C2SettingResultsBuilder(C2_TIMED_OUT);
    901     }
    902 
    903     /** \returns Interface connection is corrupted, with no further details. */
    904     inline static C2SettingResultsBuilder Corrupted() {
    905         return C2SettingResultsBuilder(C2_CORRUPTED);
    906     }
    907 
    908     inline static C2SettingResultsBuilder NoMemory(C2Param::Index index_ __unused) {
    909         // TODO: try to add failure result
    910         return C2SettingResultsBuilder(C2_NO_MEMORY);
    911     }
    912 
    913     // TODO: this should not be a constructor
    914     /** Creates a builder with a single bad value setting result. */
    915     C2SettingResultsBuilder(C2SettingResult &&result);
    916 
    917     /** Combines this results with other results. */
    918     C2SettingResultsBuilder plus(C2SettingResultsBuilder&& results);
    919 
    920     /** Retrieve (get and move out) failures and return the failure status. */
    921     c2_status_t retrieveFailures(std::vector<std::unique_ptr<C2SettingResult>>* const failures);
    922 
    923 private:
    924     /** Setting results based on a single status. This is used when actual setting could not be
    925      *  attempted to get a single C2SettingResult, or when a setting succeeded without
    926      *  'complaints'. */
    927     C2SettingResultsBuilder(c2_status_t status);
    928         // status must be one of OK, BAD_STATE, TIMED_OUT, CORRUPTED or NO_MEMORY
    929         // mainly: BLOCKING, BAD_INDEX, BAD_VALUE and NO_MEMORY requires a setting attempt, but
    930         // NO_MEMORY may not allow us to create a results structure.
    931 
    932     /**
    933      * One of OK, BAD_INDEX, BAD_VALUE, BAD_STATE, NO_MEMORY, TIMED_OUT, BLOCKING or CORRUPTED.
    934      */
    935     c2_status_t _mStatus __unused;
    936 
    937     /**
    938      * Vector of individual setting result details.
    939      */
    940     std::vector<std::unique_ptr<C2SettingResult>> _mResults;
    941 };
    942 
    943 /**
    944  * Utility class to enumerate fields of parameters.
    945  */
    946 struct C2FieldUtils {
    947     struct _Inspector;
    948 
    949     /**
    950      * An extended field descriptor object with structural information (lineage back to the root of
    951      * the param).
    952      */
    953     struct Info {
    954         typedef C2FieldDescriptor::type_t type_t; ///< field type
    955         typedef C2FieldDescriptor::NamedValuesType NamedValuesType; ///< named values list type
    956 
    957         /// returns the name of the field
    958         C2String name() const;
    959 
    960         /// returns the type of this field
    961         type_t type() const;
    962 
    963         /**
    964          * Returns the defined name-value pairings for this field. The returned reference is
    965          * only valid during the validity of this object
    966          */
    967         const NamedValuesType &namedValues() const;
    968 
    969         /**
    970          * The index of this field. E.g. param.field or param.field[0] has an index of 0, and
    971          * param.struct[2].field[3] has an index of 3.
    972          */
    973         size_t index() const;
    974 
    975         /// returns the length of the field in case it is an array. Returns 0 for
    976         /// T[] arrays if this info comes from a C2Param::Index object, and the currently used
    977         /// extent if it comes from a C2Param object. Returns 1 for T[1] arrays as well as if the
    978         /// field is not an array.
    979         size_t extent() const;
    980 
    981         /**
    982          * The (structural) depth of this field. E.g. param.field or param.field[0] has a depth of
    983          *  0, and param.struct.field or param.struct[0].field[0] has a depth of 1.
    984          */
    985         size_t depth() const;
    986 
    987         /**
    988          * Returns the offset of this field in the parameter in bytes.
    989          */
    990         size_t offset() const;
    991 
    992         /**
    993          * Returns the size of this field in bytes.
    994          */
    995         size_t size() const;
    996 
    997         /**
    998          * The offset of this field's array. E.g. for param.struct[2].field[3] this is the offset
    999          * of its smallest sibling: param.struct[2].field[0].
   1000          */
   1001         size_t arrayOffset() const;
   1002 
   1003         /**
   1004          * Returns the size of this field's array. This is equivalent to extent() * size()
   1005          */
   1006         size_t arraySize() const;
   1007 
   1008         /**
   1009          * The offset of the base field. The base field is a cousin of the current field where
   1010          * all indices are 0. E.g. the the base field for param.struct[2].field[3] is
   1011          * param.struct[0].field[0]. Base fields are used to specify supported values for
   1012          * all cousin fields.
   1013          */
   1014         size_t baseFieldOffset() const;
   1015 
   1016         /**
   1017          * Returns whether this field is an arithmetic (integral, counter or float) field.
   1018          */
   1019         bool isArithmetic() const;
   1020 
   1021         /**
   1022          * Returns whether this field can have a flexible extent. extent() returns the current
   1023          * extent.
   1024          */
   1025         bool isFlexible() const;
   1026 
   1027         /// returns whether this info is valid
   1028         inline bool isValid() const { return _mImpl != nullptr; }
   1029 
   1030         /// returns the info for the parent of this field, or an invalid Info object if it has no
   1031         /// parents
   1032         Info parent() const;
   1033 
   1034         /// returns whether this info is valid
   1035         inline operator bool() const { return isValid(); }
   1036 
   1037         struct Impl;
   1038         Info(std::shared_ptr<Impl>);
   1039 
   1040     private:
   1041         std::shared_ptr<Impl> _mImpl;
   1042         friend struct _Inspector;
   1043     };
   1044 
   1045     /**
   1046      * An (input) iterator object over fields using Info objects.
   1047      */
   1048     struct Iterator {
   1049         typedef Info const value_type;
   1050         typedef ptrdiff_t difference_type;
   1051         typedef Info const * pointer;
   1052         typedef Info const reference;
   1053         typedef std::input_iterator_tag iterator_category;
   1054 
   1055         /// return Info at current position
   1056         virtual reference operator*() const;
   1057 
   1058         /// move to the next field
   1059         virtual Iterator& operator++();
   1060 
   1061         virtual bool operator==(const Iterator &) const;
   1062         inline bool operator!=(const Iterator &other) const { return !operator==(other); }
   1063 
   1064         virtual ~Iterator() = default;
   1065 
   1066         struct Impl;
   1067         Iterator(std::shared_ptr<Impl>);
   1068 
   1069     protected:
   1070         std::shared_ptr<Impl> mImpl;
   1071     };
   1072 
   1073     /**
   1074      * An (input) iterable object representing a list of fields.
   1075      */
   1076     struct List {
   1077         /// returns an iterator to the beginning of the list
   1078         virtual Iterator begin() const;
   1079 
   1080         /// returns an iterator to the end of the list
   1081         virtual Iterator end() const;
   1082 
   1083         virtual ~List() = default;
   1084 
   1085         struct Impl;
   1086         List(std::shared_ptr<Impl>);
   1087 
   1088     protected:
   1089         std::shared_ptr<Impl> mImpl;
   1090     };
   1091 
   1092     /**
   1093      * Enumerates all (base) fields at index 0 of the parameter. The order of iteration is the
   1094      * following:
   1095      *   Fields of a structure are enumerated in field order. However, sub-fields of a structure
   1096      *   are enumerated directly after the structure field, and prior to sibling fields.
   1097      *
   1098      * In essence the order of enumeration is first by increasing offset, then by decreasing size.
   1099      *
   1100      * \param param parameter to enumerate its fields
   1101      * \param reflector parameter reflector used for enumeration
   1102      *
   1103      * \return an iterable object
   1104      */
   1105     static List enumerateFields(
   1106             const C2Param &param,
   1107             const std::shared_ptr<C2ParamReflector> &reflector);
   1108 
   1109     /**
   1110      * Enumerates all cousin fields up to depth - level for a field. If level is 0, it enumerates
   1111      * only the field. For level 1, it enumerates all fields in its current array (which may be
   1112      * itself if extent is 1). The order of iteration is by increasing field offset.
   1113      */
   1114     static List enumerateCousins(
   1115             const Info &field,
   1116             uint32_t level = ~0);
   1117 
   1118     /**
   1119      * Locates the field in a parameter and returns a list of 2 elements - the most-specific field
   1120      * array of the parameter that contains the entire field. If the field is not a valid field
   1121      * specifier for this parameter (e.g. it is outside the bounds of the parameter), it returns
   1122      * an empty list.
   1123      */
   1124     static std::vector<Info> locateField(
   1125             const C2Param &param, const _C2FieldId &field,
   1126             const std::shared_ptr<C2ParamReflector> &reflector);
   1127 
   1128     static std::vector<Info> locateField(
   1129             const C2ParamField &pf, const std::shared_ptr<C2ParamReflector> &reflector);
   1130 
   1131 };
   1132 
   1133 #include <util/C2Debug-interface.h>
   1134 
   1135 #endif  // C2UTILS_INTERFACE_UTILS_H_
   1136