Open FFBoard
Open source force feedback firmware
ClassChooser.h
Go to the documentation of this file.
1/*
2 * ClassChooser.h
3 *
4 * Created on: 18.02.2020
5 * Author: Yannick
6 */
7
8#ifndef CLASSCHOOSER_H_
9#define CLASSCHOOSER_H_
10
11#include "vector"
12#include "ChoosableClass.h"
13#include <functional>
14#include "Singleton.h"
15#include <optional>
16#include "CommandHandler.h"
17#include "SystemCommands.h"
18
19// If the class is a singleton do not create a new instance if one already exists. Return the existing pointer.
20
21
22template<class B>
24{
26 uint16_t selectionId;
27 std::function<B *()> create;
28 std::function<bool ()> isCreatable = []() -> bool { return true; };
29// std::function<bool (T cls)> isCreatable = [](T cls){ ChoosableClass* c = dynamic_cast<ChoosableClass*>(cls); return (c != NULL) ? c::isCreatable() : true;}
30};
31
32//template<class T,class B>
33//constexpr class_entry<B> add_class()
34//{
35// if constexpr(std::is_base_of<Singleton<T>, T>::value){
36// return { T::info,T::info.id, []() -> B * { return Singleton<T>::getInstance(); },T::isCreatable };
37// }else{
39// return { T::info,T::info.id, []() -> B * { return new T; } , T::isCreatable};
40// }
41//}
42
43template<class T,class B>
44constexpr class_entry<B> add_class(std::optional<uint16_t> selectionId=std::nullopt)
45{
46 if(!selectionId.has_value())
47 selectionId = T::info.id;
48
49 if constexpr(std::is_base_of<Singleton<T>, T>::value){
50 return { T::info,selectionId.value(), []() -> B * { return Singleton<T>::getInstance(); },T::isCreatable };
51 }else{
52// return { T::info, []() -> B * { return new T; } };
53 return { T::info,selectionId.value(), []() -> B * { return new T; } , T::isCreatable };
54 }
55}
56
57
58//template<class T,class B>
59//class_entry<B> add_class_ref(B* ref)
60//{
61// return { T::info,T::info.id, [ref]() -> B * { return ref; } ,T::isCreatable};
62//}
63//template<class B>
64//class_entry<B> make_class_entry(ClassIdentifier info,B* ref)
65//{
66// return { info,T::info.id, [ref]() -> B * { return ref; },ref->isCreatable };
67//}
68// Override selection id for internal lists
69template<class T,class B>
70constexpr class_entry<B> add_class_ref(B* ref,std::optional<uint16_t> selectionId=std::nullopt)
71{
72 if(!selectionId.has_value())
73 selectionId = T::info.id;
74
75 return { T::info,selectionId, [ref]() -> B * { return ref; } ,T::isCreatable};
76}
77template<class B>
78constexpr class_entry<B> make_class_entry(ClassIdentifier info,B* ref,std::optional<uint16_t> selectionId=std::nullopt)
79{
80 if(!selectionId.has_value())
81 selectionId = B::info.id;
82 return { info,selectionId, [ref]() -> B * { return ref; },ref->isCreatable };
83}
84
85// TODO make this constexpr with fixed memory so the registry is not stored on heap
86template<class T>
88public:
89 ClassChooser(const std::vector<class_entry<T>>& classes) : class_registry(&classes){
90 //this->class_registry = classes;
91 }
93
94 }
95
96
100 T* Create(uint16_t id){
101 T* cls = nullptr;
102 for(const class_entry<T>& e : *class_registry){
103
104 if(e.selectionId == id && e.isCreatable()){
105 cls = e.create();
106 cls->selectionId = id;
107 }
108 }
109 return cls;
110 }
111
116 bool isCreatable(uint16_t id){
117 for(const class_entry<T>& e : *class_registry){
118 if(e.selectionId == id && e.isCreatable()){
119 return true;
120 }
121 }
122 return false;
123 }
124
125
129 void replyAvailableClasses(std::vector<CommandReply>& replies,int16_t ignoredCreatableId = 255){
130 for(const class_entry<T>& cls : *class_registry){
131 if(cls.info.visibility == ClassVisibility::hidden || (cls.info.visibility == ClassVisibility::debug && !SystemCommands::debugMode)){
132 if(ignoredCreatableId != cls.selectionId)
133 continue;
134 }
135// std::string ret;
136 CommandReply replyObj;
137 replyObj.reply+= std::to_string(cls.selectionId);
138 replyObj.reply+= ":";
139 replyObj.reply+= (cls.isCreatable() || ignoredCreatableId == cls.selectionId) ? "1" : "0";
140 replyObj.reply+= ":";
141 replyObj.reply+= cls.info.name;
142
143 if(cls.isCreatable()){
145 replyObj.adr = cls.selectionId;
146 replyObj.val = cls.info.id;
147 }else{
149 }
150// replyObj.reply = ret;
151 replies.push_back(replyObj);
152 }
153 }
154
155
159 bool isValidClassId(uint16_t id){
160 for(const class_entry<T>& cls : *class_registry){
161 if(cls.selectionId == id){
162 return true;
163 }
164 }
165 return false;
166 }
167private:
168 const std::vector<class_entry<T>>* class_registry;
169
170};
171
172#endif /* CLASSCHOOSER_H_ */
constexpr class_entry< B > add_class(std::optional< uint16_t > selectionId=std::nullopt)
Definition: ClassChooser.h:44
constexpr class_entry< B > add_class_ref(B *ref, std::optional< uint16_t > selectionId=std::nullopt)
Definition: ClassChooser.h:70
constexpr class_entry< B > make_class_entry(ClassIdentifier info, B *ref, std::optional< uint16_t > selectionId=std::nullopt)
Definition: ClassChooser.h:78
bool isCreatable(uint16_t id)
Definition: ClassChooser.h:116
bool isValidClassId(uint16_t id)
Definition: ClassChooser.h:159
T * Create(uint16_t id)
Definition: ClassChooser.h:100
void replyAvailableClasses(std::vector< CommandReply > &replies, int16_t ignoredCreatableId=255)
Definition: ClassChooser.h:129
const std::vector< class_entry< T > > * class_registry
Definition: ClassChooser.h:168
ClassChooser(const std::vector< class_entry< T > > &classes)
Definition: ClassChooser.h:89
std::string reply
CommandReplyType type
static T * getInstance()
Definition: Singleton.h:32
static bool debugMode
Definition: ClassChooser.h:24
std::function< B *()> create
Definition: ClassChooser.h:27
uint16_t selectionId
Definition: ClassChooser.h:26
std::function< bool()> isCreatable
Definition: ClassChooser.h:28
ClassIdentifier & info
Definition: ClassChooser.h:25