LCOV - code coverage report
Current view: top level - src - enumclass_utils.h (source / functions) Coverage Total Hit
Test: jami-coverage-filtered.info Lines: 20.0 % 30 6
Test Date: 2026-06-13 09:18:46 Functions: 26.9 % 52 14

            Line data    Source code
       1              : /*
       2              :  *  Copyright (C) 2004-2026 Savoir-faire Linux Inc.
       3              :  *
       4              :  *  This program is free software: you can redistribute it and/or modify
       5              :  *  it under the terms of the GNU General Public License as published by
       6              :  *  the Free Software Foundation, either version 3 of the License, or
       7              :  *  (at your option) any later version.
       8              :  *
       9              :  *  This program is distributed in the hope that it will be useful,
      10              :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      11              :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      12              :  *  GNU General Public License for more details.
      13              :  *
      14              :  *  You should have received a copy of the GNU General Public License
      15              :  *  along with this program. If not, see <https://www.gnu.org/licenses/>.
      16              :  */
      17              : #pragma once
      18              : 
      19              : #include "logger.h"
      20              : 
      21              : #include <map>
      22              : #include <type_traits>
      23              : #include <vector>
      24              : #include <cassert>
      25              : 
      26              : namespace jami {
      27              : 
      28              : /**
      29              :  * This function adds a safe way to get an enum class size
      30              :  */
      31              : template<typename A>
      32              : constexpr inline size_t
      33          324 : enum_class_size()
      34              : {
      35          324 :     return size_t(A::COUNT__);
      36              : }
      37              : 
      38              : /**
      39              :  * This generic class represents a multidimensional enum class array.
      40              :  * It safely converts them to integers. Each enum class needs a "COUNT__" item
      41              :  * at the end."
      42              :  *
      43              :  * This struct enforces:
      44              :  * * That the rows are indexed using enum_classes
      45              :  * * That the size of the matrix matches the enum_class size
      46              :  * * That the operators are within the matrix boundary
      47              :  */
      48              : template<class Row, typename Value, typename A = Value>
      49              : struct Matrix1D
      50              : {
      51              :     constexpr Matrix1D(std::initializer_list<std::initializer_list<Value>> s);
      52              : 
      53              :     // Row is a built-in type ("int" by default)
      54              :     Value operator[](Row v);
      55              : 
      56              :     const Value operator[](Row v) const;
      57              : 
      58              :     /**
      59              :      * An Iterator for enum classes
      60              :      */
      61              :     class EnumClassIter
      62              :     {
      63              :     public:
      64              :         EnumClassIter(const Matrix1D<Row, Value, A>* p_vec, size_t pos)
      65              :             : pos_(pos)
      66              :             , p_vec_(p_vec)
      67              :         {}
      68              : 
      69              :         bool operator!=(const EnumClassIter& other) const;
      70              :         Row operator*() const;
      71              :         const EnumClassIter& operator++();
      72              : 
      73              :     private:
      74              :         size_t pos_;
      75              :         const Matrix1D<Row, Value, A>* p_vec_;
      76              :     };
      77              : 
      78              :     // Iterators
      79              :     EnumClassIter begin();
      80              :     EnumClassIter end();
      81              : 
      82              :     // Only use for single reverse mappable arrays, will ASSERT otherwise
      83              :     Row fromValue(const Value& value) const;
      84              : 
      85              :     static void setReverseMapping(Matrix1D<Row, const char*> names);
      86              : 
      87              : private:
      88              :     const std::vector<Value> data_;
      89              :     static std::map<A, Row> reverseMapping_;
      90              : };
      91              : 
      92              : /**
      93              :  * A matrix with no value
      94              :  *
      95              :  * This is useful to use enum class in C++11 foreach loops
      96              :  *
      97              :  * @usage
      98              :  *   for (const MyEnum& value : Matrix0D<MyEnum>()) {
      99              :  *       std::cout << "Name: " << MyEnumNames[value] << std::endl;
     100              :  *   }
     101              :  */
     102              : template<class EnumClass>
     103              : struct Matrix0D
     104              : {
     105              :     /**
     106              :      * An Iterator for enum classes
     107              :      */
     108              :     class EnumClassIter
     109              :     {
     110              :     public:
     111            0 :         EnumClassIter(const Matrix0D<EnumClass>* p_vec, size_t pos)
     112            0 :             : pos_(pos)
     113            0 :             , p_vec_(p_vec)
     114            0 :         {}
     115              : 
     116              :         bool operator!=(const EnumClassIter& other) const;
     117              :         EnumClass operator*() const;
     118              :         const EnumClassIter& operator++();
     119              : 
     120              :     private:
     121              :         size_t pos_;
     122              :         const Matrix0D<EnumClass>* p_vec_;
     123              :     };
     124              : 
     125              :     Matrix0D();
     126              : 
     127              :     // Iterators
     128              :     EnumClassIter begin();
     129              :     EnumClassIter end();
     130              : };
     131              : 
     132              : /**
     133              :  * A helper to type to match serializable string to enum elements
     134              :  */
     135              : template<class Row>
     136              : using EnumClassNames = Matrix1D<Row, std::string_view>;
     137              : 
     138              : /**
     139              :  * Create a matrix type with 2 enum class dimensions M[I,J] = V
     140              :  *                                                     ^ ^    ^
     141              :  *                                                     | |    |
     142              :  *                                          Rows    <--- |    |
     143              :  *                                          Columns <-----    |
     144              :  *                                          Value   <----------
     145              :  */
     146              : template<class Row, class Column, typename Value>
     147              : using Matrix2D = Matrix1D<Row, Matrix1D<Column, Value>>;
     148              : 
     149              : /**
     150              :  * Create an array of callbacks.
     151              :  *
     152              :  * This type hides all the C++ syntax requirements
     153              :  */
     154              : template<class Row, class Class, typename Result = void, typename... Args>
     155              : using CallbackMatrix1D = Matrix1D<Row, Result (Class::*)(Args... args)>;
     156              : 
     157              : /**
     158              :  * Create a method callback matrix.
     159              :  *
     160              :  * This type hides all the C++ syntax requirements
     161              :  */
     162              : template<class Row, class Column, class Class, typename Result = void, typename... Args>
     163              : using CallbackMatrix2D = Matrix2D<Row, Column, void (Class::*)(Args... args)>;
     164              : 
     165              : /*
     166              :  * IMPLEMENTATION
     167              :  *
     168              :  */
     169              : 
     170              : template<class Row, typename Value, typename Accessor>
     171          324 : constexpr Matrix1D<Row, Value, Accessor>::Matrix1D(std::initializer_list<std::initializer_list<Value>> s)
     172          648 :     : data_(*std::begin(s))
     173              : {
     174              :     static_assert(std::is_enum<Row>(), "Row has to be an enum class");
     175              :     static_assert((int) Row::COUNT__ > 0, "Row need a COUNT__ element");
     176              : 
     177              :     // FIXME C++14, use static_assert and make the ctor constexpr
     178          324 :     assert(s.begin()->size() == enum_class_size<Row>()); //,"Matrix row have to match the enum class size");
     179          324 : }
     180              : 
     181              : template<class Row, typename Value, typename Accessor>
     182              : Value
     183              : Matrix1D<Row, Value, Accessor>::operator[](Row v)
     184              : {
     185              :     // ASSERT(size_t(v) >= size_t(Row::COUNT__),"State Machine Out of Bounds\n");
     186              :     if (size_t(v) >= enum_class_size<Row>() || static_cast<int>(v) < 0) {
     187              :         JAMI_ERROR("State Machine Out of Bounds {}", size_t(v));
     188              :         assert(false);
     189              :         throw v;
     190              :     }
     191              :     return data_[size_t(v)];
     192              : }
     193              : 
     194              : template<class Row, typename Value, typename Accessor>
     195              : const Value
     196            0 : Matrix1D<Row, Value, Accessor>::operator[](Row v) const
     197              : {
     198            0 :     assert(size_t(v) <= enum_class_size<Row>() + 1 && size_t(v) >= 0); // COUNT__ is also valid
     199            0 :     if (size_t(v) >= enum_class_size<Row>()) {
     200            0 :         JAMI_ERROR("State Machine Out of Bounds {}", size_t(v));
     201            0 :         assert(false);
     202              :         throw v;
     203              :     }
     204            0 :     return data_[size_t(v)];
     205              : }
     206              : 
     207              : template<class E, class T, class A>
     208              : std::map<A, E> Matrix1D<E, T, A>::reverseMapping_;
     209              : 
     210              : template<class Row, typename Value, typename Accessor>
     211              : void
     212              : Matrix1D<Row, Value, Accessor>::setReverseMapping(Matrix1D<Row, const char*> names)
     213              : {
     214              :     for (const Row row : Matrix0D<Row>())
     215              :         reverseMapping_[names[row]] = row;
     216              : }
     217              : 
     218              : template<class Row, typename Value, typename Accessor>
     219              : Row
     220              : Matrix1D<Row, Value, Accessor>::fromValue(const Value& value) const
     221              : {
     222              :     if (!reverseMapping_.empty()) {
     223              :         for (int i = 0; i < enum_class_size<Row>(); i++) {
     224              :             const_cast<Matrix1D*>(this)->reverseMapping_[(*const_cast<Matrix1D*>(this))[(Row) i]] = static_cast<Row>(i);
     225              :         }
     226              :         assert(reverseMapping_.empty() == enum_class_size<Row>());
     227              :     }
     228              :     if (reverseMapping_.count(value) == 0) {
     229              :         throw value;
     230              :     }
     231              :     return reverseMapping_[value];
     232              : }
     233              : 
     234              : template<class EnumClass>
     235            0 : Matrix0D<EnumClass>::Matrix0D()
     236              : {
     237              :     static_assert(std::is_enum<EnumClass>(), "The first template parameter has to be an enum class\n");
     238            0 : }
     239              : 
     240              : template<class EnumClass>
     241              : EnumClass
     242            0 : Matrix0D<EnumClass>::EnumClassIter::operator*() const
     243              : {
     244            0 :     assert(pos_ < enum_class_size<EnumClass>());
     245            0 :     return static_cast<EnumClass>(pos_);
     246              : }
     247              : 
     248              : template<class EnumClass>
     249              : const typename Matrix0D<EnumClass>::EnumClassIter&
     250            0 : Matrix0D<EnumClass>::EnumClassIter::operator++()
     251              : {
     252            0 :     ++pos_;
     253            0 :     return *this;
     254              : }
     255              : 
     256              : template<class EnumClass>
     257              : bool
     258            0 : Matrix0D<EnumClass>::EnumClassIter::operator!=(const EnumClassIter& other) const
     259              : {
     260            0 :     return pos_ != other.pos_;
     261              : }
     262              : 
     263              : template<class EnumClass>
     264              : typename Matrix0D<EnumClass>::EnumClassIter
     265            0 : Matrix0D<EnumClass>::begin()
     266              : {
     267            0 :     return Matrix0D<EnumClass>::EnumClassIter(this, 0);
     268              : }
     269              : 
     270              : template<class EnumClass>
     271              : typename Matrix0D<EnumClass>::EnumClassIter
     272            0 : Matrix0D<EnumClass>::end()
     273              : {
     274            0 :     return Matrix0D<EnumClass>::EnumClassIter(this, enum_class_size<EnumClass>());
     275              : }
     276              : 
     277              : template<class Row, typename Value, typename Accessor>
     278              : const typename Matrix1D<Row, Value, Accessor>::EnumClassIter&
     279              : Matrix1D<Row, Value, Accessor>::EnumClassIter::operator++()
     280              : {
     281              :     ++pos_;
     282              :     return *this;
     283              : }
     284              : 
     285              : template<class Row, typename Value, typename Accessor>
     286              : bool
     287              : Matrix1D<Row, Value, Accessor>::EnumClassIter::operator!=(const EnumClassIter& other) const
     288              : {
     289              :     return pos_ != other.pos_;
     290              : }
     291              : 
     292              : template<class Row, typename Value, typename Accessor>
     293              : typename Matrix1D<Row, Value, Accessor>::EnumClassIter
     294              : Matrix1D<Row, Value, Accessor>::begin()
     295              : {
     296              :     return Matrix1D<Row, Value, Accessor>::EnumClassIter(this, 0);
     297              : }
     298              : 
     299              : template<class Row, typename Value, typename Accessor>
     300              : typename Matrix1D<Row, Value, Accessor>::EnumClassIter
     301              : Matrix1D<Row, Value, Accessor>::end()
     302              : {
     303              :     return Matrix1D<Row, Value, Accessor>::EnumClassIter(this, enum_class_size<Row>());
     304              : }
     305              : 
     306              : } // namespace jami
        

Generated by: LCOV version 2.0-1