MacStd
OS X API using Standard C++
Loading...
Searching...
No Matches
common.hpp
1/*
2 SPDX-License-Identifier: MIT
3 Copyright © 2023-2024 Amebis
4*/
5
6#pragma once
7
8#include <stddef.h>
9
13#define MACSTD_NONCOPYABLE(C) \
14private: \
15 C (_In_ const C &h) noexcept; \
16 C& operator=(_In_ const C &h) noexcept;
17
21#define MACSTD_NONMOVABLE(C) \
22private: \
23 C (_Inout_ C &&h) noexcept; \
24 C& operator=(_Inout_ C &&h) noexcept;
25
33#define MACSTD_STACK_BUFFER_BYTES 1024
34
38#define MACSTD_HANDLE_IMPL(C, T, INVAL) \
39public: \
40 C ( ) noexcept {} \
41 C (_In_opt_ T h) noexcept : handle<T, INVAL>( h ) {} \
42 C (_Inout_ C &&h) noexcept : handle<T, INVAL>(std::move(h)) {} \
43 C& operator=(_In_opt_ T h) noexcept { handle<T, INVAL>::operator=( h ); return *this; } \
44 C& operator=(_Inout_ C &&h) noexcept { handle<T, INVAL>::operator=(std::move(h)); return *this; } \
45MACSTD_NONCOPYABLE(C)
46
50#define MACSTD_DPLHANDLE_IMPL(C, T, INVAL) \
51public: \
52 C ( ) noexcept {} \
53 C (_In_opt_ T h) noexcept : dplhandle<T, INVAL>( h ) {} \
54 C (_In_ const C &h) noexcept : dplhandle<T, INVAL>(duplicate_internal(h.m_h)) {} \
55 C (_Inout_ C &&h) noexcept : dplhandle<T, INVAL>(std::move (h )) {} \
56 C& operator=(_In_opt_ T h) noexcept { dplhandle<T, INVAL>::operator=( h ); return *this; } \
57 C& operator=(_In_ const C &h) noexcept { dplhandle<T, INVAL>::operator=( h ); return *this; } \
58 C& operator=(_Inout_ C &&h) noexcept { dplhandle<T, INVAL>::operator=(std::move(h)); return *this; } \
59private:
60
61namespace macstd
62{
68 template <class T, const T INVAL>
69 class handle
70 {
71 public:
75 handle() noexcept : m_h(INVAL)
76 {}
77
83 handle(_In_opt_ T h) noexcept : m_h(h)
84 {}
85
91 handle(_Inout_ handle<T, INVAL> &&h) noexcept
92 {
93 // Transfer handle.
94 m_h = h.m_h;
95 h.m_h = INVAL;
96 }
97
98 private:
99 // This class is noncopyable.
100 handle(_In_ const handle<T, INVAL> &h) noexcept {};
101 handle<T, INVAL>& operator=(_In_ const handle<T, INVAL> &h) noexcept {};
102
103 public:
109 handle<T, INVAL>& operator=(_In_opt_ T h) noexcept
110 {
111 attach(h);
112 return *this;
113 }
114
120 #pragma warning(suppress: 26432) // Move constructor is also present, but not detected by code analysis somehow.
122 {
123 if (this != std::addressof(h)) {
124 // Transfer handle.
125 if (m_h != INVAL)
127 m_h = h.m_h;
128 h.m_h = INVAL;
129 }
130 return *this;
131 }
132
138 operator T() const
139 {
140 return m_h;
141 }
142
148 T*& operator*() const
149 {
150 assert(m_h != INVAL);
151 return *m_h;
152 }
153
159 {
160 assert(m_h == INVAL);
161 return &m_h;
162 }
163
169 T operator->() const
170 {
171 assert(m_h != INVAL);
172 return m_h;
173 }
174
185 bool operator!() const
186 {
187 return m_h == INVAL;
188 }
189
198 bool operator<(_In_opt_ T h) const
199 {
200 return m_h < h;
201 }
202
211 bool operator<=(_In_opt_ T h) const
212 {
213 return !operator>(h);
214 }
215
224 bool operator>=(_In_opt_ T h) const
225 {
226 return !operator<(h);
227 }
228
237 bool operator>(_In_opt_ T h) const
238 {
239 return h < m_h;
240 }
241
250 bool operator!=(_In_opt_ T h) const
251 {
252 return !operator==(h);
253 }
254
263 bool operator==(_In_opt_ T h) const
264 {
265 return m_h == h;
266 }
267
275 void attach(_In_opt_ T h) noexcept
276 {
277 if (m_h != INVAL)
279 m_h = h;
280 }
281
288 {
289 T h = m_h;
290 m_h = INVAL;
291 return h;
292 }
293
297 void free()
298 {
299 if (m_h != INVAL) {
301 m_h = INVAL;
302 }
303 }
304
305 protected:
309 virtual void free_internal() noexcept = 0;
310
311 protected:
312 T m_h;
313 };
314
318 template <class T, T INVAL>
319 class dplhandle : public handle<T, INVAL>
320 {
321 public:
325 dplhandle() noexcept
326 {}
327
333 dplhandle(_In_opt_ T h) noexcept : handle<T, INVAL>(h)
334 {}
335
341 dplhandle<T, INVAL>(_In_ const dplhandle<T, INVAL> &h) : handle<T, INVAL>(duplicate_internal(h.m_h))
342 {}
343
349 dplhandle<T, INVAL>(_Inout_ dplhandle<T, INVAL> &&h) noexcept : handle<T, INVAL>(std::move(h))
350 {}
351
357 dplhandle<T, INVAL>& operator=(_In_opt_ T h) noexcept
358 {
360 return *this;
361 }
362
369 {
370 if (this != std::addressof(h)) {
371 if (h.m_h != INVAL) {
372 T h_new = duplicate_internal(h.m_h);
373
374 if (this->m_h != INVAL)
375 this->free_internal();
376
377 this->m_h = h_new;
378 } else {
379 if (this->m_h != INVAL)
380 this->free_internal();
381
382 this->m_h = INVAL;
383 }
384 }
385 return *this;
386 }
387
393 #pragma warning(disable: 26432) // Move constructor is also present, but not detected by code analysis somehow.
395 {
396 handle<T, INVAL>::operator=(std::move(h));
397 return *this;
398 }
399
405 T duplicate() const
406 {
407 return this->m_h != INVAL ? duplicate_internal(this->m_h) : INVAL;
408 }
409
415 void attach_duplicated(_In_opt_ T h)
416 {
417 if (this->m_h != INVAL)
418 this->free_internal();
419
420 this->m_h = h != INVAL ? duplicate_internal(h) : INVAL;
421 }
422
423 protected:
432 virtual T duplicate_internal(_In_ T h) const = 0;
433 };
434}
Base abstract template class to support object handle keeping for objects that support trivial handle...
Definition common.hpp:320
dplhandle() noexcept
Initializes a new class instance with the object handle set to INVAL.
Definition common.hpp:325
virtual T duplicate_internal(T h) const =0
Abstract member function that must be implemented by child classes to do the actual object handle dup...
dplhandle< T, INVAL > & operator=(T h) noexcept
Attaches already available object handle.
Definition common.hpp:357
dplhandle< T, INVAL > & operator=(dplhandle< T, INVAL > &&h) noexcept
Moves the object.
Definition common.hpp:394
dplhandle(T h) noexcept
Initializes a new class instance with an already available object handle.
Definition common.hpp:333
void attach_duplicated(T h)
Duplicates an object handle and sets a new object handle.
Definition common.hpp:415
T duplicate() const
Duplicates and returns a new object handle.
Definition common.hpp:405
dplhandle< T, INVAL > & operator=(const dplhandle< T, INVAL > &h) noexcept
Duplicates the object.
Definition common.hpp:368
Base abstract template class to support generic object handle keeping.
Definition common.hpp:70
bool operator>=(T h) const
Is handle greater than or equal to?
Definition common.hpp:224
handle< T, INVAL > & operator=(handle< T, INVAL > &&h) noexcept
Move assignment.
Definition common.hpp:121
bool operator<=(T h) const
Is handle less than or equal to?
Definition common.hpp:211
handle() noexcept
Initializes a new class instance with the object handle set to INVAL.
Definition common.hpp:75
handle(T h) noexcept
Initializes a new class instance with an already available object handle.
Definition common.hpp:83
virtual void free_internal() noexcept=0
Abstract member function that must be implemented by child classes to do the actual object destructio...
void attach(T h) noexcept
Sets a new object handle for the class.
Definition common.hpp:275
bool operator==(T h) const
Is handle equal to?
Definition common.hpp:263
T * operator&()
Returns the object handle reference.
Definition common.hpp:158
bool operator>(T h) const
Is handle greater than?
Definition common.hpp:237
T *& operator*() const
Returns the object handle value when the object handle is a pointer to a value (class,...
Definition common.hpp:148
T m_h
Object handle.
Definition common.hpp:312
bool operator!() const
Tests if the object handle is invalid.
Definition common.hpp:185
handle< T, INVAL > & operator=(T h) noexcept
Attaches already available object handle.
Definition common.hpp:109
T detach()
Dismisses the object handle from this class.
Definition common.hpp:287
bool operator!=(T h) const
Is handle not equal to?
Definition common.hpp:250
bool operator<(T h) const
Is handle less than?
Definition common.hpp:198
handle(handle< T, INVAL > &&h) noexcept
Move constructor.
Definition common.hpp:91
void free()
Destroys the object.
Definition common.hpp:297
T operator->() const
Provides object handle member access when the object handle is a pointer to a class or struct.
Definition common.hpp:169