libebml_ng
flexptr.h
Go to the documentation of this file.
1 #ifndef EBML_NG_FLEXPTR_H
2 #define EBML_NG_FLEXPTR_H
3 
4 #include <memory>
5 #include <utility>
6 #include <stdexcept>
7 #include "ptrs.h" // Assuming that ptr and wptr types are declared in ptrs.h
8 
9 namespace ebml {
10 
20  template<typename T>
21  class flexible_ptr {
22  private:
23  char _flags = 0;
24 
26  union {
31  };
32 
33  // Initialization functions for the internal pointer (using placement new).
34  void _init_ptr() {
35  new (&this->sp) ptr<T>();
36  this->_flags = 0x00;
37  }
38 
39  void _init_ptr(const ptr<T>& p) {
40  new (&this->sp) ptr<T>(p);
41  this->_flags = 0x00;
42  }
43 
44  void _init_ptr(ptr<T>&& p) {
45  new (&this->sp) ptr<T>(std::move(p));
46  this->_flags = 0x00;
47  }
48 
49  void _init_ptr(const wptr<T>& p) {
50  new (&this->wp) wptr<T>(p);
51  this->_flags = 0x01;
52  }
53 
54  void _init_ptr(wptr<T>&& p) {
55  new (&this->wp) wptr<T>(std::move(p));
56  this->_flags = 0x01;
57  }
58 
59  void _init_ptr(const ptr<const T>& p) {
60  new (&this->const_sp) ptr<const T>(p);
61  this->_flags = 0x02;
62  }
63 
64  void _init_ptr(ptr<const T>&& p) {
65  new (&this->const_sp) ptr<const T>(std::move(p));
66  this->_flags = 0x02;
67  }
68 
69  void _init_ptr(const wptr<const T>& p) {
70  new (&this->const_wp) wptr<const T>(p);
71  this->_flags = 0x03;
72  }
73 
74  void _init_ptr(wptr<const T>&& p) {
75  new (&this->const_wp) wptr<const T>(std::move(p));
76  this->_flags = 0x03;
77  }
78 
79  // Reinitializes the pointer: if the flag indicates a strong pointer,
80  // its default value is set; otherwise, the current pointer is destroyed.
81  void _reinit_ptr() {
82  if (this->_flags == 0x00) {
83  this->_set_ptr();
84  return;
85  }
86  this->_destroy_ptr();
87  this->_init_ptr();
88  }
89 
90  // Set pointer members (copy/move assign)
91  void _set_ptr() {
92  this->sp = nullptr;
93  }
94 
95  void _set_ptr(const ptr<T>& p) {
96  this->sp = p;
97  }
98 
99  void _set_ptr(ptr<T>&& p) {
100  this->sp = std::move(p);
101  }
102 
103  void _set_ptr(const ptr<const T>& p) {
104  this->const_sp = p;
105  }
106 
107  void _set_ptr(ptr<const T>&& p) {
108  this->const_sp = std::move(p);
109  }
110 
111  void _set_ptr(const wptr<T>& p) {
112  this->wp = p;
113  }
114 
115  void _set_ptr(wptr<T>&& p) {
116  this->wp = std::move(p);
117  }
118 
119  void _set_ptr(const wptr<const T>& p) {
120  this->const_wp = p;
121  }
122 
123  void _set_ptr(wptr<const T>&& p) {
124  this->const_wp = std::move(p);
125  }
126 
127  // Destroys the stored pointer, calling the appropriate destructor
128  // based on the flag bits stored in _flags.
129  void _destroy_ptr() {
130  unsigned char flags = this->_flags & 0x03;
131  switch (flags) {
132  case 0x00: {
133  using p = ptr<T>;
134  sp.~p();
135  break;
136  }
137  case 0x01: {
138  using p = wptr<T>;
139  wp.~p();
140  break;
141  }
142  case 0x02: {
143  using p = ptr<const T>;
144  const_sp.~p();
145  break;
146  }
147  case 0x03: {
148  using p = wptr<const T>;
149  const_wp.~p();
150  break;
151  }
152  }
153  }
154 
155  public:
158  _init_ptr();
159  }
160 
162  flexible_ptr(const std::nullptr_t&) {
163  _init_ptr();
164  }
165 
174  unsigned char flags = other._flags & 0x03;
175  switch (flags) {
176  case 0x00: {
177  this->_init_ptr(other.sp);
178  break;
179  }
180  case 0x01: {
181  this->_init_ptr(other.wp);
182  break;
183  }
184  case 0x02: {
185  this->_init_ptr(other.const_sp);
186  break;
187  }
188  case 0x03: {
189  this->_init_ptr(other.const_wp);
190  break;
191  }
192  }
193  }
194 
203  unsigned char flags = other._flags & 0x03;
204  switch (flags) {
205  case 0x00: {
206  this->_init_ptr(std::move(other.sp));
207  break;
208  }
209  case 0x01: {
210  this->_init_ptr(std::move(other.wp));
211  other._reinit_ptr();
212  break;
213  }
214  case 0x02: {
215  this->_init_ptr(std::move(other.const_sp));
216  other._reinit_ptr();
217  break;
218  }
219  case 0x03: {
220  this->_init_ptr(std::move(other.const_wp));
221  other._reinit_ptr();
222  break;
223  }
224  }
225  }
226 
232  flexible_ptr(const ptr<T>& p) {
233  this->_init_ptr(p);
234  }
235 
242  this->_init_ptr(std::move(p));
243  }
244 
251  this->_init_ptr(p);
252  }
253 
260  this->_init_ptr(std::move(p));
261  }
262 
268  flexible_ptr(const wptr<T>& p) {
269  this->_init_ptr(p);
270  }
271 
278  this->_init_ptr(std::move(p));
279  }
280 
287  this->_init_ptr(p);
288  }
289 
296  this->_init_ptr(std::move(p));
297  }
298 
305  this->_destroy_ptr();
306  }
307 
317  if (this == &other) {
318  return *this;
319  }
320 
321  if (this->_flags == other._flags) {
322  switch (this->_flags) {
323  case 0x00: {
324  this->_set_ptr(other.sp);
325  break;
326  }
327  case 0x01: {
328  this->_set_ptr(other.wp);
329  break;
330  }
331  case 0x02: {
332  this->_set_ptr(other.const_sp);
333  break;
334  }
335  case 0x03: {
336  this->_set_ptr(other.const_wp);
337  break;
338  }
339  }
340  return *this;
341  }
342 
343  this->_destroy_ptr();
344  switch (other._flags) {
345  case 0x00: {
346  this->_init_ptr(other.sp);
347  break;
348  }
349  case 0x01: {
350  this->_init_ptr(other.wp);
351  break;
352  }
353  case 0x02: {
354  this->_init_ptr(other.const_sp);
355  break;
356  }
357  case 0x03: {
358  this->_init_ptr(other.const_wp);
359  break;
360  }
361  }
362 
363  return *this;
364  }
365 
375  if (this == &other) {
376  return *this;
377  }
378 
379  if (this->_flags == other._flags) {
380  switch (this->_flags) {
381  case 0x00: {
382  this->_set_ptr(std::move(other.sp));
383  break;
384  }
385  case 0x01: {
386  this->_set_ptr(std::move(other.wp));
387  other._reinit_ptr();
388  break;
389  }
390  case 0x02: {
391  this->_set_ptr(std::move(other.const_sp));
392  other._reinit_ptr();
393  break;
394  }
395  case 0x03: {
396  this->_set_ptr(std::move(other.const_wp));
397  other._reinit_ptr();
398  break;
399  }
400  }
401  return *this;
402  }
403 
404  this->_destroy_ptr();
405  switch (other._flags) {
406  case 0x00: {
407  this->_init_ptr(std::move(other.sp));
408  break;
409  }
410  case 0x01: {
411  this->_init_ptr(std::move(other.wp));
412  other._reinit_ptr();
413  break;
414  }
415  case 0x02: {
416  this->_init_ptr(std::move(other.const_sp));
417  other._reinit_ptr();
418  break;
419  }
420  case 0x03: {
421  this->_init_ptr(std::move(other.const_wp));
422  other._reinit_ptr();
423  break;
424  }
425  }
426 
427  return *this;
428  }
429 
437  if (this->_flags == 0x00) {
438  this->_set_ptr(other);
439  return *this;
440  }
441  this->_destroy_ptr();
442  this->_init_ptr(other);
443  return *this;
444  }
445 
453  if (this->_flags == 0x00) {
454  this->_set_ptr(std::move(other));
455  return *this;
456  }
457  this->_destroy_ptr();
458  this->_init_ptr(std::move(other));
459  return *this;
460  }
461 
469  if (this->_flags == 0x02) {
470  this->_set_ptr(other);
471  return *this;
472  }
473  this->_destroy_ptr();
474  this->_init_ptr(other);
475  return *this;
476  }
477 
485  if (this->_flags == 0x01) {
486  this->_set_ptr(std::move(other));
487  return *this;
488  }
489  this->_destroy_ptr();
490  this->_init_ptr(std::move(other));
491  return *this;
492  }
493 
501  if (this->_flags == 0x02) {
502  this->_set_ptr(other);
503  return *this;
504  }
505  this->_destroy_ptr();
506  this->_init_ptr(other);
507  return *this;
508  }
509 
517  if (this->_flags == 0x02) {
518  this->_set_ptr(std::move(other));
519  return *this;
520  }
521  this->_destroy_ptr();
522  this->_init_ptr(std::move(other));
523  return *this;
524  }
525 
533  if (this->_flags == 0x03) {
534  this->_set_ptr(other);
535  return *this;
536  }
537  this->_destroy_ptr();
538  this->_init_ptr(other);
539  return *this;
540  }
541 
549  if (this->_flags == 0x03) {
550  this->_set_ptr(std::move(other));
551  return *this;
552  }
553  this->_destroy_ptr();
554  this->_init_ptr(std::move(other));
555  return *this;
556  }
557 
565  flexible_ptr<T>& operator=(const std::nullptr_t&) {
566  this->_reinit_ptr();
567  return *this;
568  }
569 
575  bool is_const() const {
576  return (this->_flags & 0x02);
577  }
578 
584  bool is_weak() const {
585  return (this->_flags & 0x01);
586  }
587 
596  ptr<T> get() const {
597  if (this->is_const()) {
598  throw std::runtime_error("non-const access to const object");
599  }
600  unsigned char flags = this->_flags & 0x03;
601  switch (flags) {
602  case 0x00: {
603  return this->sp;
604  }
605  case 0x01: {
606  return this->wp.lock();
607  }
608  }
609  throw std::runtime_error("this should never happen");
610  }
611 
620  ptr<const T> cget() const {
621  unsigned char flags = this->_flags & 0x03;
622  switch (flags) {
623  case 0x00: {
624  return ebml::ebml_const_pointer_cast<const T>(sp);
625  }
626  case 0x01: {
627  return ebml::ebml_const_pointer_cast<const T>(wp.lock());
628  }
629  case 0x02: {
630  return const_sp;
631  }
632  case 0x03: {
633  return const_wp.lock();
634  }
635  }
636  throw std::runtime_error("this should never happen");
637  }
638 
647  bool notnull() const {
648  unsigned char flags = this->_flags & 0x03;
649  switch (flags) {
650  case 0x00: {
651  return this->sp != nullptr;
652  }
653  case 0x01: {
654  return not this->wp.expired();
655  }
656  case 0x02: {
657  return this->const_sp != nullptr;
658  }
659  case 0x03: {
660  return not this->const_wp.expired();
661  }
662  }
663  throw std::runtime_error("this should never happen");
664  }
665  };
666 
667 } // namespace ebml
668 
669 #endif
flexible_ptr(ptr< T > &&p)
Constructs a flexible_ptr from a movable strong pointer to T.
Definition: flexptr.h:241
flexible_ptr(const ptr< T > &p)
Constructs a flexible_ptr from a strong pointer to T.
Definition: flexptr.h:232
~flexible_ptr()
Destructor.
Definition: flexptr.h:304
bool is_weak() const
Checks whether the stored pointer is a weak pointer.
Definition: flexptr.h:584
flexible_ptr< T > & operator=(wptr< const T > &&other)
Assignment operator from a movable weak pointer of type wptr<const T>.
Definition: flexptr.h:548
flexible_ptr(ptr< const T > &&p)
Constructs a flexible_ptr from a movable strong pointer to a const T.
Definition: flexptr.h:259
ptr< const T > const_sp
Stored strong pointer for const T.
Definition: flexptr.h:28
flexible_ptr(const flexible_ptr< T > &other)
Copy constructor.
Definition: flexptr.h:173
wptr< T > wp
Stored weak pointer for mutable T.
Definition: flexptr.h:29
flexible_ptr(wptr< T > &&p)
Constructs a flexible_ptr from a movable weak pointer to T.
Definition: flexptr.h:277
flexible_ptr(const ptr< const T > &p)
Constructs a flexible_ptr from a strong pointer to a const T.
Definition: flexptr.h:250
A drop-in replacement for std::weak_ptr tailored for EBML objects.
Definition: ptrs.h:30
flexible_ptr< T > & operator=(const ptr< T > &other)
Assignment operator from a strong pointer of type ptr<T>.
Definition: flexptr.h:436
ptr< const T > cget() const
Retrieves the stored strong pointer to a const T.
Definition: flexptr.h:620
flexible_ptr< T > & operator=(const flexible_ptr< T > &other)
Copy assignment operator.
Definition: flexptr.h:316
Definition: basictypes.h:40
flexible_ptr()
Default constructor. Initializes with an empty strong pointer.
Definition: flexptr.h:157
A drop-in replacement for std::shared_ptr tailored for EBML objects.
Definition: ptrs.h:27
flexible_ptr(const wptr< const T > &p)
Constructs a flexible_ptr from a weak pointer to a const T.
Definition: flexptr.h:286
flexible_ptr< T > & operator=(ptr< const T > &&other)
Assignment operator from a movable strong pointer of type ptr<const T>.
Definition: flexptr.h:516
wptr< const T > const_wp
Stored weak pointer for const T.
Definition: flexptr.h:30
flexible_ptr< T > & operator=(wptr< T > &&other)
Assignment operator from a movable weak pointer of type wptr<T>.
Definition: flexptr.h:484
flexible_ptr< T > & operator=(flexible_ptr< T > &&other)
Move assignment operator.
Definition: flexptr.h:374
flexible_ptr< T > & operator=(const ptr< const T > &other)
Assignment operator from a strong pointer of type ptr<const T>.
Definition: flexptr.h:500
A flexible pointer that can store either a strong (shared) or weak pointer.
Definition: flexptr.h:21
flexible_ptr< T > & operator=(const wptr< const T > &other)
Assignment operator from a weak pointer of type wptr<const T>.
Definition: flexptr.h:532
flexible_ptr< T > & operator=(ptr< T > &&other)
Assignment operator from a movable strong pointer of type ptr<T>.
Definition: flexptr.h:452
ptr< T > sp
Stored strong pointer for mutable T.
Definition: flexptr.h:27
flexible_ptr< T > & operator=(const std::nullptr_t &)
Assignment operator from nullptr.
Definition: flexptr.h:565
bool is_const() const
Checks whether the stored pointer is pointing to a const object.
Definition: flexptr.h:575
flexible_ptr(const std::nullptr_t &)
Constructs a flexible_ptr that is null.
Definition: flexptr.h:162
flexible_ptr< T > & operator=(const wptr< T > &other)
Assignment operator from a weak pointer of type wptr<T>.
Definition: flexptr.h:468
flexible_ptr(wptr< const T > &&p)
Constructs a flexible_ptr from a movable weak pointer to a const T.
Definition: flexptr.h:295
flexible_ptr(const wptr< T > &p)
Constructs a flexible_ptr from a weak pointer to T.
Definition: flexptr.h:268
ebml_shared_ptr< T > ebml_const_pointer_cast(const ebml_shared_ptr< U > &)
Definition: ptrs.h:777
bool notnull() const
Checks whether the stored pointer is not null.
Definition: flexptr.h:647
flexible_ptr(flexible_ptr< T > &&other)
Move constructor.
Definition: flexptr.h:202