LCOV - code coverage report
Current view: top level - src - enumclass_utils.h (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 6 30 20.0 %
Date: 2024-12-21 08:56:24 Functions: 14 36 38.9 %

          Line data    Source code
       1             : /*
       2             :  *  Copyright (C) 2004-2024 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         504 : enum_class_size()
      34             : {
      35         504 :     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         504 : constexpr Matrix1D<Row, Value, Accessor>::Matrix1D(std::initializer_list<std::initializer_list<Value>> s)
     172         504 :     : 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         504 :     assert(s.begin()->size()
     179             :            == enum_class_size<Row>()); //,"Matrix row have to match the enum class size");
     180         504 : }
     181             : 
     182             : template<class Row, typename Value, typename Accessor>
     183             : Value 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_ERR("State Machine Out of Bounds %d\n", 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           0 : const Value Matrix1D<Row, Value, Accessor>::operator[](Row v) const
     196             : {
     197           0 :     assert(size_t(v) <= enum_class_size<Row>() + 1 && size_t(v) >= 0); // COUNT__ is also valid
     198           0 :     if (size_t(v) >= enum_class_size<Row>()) {
     199           0 :         JAMI_ERR("State Machine Out of Bounds %zu\n", size_t(v));
     200           0 :         assert(false);
     201             :         throw v;
     202             :     }
     203           0 :     return data_[size_t(v)];
     204             : }
     205             : 
     206             : template<class E, class T, class A>
     207             : std::map<A, E> Matrix1D<E, T, A>::reverseMapping_;
     208             : 
     209             : template<class Row, typename Value, typename Accessor>
     210             : void
     211             : Matrix1D<Row, Value, Accessor>::setReverseMapping(Matrix1D<Row, const char*> names)
     212             : {
     213             :     for (const Row row : Matrix0D<Row>())
     214             :         reverseMapping_[names[row]] = row;
     215             : }
     216             : 
     217             : template<class Row, typename Value, typename Accessor>
     218             : Row
     219             : Matrix1D<Row, Value, Accessor>::fromValue(const Value& value) const
     220             : {
     221             :     if (!reverseMapping_.empty()) {
     222             :         for (int i = 0; i < enum_class_size<Row>(); i++) {
     223             :             const_cast<Matrix1D*>(this)->reverseMapping_[(*const_cast<Matrix1D*>(this))[(Row) i]]
     224             :                 = 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>(),
     238             :                   "The first template parameter has to be an enum class\n");
     239           0 : }
     240             : 
     241             : template<class EnumClass>
     242           0 : EnumClass 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 1.14