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;
put_C2FieldValueHelper35     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