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