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 */
32template<typename T>
33struct 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
40template<>
41struct C2_HIDE _C2FieldValueHelper<uint8_t> {
42    typedef uint32_t ValueType;
43    static std::ostream& put(std::ostream &os, const C2Value::Primitive &p);
44};
45
46template<>
47struct 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 */
57template<typename T>
58class 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
66public:
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
271private:
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 */
340template<typename T>
341class C2SupportedFlags {
342    typedef typename _C2FieldValueHelper<T>::ValueType ValueType;
343
344public:
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
432private:
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 */
472template<typename T>
473class C2SupportedValueSet {
474    typedef typename _C2FieldValueHelper<T>::ValueType ValueType;
475
476public:
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
571private:
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 */
609template<typename T>
610class C2FieldSupportedValuesHelper;
611
612// templated operator must be predeclared for friend declaration
613template<typename T>
614std::ostream& operator<<(std::ostream& os, const C2FieldSupportedValuesHelper<T> &i);
615
616template<typename T>
617class C2FieldSupportedValuesHelper {
618public:
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
633private:
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 */
649template<typename T>
650class C2ParamFieldValuesBuilder {
651public:
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
783private:
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 */
806class C2SettingConflictsBuilder {
807public:
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
836private:
837    std::vector<C2ParamFieldValues> _mConflicts;
838};
839
840/**
841 * Setting result builder for a parameter.
842 */
843struct 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
871private:
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 */
883struct 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
923private:
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 */
946struct 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