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> ¬LessThan(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> ¬GreaterThan(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 ¶m); 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 ¶mField, 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 &¶mFieldValues, 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 ¶m, 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 ¶m, 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