LCOV - code coverage report
Current view: top level - ugbase/registry - class_name_provider_impl.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 35.8 % 53 19
Test Date: 2025-09-21 23:31:46 Functions: 39.1 % 7036 2749

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2011-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Authors: Sebastian Reiter, Andreas Vogel
       4              :  * 
       5              :  * This file is part of UG4.
       6              :  * 
       7              :  * UG4 is free software: you can redistribute it and/or modify it under the
       8              :  * terms of the GNU Lesser General Public License version 3 (as published by the
       9              :  * Free Software Foundation) with the following additional attribution
      10              :  * requirements (according to LGPL/GPL v3 §7):
      11              :  * 
      12              :  * (1) The following notice must be displayed in the Appropriate Legal Notices
      13              :  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
      14              :  * 
      15              :  * (2) The following notice must be displayed at a prominent place in the
      16              :  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
      17              :  * 
      18              :  * (3) The following bibliography is recommended for citation and must be
      19              :  * preserved in all covered files:
      20              :  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
      21              :  *   parallel geometric multigrid solver on hierarchically distributed grids.
      22              :  *   Computing and visualization in science 16, 4 (2013), 151-164"
      23              :  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
      24              :  *   flexible software system for simulating pde based models on high performance
      25              :  *   computers. Computing and visualization in science 16, 4 (2013), 165-179"
      26              :  * 
      27              :  * This program is distributed in the hope that it will be useful,
      28              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      29              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      30              :  * GNU Lesser General Public License for more details.
      31              :  */
      32              : 
      33              : #ifndef __H__UG_BRIDGE__CLASS_NAME_PROVIDER_IMPL__
      34              : #define __H__UG_BRIDGE__CLASS_NAME_PROVIDER_IMPL__
      35              : 
      36              : #include <algorithm>
      37              : #include <string>
      38              : 
      39              : #include "class_name_provider.h"
      40              : #include "common/util/typename.h"
      41              : 
      42              : namespace ug{
      43              : namespace bridge{
      44              : 
      45              : ////////////////////////////////////////////////////////////////////////////////
      46              : //  ClassNameProvider
      47              : ////////////////////////////////////////////////////////////////////////////////
      48              : 
      49              : template <typename TClass>
      50         3731 : void ClassNameProvider<TClass>::
      51              : set_name(const std::string& nameIn, const std::string& group, bool newName)
      52              : {
      53              : //      if class already named throw error
      54         3731 :         if(newName == true && m_bForwardDeclared==false && !m_ClassNameNode.empty())
      55              :         {
      56            0 :                 if(nameIn != name())
      57            0 :                         UG_THROW_REGISTRY_ERROR(nameIn,
      58              :                         "Trying to register class with name '"<<nameIn
      59              :                         << "', that has already been named. This is not allowed.");
      60              :         }
      61              : 
      62              : //      check name
      63         3731 :         if(nameIn.empty())
      64            0 :                 UG_THROW_REGISTRY_MSG("Registered class name has length zero");
      65              : 
      66         3731 :         if(nameIn.c_str()[0] == '[')
      67            0 :                 UG_THROW_REGISTRY_ERROR(nameIn, "Registered class name must not begin with '['");
      68              : 
      69              : //      check for non-allowed character
      70              :         size_t found = nameIn.find_first_not_of("abcdefghijklmnopqrstuvwxyz"
      71              :                                                                                          "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
      72              :                                                                                          "_"
      73              :                                                                                          "0123456789");
      74         3731 :         if (found!=std::string::npos)
      75              :         {
      76            0 :                 UG_ERR_LOG("Non-allowed character '"<<nameIn[found]<<"' "<<
      77              :                        "contained at position "<<int(found)<<" in registered Class Name "
      78              :                        "'"<<nameIn<<"'.\nClass names must match the regular expression: "
      79              :                        "[a-zA-Z_][a-zA-Z_0-9]*, \ni.e. only alphabetic characters, numbers "
      80              :                        " and '_' are allowed; no numbers at the beginning.\n");
      81            0 :                 UG_THROW_REGISTRY_ERROR(nameIn, "Class Name must only contain [a-zA-Z_][a-zA-Z_0-9]*.");
      82              :         }
      83              : 
      84              : //      check that no number at the beginning
      85              :          found = nameIn.find_first_of("0123456789");
      86         3731 :         if (found!=std::string::npos && found == 0)
      87              :         {
      88            0 :                 UG_ERR_LOG("Class Name "<<nameIn<<" starts with a number.\nThis is "
      89              :                                 " not allowed. Please change naming.\n");
      90            0 :                 UG_THROW_REGISTRY_ERROR(nameIn,"Class Name must not start with number.");
      91              :         }
      92              : 
      93              : 
      94              : //      copy name into static string
      95         3731 :         m_ClassNameNode.set_name(nameIn);
      96              : 
      97              : //      set forward declared to false, since now name set
      98         3731 :         m_bForwardDeclared = false;
      99              : 
     100              : //      remember groups
     101         3731 :         m_group = std::string(group);
     102         3731 : };
     103              : 
     104              : template <typename TClass>
     105              : template <typename TParent1>
     106              : void ClassNameProvider<TClass>::
     107              : set_name(const std::string& name, const std::string& group, bool newName)
     108              : {
     109              : //      set own name
     110          982 :         set_name(name, group, newName);
     111              : 
     112              : //      add parent nodes
     113          982 :         m_ClassNameNode.add_base_class(ClassNameProvider<TParent1>::class_name_node());
     114              : }
     115              : 
     116              : template <typename TClass>
     117              : template <typename TParent1, typename TParent2>
     118           51 : void ClassNameProvider<TClass>::
     119              : set_name(const std::string& name, const std::string& group,bool newName)
     120              : {
     121              : //      set own name
     122           51 :         set_name(name, group, newName);
     123              : 
     124              : //      add parent nodes
     125           51 :         m_ClassNameNode.add_base_class(ClassNameProvider<TParent1>::class_name_node());
     126           51 :         m_ClassNameNode.add_base_class(ClassNameProvider<TParent2>::class_name_node());
     127           51 : }
     128              : 
     129              : template <typename TClass>
     130              : bool ClassNameProvider<TClass>::is_a(const std::string& parent, bool strict)
     131              : {
     132              : //      check if class is forward declared
     133              :         if(m_bForwardDeclared)
     134              :                 UG_THROW_REGISTRY_ERROR(parent,
     135              :                 "Class '"<<parent<<"' must not be foreward declared to use is_a");
     136              : 
     137              : //  strict comparison: must match this class name, parents are not allowed
     138              :         if(strict)
     139              :         {
     140              :         //  compare strings
     141              :                 if(parent == name()) return true;
     142              : 
     143              :         //  names does not match
     144              :                 return false;
     145              :         }
     146              : 
     147              : //      return if parent name is contained in tree of base classes
     148              :         return ClassNameTreeContains(m_ClassNameNode, parent);
     149              : }
     150              : 
     151              : template <typename TClass>
     152              : const std::string& ClassNameProvider<TClass>::name()
     153              : {
     154              : //      if name has not been set, set temporary forward declaration
     155      3472359 :         if(m_ClassNameNode.empty()) set_foreward_declared();
     156              : 
     157              : //      return the name of this class as stored in ClassNameNode
     158              :         return m_ClassNameNode.name();
     159              : }
     160              : 
     161              : template <typename TClass>
     162            0 : const std::vector<const char*>& ClassNameProvider<TClass>::names()
     163              : {
     164              : //      if name has not been set, set temporary forward declaration
     165            0 :         if(m_ClassNameNode.empty()) set_foreward_declared();
     166              : 
     167              : //      create names list, including this class and all base classes
     168              : //      \todo: remove this, avoid names-vector
     169            0 :         ExtractClassNameVec(m_names, m_ClassNameNode, true);
     170              : 
     171              : //      return the vector of base class names
     172            0 :         return m_names;
     173              : }
     174              : 
     175              : template <typename TClass>
     176            0 : void ClassNameProvider<TClass>::set_foreward_declared()
     177              : {
     178              : //      build default name using typeinfo
     179            0 :         std::string name("[[");
     180            0 :         name.append( TypeName<TClass>() );
     181            0 :         name.append(" (undeclared) ]]");
     182              : 
     183              : //      set this as current name, but remember pre-declaration
     184            0 :         m_ClassNameNode.set_name(name);
     185            0 :         m_bForwardDeclared = true;
     186            0 : }
     187              : 
     188              : template <typename TClass>
     189              : std::vector<const char*> ClassNameProvider<TClass>::m_names = std::vector<const char*>();
     190              : 
     191              : template <typename TClass>
     192              : std::string ClassNameProvider<TClass>::m_group = std::string("");
     193              : 
     194              : template <typename TClass>
     195              : bool ClassNameProvider<TClass>::m_bForwardDeclared = false;
     196              : 
     197              : template <typename TClass>
     198              : ClassNameNode ClassNameProvider<TClass>::m_ClassNameNode = ClassNameNode();
     199              : 
     200              : ////////////////////////////////////////////////////////////////////////////////
     201              : //  ClassCastProvider
     202              : ////////////////////////////////////////////////////////////////////////////////
     203              : 
     204              : template <typename TBase, typename TDerived>
     205            0 : void* StaticVoidCast(void* DerivVoidPtr)
     206              : {
     207              : //      cast to derived class; this assumes, that the void pointer points to the
     208              : //      beginning of the data field of the Derived object
     209              :         TDerived* pDeriv = reinterpret_cast<TDerived*>(DerivVoidPtr);
     210              : 
     211              : //      static case to the Derid class
     212            0 :         TBase* pBase = static_cast<TBase*>(pDeriv);
     213              : 
     214              : //      return cast to void
     215            0 :         return reinterpret_cast<void*>(pBase);
     216              : }
     217              : 
     218              : template <typename TBase, typename TDerived>
     219              : void ClassCastProvider::add_cast_func()
     220              : {
     221              :         const ClassNameNode* pBaseNode =
     222              :                                                 &ClassNameProvider<TBase>::class_name_node();
     223              :         const ClassNameNode* pDerivNode =
     224              :                                                 &ClassNameProvider<TDerived>::class_name_node();
     225              : 
     226              :         std::pair<const ClassNameNode*, const ClassNameNode*>
     227              :                                                                                 namePair(pBaseNode, pDerivNode);
     228              : 
     229         1033 :         m_mmCast[namePair] = &StaticVoidCast<TBase, TDerived>;
     230              : }
     231              : 
     232              : template <typename T>
     233            0 : T* ClassCastProvider::
     234              : cast_to(void* ptr, const ClassNameNode*& node)
     235              : {
     236              : //      get base name
     237              :         const std::string& baseName = ClassNameProvider<T>::name();
     238              : 
     239              : //      cast the plain pointer
     240            0 :         ptr = ClassCastProvider::cast_to_base_class(ptr, node, baseName);
     241              : 
     242              : //      return it
     243            0 :         return reinterpret_cast<T*>(ptr);
     244              : }
     245              : 
     246              : template <typename T>
     247            0 : const T* ClassCastProvider::
     248              : cast_to(const void* ptr, const ClassNameNode*& node)
     249              : {
     250              : //      get base name
     251              :         const std::string& baseName = ClassNameProvider<T>::name();
     252              : 
     253              : //      cast the plain pointer
     254            0 :         ptr = ClassCastProvider::cast_to_base_class(ptr, node, baseName);
     255              : 
     256              : //      return it
     257            0 :         return reinterpret_cast<const T*>(ptr);
     258              : }
     259              : 
     260              : template <typename T>
     261            0 : SmartPtr<T> ClassCastProvider::
     262              : cast_to(SmartPtr<void> spDerivVoid, const ClassNameNode*& node)
     263              : {
     264              : //      get base name
     265              :         const std::string& baseName = ClassNameProvider<T>::name();
     266              : 
     267              : //      extract plain pointer
     268              :         void* rawPtr = spDerivVoid.get();
     269              : 
     270              : //      cast the plain pointer
     271            0 :         rawPtr = ClassCastProvider::cast_to_base_class(rawPtr, node, baseName);
     272              : 
     273              : //      sets as pointer to the smart ptr
     274              :         spDerivVoid.set_impl<T, FreeDelete>(rawPtr);
     275              : 
     276              : //      return it
     277            0 :         return spDerivVoid.cast_reinterpret<T, FreeDelete>();
     278              : }
     279              : 
     280              : template <typename T>
     281            0 : ConstSmartPtr<T> ClassCastProvider::
     282              : cast_to(ConstSmartPtr<void> spDerivVoid, const ClassNameNode*& node)
     283              : {
     284              : //      get base name
     285              :         const std::string& baseName = ClassNameProvider<T>::name();
     286              : 
     287              : //      extract plain pointer
     288              :         const void* rawPtr = spDerivVoid.get();
     289              : 
     290              : //      cast the plain pointer
     291            0 :         rawPtr = ClassCastProvider::cast_to_base_class(rawPtr, node, baseName);
     292              : 
     293              : //      sets as pointer to the smart ptr
     294              :         spDerivVoid.set_impl<T, FreeDelete>(rawPtr);
     295              : 
     296              : //      return it
     297            0 :         return spDerivVoid.cast_reinterpret<T, FreeDelete>();
     298              : }
     299              : } // end namespace ug
     300              : } // end namespace bridge
     301              : 
     302              : #endif /* __H__UG_BRIDGE__CLASS_NAME_PROVIDER_IMPL__ */
        

Generated by: LCOV version 2.0-1