AnimEngine
Core_Utilities.hpp
1 #pragma once
2 #ifndef KJY_OBJECT_ORIENTED_OPENGL_CORE_UTILITIES_HPP_
3 #define KJY_OBJECT_ORIENTED_OPENGL_CORE_UTILITIES_HPP_
4 #include <map>
5 #include <vector>
6 #include <optional>
7 #include <type_traits>
8 #include "OOOGL_Core.hpp"
9 
10 namespace OOOGL {
11 
12 
13 /* ------- Possessor Utilities ------- */
14 
15 template<class... Possessibles> class AbstractGenericPossessor{
16  protected:
17  std::map<GLuint, ConstPersistentOglName> possessed_items;
18 };
19 
20 template<class P, class... Possessibles>
21 class AbstractGenericPossessor<P, Possessibles...> : public OglPossessorInterface<P>, public AbstractGenericPossessor<Possessibles...>{
22  typedef std::pair<GLuint, ConstPersistentOglName> item_pair_t;
23  public:
24  virtual size_t numPossessed() const {return(AbstractGenericPossessor::possessed_items.size());}
25  virtual void possessObject(P possessible_object) override{
26  AbstractGenericPossessor::possessed_items.emplace(item_pair_t(possessible_object.getNameDirect(), possessible_object));
27  }
28  virtual bool doesPossessObject(P possessible_object) const override{
29  return(AbstractGenericPossessor::possessed_items.find(possessible_object.getNameDirect()) == AbstractGenericPossessor::possessed_items.end());
30  }
31  virtual void dispossessObject(const P& possessible_object) override{
32  if(doesPossessObject(possessible_object)){
33  AbstractGenericPossessor::possessed_items.erase(possessible_object.getNameDirect());
34  }
35  }
36 };
37 
38 
40  : public OglPossessorInterface<PersistentOglName, ConstPersistentOglName, OglObject>
41 {
42  public:
43  virtual void possessObject(PersistentOglName object) override;
44  virtual void possessObject(ConstPersistentOglName object) override;
45  virtual void possessObject(OglObject object) override;
46 
47  virtual bool doesPossessObject(PersistentOglName object) const override;
48  virtual bool doesPossessObject(ConstPersistentOglName object) const override;
49  virtual bool doesPossessObject(OglObject object) const override;
50 
51  virtual void dispossessObject(const PersistentOglName& object) override;
52  virtual void dispossessObject(const ConstPersistentOglName& object) override;
53  virtual void dispossessObject(const OglObject& object) override;
54 
55  protected:
56  std::map<GLuint, ConstPersistentOglName> possessed_items;
57 };
58 
59 /* ------- My own specialized optional container for OpenGL objects */
60 
61 template<class T>
63  public:
64 
65  struct EmptyOptionalException : public std::exception{
66  virtual const char* what() const noexcept override{
67  return("Optional OpenGL object does not contain a value");
68  }
69  };
70 
71  OptionalGlObject() : _encapsulated_object_(_zombie_name) {}
72  OptionalGlObject(const T& t) : _encapsulated_object_(t) {}
73  template<typename... Args> OptionalGlObject(Args&&... args) : _encapsulated_object_(args...) {}
74 
75  void reset() {_encapsulated_object_ = T(_zombie_name);}
76  bool has_value() const {return(_has_value_());}
77  T& value() & {_assert_has_value(); return(_encapsulated_object_);}
78  const T& value() const& {_assert_has_value(); return(_encapsulated_object_);}
79  // T&& value() && {_assert_has_value(); return(_encapsulated_object_);}
80  // const T&& value() const&& {_assert_has_value(); return(_encapsulated_object_);}
81 
82  template<typename... Args> void emplace(Args&&... args) {_encapsulated_object_ = T(args...);}
83 
84  OptionalGlObject& operator=(const std::nullopt_t nullopt){_encapsulated_object_ = T(_zombie_name);}
85  const T* operator->() const {_assert_has_value(); return(&_encapsulated_object_);}
86  T* operator->() {_assert_has_value(); return(&_encapsulated_object_);}
87  const T& operator*() const& {_assert_has_value(); return(_encapsulated_object_);}
88  T& operator*() & {_assert_has_value(); return(_encapsulated_object_);}
89  // const T&& operator*() const&& {_assert_has_value(); return(_encapsulated_object_);}
90  // T&& operator*() && {_assert_has_value(); return(_encapsulated_object_);}
91  operator bool() const {return(_has_value_());}
92 
93  private:
94  inline bool _has_value_() const {return(!_encapsulated_object_.isZombie());}
95  inline void _assert_has_value() const {if(!_has_value_()) throw EmptyOptionalException();}
96  T _encapsulated_object_;
97 };
98 
99 
100 
101 /* ------- Indexed Binding Vector ------- AKA: Home of the least readable code I've ever written */
102 
104  public:
105  IndexBindingInvalidIndexException(GLuint index) : _whatstr("Invalid index in access of IndexBindingVector: '" + std::to_string(index) + "'") {}
106  virtual const char* what() const noexcept override{return(_whatstr.c_str());}
107  private:
108  const std::string _whatstr;
109 };
111  public:
112  UnoccupiedIndexException(GLuint index) : _whatstr("Attempted to extract reference from unoccupied index in IndexBindingVector: '" + std::to_string(index) + "'") {}
113  virtual const char* what() const noexcept override{return(_whatstr.c_str());}
114  private:
115  const std::string _whatstr;
116 };
117 
118 template<class BoundType, class IteratorBundle, typename SizeType = size_t, class Allocator = std::allocator<BoundType>>
120  public:
121  using iterator = typename IteratorBundle::iterator;
122  using const_iterator = typename IteratorBundle::const_iterator;
123  using size_type = SizeType;
124  using allocator_type = Allocator;
125 
126  bool isOccupied(size_type pos) const = delete;
127  iterator begin() = delete;
128  const_iterator begin() const = delete;
129  BoundType& at(size_type pos) = delete;
130  const BoundType& at(size_type pos) const = delete;
131  size_type size() const = delete;
132  void set(size_type pos, const BoundType& value) = delete;
133  void clear() = delete;
134  void clearIndex(size_type pos) = delete;
135  iterator erase(iterator pos) = delete;
136  const_iterator erase(const_iterator pos) = delete;
137 };
138 
139 template<typename internal_iterator, template<typename _internal_iterator> class OccupationChecker, typename index_type = GLuint>
141  template<typename B, typename IB, typename ST, typename A>
142  friend class IndexBindingVectorInferface;
143  static_assert(std::is_trivially_constructible<OccupationChecker<internal_iterator>>::value, "Occupation checker must be trivially constructable");
144  static_assert(std::is_invocable<OccupationChecker<internal_iterator>, internal_iterator>::value, "Occupation checker must be a callable bool function taking <internal_iterator> as its only parameter");
145  using reference = std::nullptr_t /*error_t* no error_t on some compilers*/ ; // Intended to be overwritten by derived class
146  using pointer = std::nullptr_t /*error_t* no error_t on some compilers*/ ; // Intended to be overwritten by derived class
147 
148  AbstractIndexedBindingIterator(const internal_iterator& start, const internal_iterator& end) : _internal(start), _end(end) {}
149  reference operator*() const = delete;
150  pointer operator->() const = delete;
151  AbstractIndexedBindingIterator& operator++(){
152  if(_internal == _end) return(*this);
153  do{
154  index++;
155  std::advance(_internal,1);
156  }while(_internal != _end && !_is_occupied(_internal));
157  return(*this);
158  }
159  AbstractIndexedBindingIterator operator++(int) {const auto tmp(*this); ++*this; return(tmp);}
160  bool equal(AbstractIndexedBindingIterator const& rhs) const {return(_internal == rhs._internal);}
161  bool operator==(const AbstractIndexedBindingIterator& other) const {return(equal(other));}
162  bool operator!=(const AbstractIndexedBindingIterator& other) const {return(!equal(other));}
163  index_type getIndex() const {return(index);}
164  protected:
165  index_type index = 0;
166  internal_iterator _internal;
167  internal_iterator _end;
168  const OccupationChecker<internal_iterator> _is_occupied;
169 };
170 
171 template<typename iterator>
172 struct IndexedPointersOccupationChecker{ IndexedPointersOccupationChecker() = default; bool operator()(iterator itr) const {return(bool(*itr));} };
173 
174 template<class BoundType, typename internal_iterator, template<typename _internal_iterator> class OccupationChecker>
175 struct IndexedPointersBindingIteratorTemplate : public AbstractIndexedBindingIterator<internal_iterator, OccupationChecker>
176 {
178  using reference = std::pair<GLuint, BoundType&>;
179  using pointer = BoundType*;
180  IndexedPointersBindingIteratorTemplate(const internal_iterator& start, const internal_iterator& end) : Abstract_Parent(start, end) {}
182  reference operator*() const{
183  return(std::pair<GLuint, BoundType&>(Abstract_Parent::index, **Abstract_Parent::_internal));
184  }
185  pointer operator->() const{
186  return(&**Abstract_Parent::_internal);
187  }
188 };
189 
190 template<class BoundType>
193  // < BoundType, internal iterator, callable object to check if index is occupied >
194  <BoundType, typename std::vector<BoundType*>::iterator, IndexedPointersOccupationChecker>
195  ;
197  // < BoundType, internal iterator, callable object to check if index is occupied >
198  <BoundType, typename std::vector<BoundType*>::const_iterator, IndexedPointersOccupationChecker>
199  ;
200 };
201 
202 template<class BoundType>
203 class IndexedPointersVector : public IndexBindingVectorInferface<BoundType, IndexedPointersIteratorBundle<BoundType>>, protected std::vector<BoundType*>{
204  public:
205  typedef std::vector<BoundType*> base_vector;
206  using internal_iterator = typename std::vector<BoundType*>::iterator;
207  using const_internal_iterator =typename std::vector<BoundType*>::const_iterator;
209  using const_iterator = typename IndexBindingVectorInferface<BoundType, IndexedPointersIteratorBundle<BoundType>>::const_iterator;
210  using reference = typename const_iterator::reference;
211  using const_reference = typename const_iterator::reference;
212  using size_type = typename std::vector<BoundType*>::size_type;
213  using allocator_type = typename std::vector<BoundType*>::allocator_type;
214 
215  public:
216  IndexedPointersVector() : base_vector() {}
217  IndexedPointersVector(size_type count, BoundType* value, const allocator_type& alloc = allocator_type()) : base_vector(count, value, alloc) {}
219  for(const_internal_iterator itr = base_vector::begin(); itr != base_vector::end(); itr++){
220  if(*itr!=nullptr) delete *itr;
221  }
222  }
223 
224  iterator begin() {return(IndexedPointersVector<BoundType>::iterator(base_vector::begin(), base_vector::end()));}
225  const_iterator begin() const {return(IndexedPointersVector<BoundType>::const_iterator(base_vector::begin(), base_vector::end()));}
226  iterator end() {return(IndexedPointersVector<BoundType>::iterator(base_vector::end(), base_vector::end()));}
227  const_iterator end() const {return(IndexedPointersVector<BoundType>::const_iterator(base_vector::end(), base_vector::end()));}
228  internal_iterator beginInternal() {return(base_vector::begin());}
229  const_internal_iterator beginInternal() const {return(base_vector::begin());}
230  internal_iterator endInternal() {return(base_vector::end());}
231  const_internal_iterator endInternal() const {return(base_vector::end());}
232 
233  inline bool isOccupied(size_type pos) const {return(pos >= 0 && pos < base_vector::size() && base_vector::at(pos) != nullptr);}
234 
235  BoundType& at(size_type pos) {_assert_occupied_index(pos); return(*base_vector::at(pos));}
236  const BoundType& at(size_type pos) const {_assert_occupied_index(pos); return(*base_vector::at(pos));}
237  inline BoundType& operator[](size_type pos) {return(at(pos));}
238  inline const BoundType& operator[](size_type pos) const {return(at(pos));}
239  size_type size() const {return(_occupied_count);}
240  using base_vector::capacity;
241 
242  void set(size_type pos, const BoundType& value) {
243  _assert_valid_index(pos);
244  if(isOccupied(pos)){
245  delete base_vector::at(pos);
246  }else{
247  _occupied_count++;
248  }
249  base_vector::at(pos) = new BoundType(value);
250  }
251  void clearIndex(size_type pos) {
252  _assert_valid_index(pos);
253  const BoundType* ptr_at_index = base_vector::at(pos);
254  if(ptr_at_index != nullptr){
255  delete ptr_at_index;
256  base_vector::at(pos) = nullptr;
257  _occupied_count--;
258  }
259  }
260  void clear(){
261  for(internal_iterator itr = base_vector::begin(); itr != base_vector::end(); itr++){
262  if(*itr != nullptr) delete (*itr);
263  }
264  _occupied_count = 0;
265  }
266  iterator erase(iterator pos){
267  if(pos == end()) return(end());
268  clearIndex(pos.getIndex());
269  return(++pos);
270  }
271  const_iterator erase(const_iterator pos){
272  if(pos == end()) return(end());
273  clearIndex(pos.getIndex());
274  return(++pos);
275  }
276 
277  private:
278  size_t _occupied_count = 0;
279  void _assert_valid_index(size_type index){if(index < 0 || index >= base_vector::size()) throw IndexBindingInvalidIndexException(index);}
280  void _assert_occupied_index(size_type index){_assert_valid_index(index); if(!isOccupied(index)) throw UnoccupiedIndexException(index);}
281 };
282 
283 template<typename iterator>
284 struct OptionalOccupationChecker{OptionalOccupationChecker() = default; bool operator()(iterator itr) const {return(*itr);}};
285 
286 template<class BoundType>
289  // < BoundType, internal iterator, callable object to check if index is occupied >
290  <BoundType, typename std::vector<std::optional<BoundType>>::iterator, IndexedPointersOccupationChecker>
291  ;
293  // < BoundType, internal iterator, callable object to check if index is occupied >
294  <BoundType, typename std::vector<std::optional<BoundType>>::const_iterator, IndexedPointersOccupationChecker>
295  ;
296 };
297 
298 template<class BoundType>
299 class OptionalIndexedBindingVector : public IndexBindingVectorInferface<BoundType, OptionalIteratorBundle<BoundType>>, protected std::vector<std::optional<BoundType>>{
300  public:
301  typedef std::vector<std::optional<BoundType>> base_vector;
302  using internal_iterator = typename base_vector::iterator;
303  using const_internal_iterator =typename base_vector::const_iterator;
305  using const_iterator = typename IndexBindingVectorInferface<BoundType, OptionalIteratorBundle<BoundType>>::const_iterator;
306  using reference = typename const_iterator::reference;
307  using const_reference = typename const_iterator::reference;
308  using size_type = typename base_vector::size_type;
309  using allocator_type = typename base_vector::allocator_type;
310 
311  public:
312  OptionalIndexedBindingVector() : base_vector() {}
313  OptionalIndexedBindingVector(size_type count, const std::optional<BoundType>& value, const allocator_type& alloc = allocator_type()) : base_vector(count, value, alloc) {}
314  OptionalIndexedBindingVector(size_type count) : OptionalIndexedBindingVector(count, std::optional<BoundType>()) {}
315 
316  iterator begin() {return(OptionalIndexedBindingVector<BoundType>::iterator(base_vector::begin(), base_vector::end()));}
317  const_iterator begin() const {return(OptionalIndexedBindingVector<BoundType>::const_iterator(base_vector::begin(), base_vector::end()));}
318  iterator end() {return(OptionalIndexedBindingVector<BoundType>::iterator(base_vector::end(), base_vector::end()));}
319  const_iterator end() const {return(OptionalIndexedBindingVector<BoundType>::const_iterator(base_vector::end(), base_vector::end()));}
320  internal_iterator beginInternal() {return(base_vector::begin());}
321  const_internal_iterator beginInternal() const {return(base_vector::begin());}
322  internal_iterator endInternal() {return(base_vector::end());}
323  const_internal_iterator endInternal() const {return(base_vector::end());}
324 
325  inline bool isOccupied(size_type pos) const {return(pos >= 0 && pos < base_vector::size() && base_vector::at(pos));}
326 
327  BoundType& at(size_type pos) {_assert_occupied_index(pos); return(*base_vector::at(pos));}
328  const BoundType& at(size_type pos) const {_assert_occupied_index(pos); return(*base_vector::at(pos));}
329  inline BoundType& operator[](size_type pos) {return(at(pos));}
330  inline const BoundType& operator[](size_type pos) const {return(at(pos));}
331  size_type size() const {return(_occupied_count);}
332  using base_vector::capacity;
333 
334  void set(size_type pos, const BoundType& value) {
335  _assert_valid_index(pos);
336  if(!isOccupied(pos)){
337  _occupied_count++;
338  }
339  base_vector::at(pos) = std::optional<BoundType>(value);
340  }
341  void clearIndex(size_type pos) {
342  _assert_valid_index(pos);
343  if(base_vector::at(pos)){
344  base_vector::at(pos) = std::optional<BoundType>();
345  _occupied_count--;
346  }
347  }
348  void clear(){
349  for(internal_iterator itr = base_vector::begin(); itr != base_vector::end(); itr++){
350  *itr = std::optional<BoundType>();
351  }
352  _occupied_count = 0;
353  }
354  iterator erase(iterator pos){
355  if(pos == end()) return(end());
356  clearIndex(pos.getIndex());
357  return(++pos);
358  }
359  const_iterator erase(const_iterator pos){
360  if(pos == end()) return(end());
361  clearIndex(pos.getIndex());
362  return(++pos);
363  }
364 
365  private:
366  size_t _occupied_count = 0;
367  void _assert_valid_index(size_type index) const {if(index < 0 || index >= base_vector::size()) throw IndexBindingInvalidIndexException(index);}
368  void _assert_occupied_index(size_type index) const {_assert_valid_index(index); if(!isOccupied(index)) throw UnoccupiedIndexException(index);}
369 };
370 
371 } // namespace OOOGL
372 
373 #endif
Definition: Core_Utilities.hpp:119
Definition: Core_Utilities.hpp:103
Definition: Core_Utilities.hpp:203
Definition: OOOGL_Core.hpp:92
Definition: Core_Utilities.hpp:15
Definition: OOOGL_Core.hpp:119
Definition: Core_Utilities.hpp:39
Definition: OOOGL_Core.hpp:144
Definition: Core_Utilities.hpp:191
Definition: OOOGL_Core.hpp:105
Definition: Core_Utilities.hpp:140
Definition: OOOGL_Core.hpp:74
Definition: Core_Utilities.hpp:175
Definition: Core_Utilities.hpp:62
Definition: Core_Utilities.hpp:299
Definition: Core_Utilities.hpp:110
Definition: Core_Utilities.cpp:3
Definition: Core_Utilities.hpp:287
Definition: Core_Utilities.hpp:284
Definition: Core_Utilities.hpp:65
Definition: Core_Utilities.hpp:172