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-04-25 08:05:53 Functions: 14 36 38.9 %

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

Generated by: LCOV version 1.14