UCommon
generics.h
Go to the documentation of this file.
1// Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
2// Copyright (C) 2015-2020 Cherokees of Idaho.
3//
4// This file is part of GNU uCommon C++.
5//
6// GNU uCommon C++ is free software: you can redistribute it and/or modify
7// it under the terms of the GNU Lesser General Public License as published
8// by the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// GNU uCommon C++ is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU Lesser General Public License for more details.
15//
16// You should have received a copy of the GNU Lesser General Public License
17// along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
18
25#ifndef _UCOMMON_GENERICS_H_
26#define _UCOMMON_GENERICS_H_
27
28#ifndef _UCOMMON_CPR_H_
29#include <ucommon/cpr.h>
30#endif
31
32#include <cstdlib>
33#include <cstring>
34#include <stdexcept>
35
36#ifndef UCOMMON_SYSRUNTIME
37#define THROW(x) throw x
38#if __cplusplus > 199711L
39#define THROWS(x)
40#define THROWS_ANY
41#else
42#define THROWS(x) throw(x)
43#define THROWS_ANY throw()
44#endif
45#else
46#define THROW(x) ::abort()
47#define THROWS(x)
48#define THROWS_ANY
49#endif
50
51namespace ucommon {
52
58template <typename T>
60{
61protected:
62 unsigned *counter;
63 T *object;
64
65public:
66 inline void release(void) {
67 if(counter && --(*counter)==0) {
68 delete counter;
69 delete object;
70 }
71 object = NULL;
72 counter = NULL;
73 }
74
75 inline void retain(void) {
76 if(counter)
77 ++*counter;
78 }
79
80 inline void set(T* ptr) {
81 if(object != ptr) {
82 release();
83 counter = new unsigned;
84 *counter = 1;
85 object = ptr;
86 }
87 }
88
89 inline void set(const pointer<T> &ref) {
90 if(object == ref.object)
91 return;
92
93 if(counter && --(*counter)==0) {
94 delete counter;
95 delete object;
96 }
97 object = ref.object;
98 counter = ref.counter;
99 if(counter)
100 ++(*counter);
101 }
102
103 inline pointer() {
104 counter = NULL;
105 object = NULL;
106 }
107
108 inline explicit pointer(T* ptr = NULL) : object(ptr) {
109 if(object) {
110 counter = new unsigned;
111 *counter = 1;
112 }
113 else
114 counter = NULL;
115 }
116
117 inline pointer(const pointer<T> &ref) {
118 object = ref.object;
119 counter = ref.counter;
120 if(counter)
121 ++(*counter);
122 }
123
124 inline pointer& operator=(const pointer<T> &ref) {
125 this->set(ref);
126 return *this;
127 }
128
129 inline pointer& operator=(T *ptr) {
130 this->set(ptr);
131 return *this;
132 }
133
134 inline ~pointer() {
135 release();
136 }
137
138 inline T& operator*() const {
139 return *object;
140 }
141
142 inline T* operator->() const {
143 return object;
144 }
145
146 inline bool operator!() const {
147 return (counter == NULL);
148 }
149
150 inline operator bool() const {
151 return counter != NULL;
152 }
153};
154
160template <typename T>
162{
163protected:
164 unsigned *counter;
165 T *array;
166
167public:
168 inline void release(void) {
169 if(counter && --(*counter)==0) {
170 delete counter;
171 delete[] array;
172 }
173 array = NULL;
174 counter = NULL;
175 }
176
177 inline void retain(void) {
178 if(counter)
179 ++*counter;
180 }
181
182 inline void set(T* ptr) {
183 if(array != ptr) {
184 release();
185 counter = new unsigned;
186 *counter = 1;
187 array = ptr;
188 }
189 }
190
191 inline void set(const array_pointer<T> &ref) {
192 if(array == ref.array)
193 return;
194
195 if(counter && --(*counter)==0) {
196 delete counter;
197 delete[] array;
198 }
199 array = ref.array;
200 counter = ref.counter;
201 if(counter)
202 ++(*counter);
203 }
204
205 inline array_pointer() {
206 counter = NULL;
207 array = NULL;
208 }
209
210 inline explicit array_pointer(T* ptr = NULL) : array(ptr) {
211 if(array) {
212 counter = new unsigned;
213 *counter = 1;
214 }
215 else
216 counter = NULL;
217 }
218
219 inline array_pointer(const array_pointer<T> &ref) {
220 array = ref.array;
221 counter = ref.counter;
222 if(counter)
223 ++(*counter);
224 }
225
226 inline array_pointer& operator=(const array_pointer<T> &ref) {
227 this->set(ref);
228 return *this;
229 }
230
231 inline array_pointer& operator=(T *ptr) {
232 this->set(ptr);
233 return *this;
234 }
235
236 inline ~array_pointer() {
237 release();
238 }
239
240 inline T* operator*() const {
241 return array;
242 }
243
244 inline T& operator[](size_t offset) const {
245 return array[offset];
246 }
247
248 inline T* operator()(size_t offset) const {
249 return &array[offset];
250 }
251
252 inline bool operator!() const {
253 return (counter == NULL);
254 }
255
256 inline operator bool() const {
257 return counter != NULL;
258 }
259};
260
265template<typename T>
267{
268private:
269 T *original;
270 T temp;
271
272 save_restore() __DELETED;
273
274public:
279 inline save_restore(T& object) {
280 original = &object; temp = object;
281 }
282
286 inline ~save_restore() {
287 *original = temp;
288 }
289};
290
296template<typename T>
297inline bool is(T& object) {
298 return object.operator bool();
299}
300
307template<typename T>
308inline bool isnull(T& object) {
309 return (bool)(object.operator*() == nullptr);
310}
311
318template<typename T>
319inline bool isnullp(T *object) {
320 return (bool)(object->operator*() == nullptr);
321}
322
328template<typename T>
329inline T* dup(const T& object) {
330 return new T(object);
331}
332
333template<typename T>
334inline void dupfree(T object) {
335 delete object;
336}
337
338template<>
339inline char *dup<char>(const char& object) {
340 return strdup(&object);
341}
342
343template<>
344inline void dupfree<char*>(char* object) {
345 ::free(object);
346}
347
352template<typename T>
353inline void reset_unsafe(T& object) {
354 new((caddr_t)&object) T;
355}
356
361template<typename T>
362inline void zero_unsafe(T& object) {
363 memset((void *)&object, 0, sizeof(T)); new((caddr_t)&object) T;
364}
365
371template<typename T>
372inline void copy_unsafe(T* target, const T* source) {
373 memcpy((void *)target, (void *)source, sizeof(T));
374}
375
381template<typename T>
382inline void store_unsafe(T& target, const T* source) {
383 memcpy((void *)&target, (void *)source, sizeof(T));
384}
385
391template<typename T>
392inline void swap(T& o1, T& o2) {
393 cpr_memswap(&o1, &o2, sizeof(T));
394}
395
399template<typename T>
400inline T copy(const T& src) {
401 return T(src);
402}
403
404template<typename T>
405inline T& copy(const T& src, T& to) {
406 new((caddr_t)&to) T(src);
407 return to;
408}
409
413template<typename T>
414inline T& move(T& src, T& to) {
415 memcpy((void *)&to, (void *)&src, sizeof(T));
416 new((caddr_t)&src) T();
417 return to;
418}
419
420template<typename T>
421inline T& clear(T& o) {
422 o.~T();
423 new((caddr_t)&o) T();
424 return o;
425}
426
434template<typename T>
435inline bool bound(const T* pointer, const T* base, size_t count) {
436 if(pointer < base || pointer >= &base[count])
437 return false;
438 if(((size_t)pointer) % sizeof(T))
439 return false;
440 return true;
441}
442
449template<typename T>
450inline T& (max)(T& o1, T& o2) {
451 return o1 > o2 ? o1 : o2;
452}
453
460template<typename T>
461inline T& (min)(T& o1, T& o2) {
462 return o1 < o2 ? o1 : o2;
463}
464
472template<typename T>
473inline T& (limit)(T& value, T& low, T& high) {
474 return (value < low) ? low : ((value > high) ? high : value);
475}
476
483template<typename T>
484inline T& deref_pointer(T *pointer) {
485 __THROW_DEREF(pointer);
486 return *pointer;
487}
488
489} // namespace ucommon
490
491#endif
Runtime functions.
void cpr_memswap(void *mem1, void *mem2, size_t size)
Portable swap code.
Common namespace for all ucommon objects.
Definition: access.h:47
T &() min(T &o1, T &o2)
Convenience function to return min of two objects.
Definition: generics.h:461
void store_unsafe(T &target, const T *source)
Convenience function to store object pointer into object.
Definition: generics.h:382
T * dup(const T &object)
Convenience function to duplicate object pointer to heap.
Definition: generics.h:329
bool isnullp(T *object)
Convenience function to test pointer-pointer object.
Definition: generics.h:319
bool bound(const T *pointer, const T *base, size_t count)
Convenience function to check memory arrays.
Definition: generics.h:435
T &() max(T &o1, T &o2)
Convenience function to return max of two objects.
Definition: generics.h:450
void reset_unsafe(T &object)
Convenience function to reset an existing object.
Definition: generics.h:353
T & deref_pointer(T *pointer)
Convert a pointer to a reference with type checking.
Definition: generics.h:484
void swap(T &o1, T &o2)
Convenience function to swap objects.
Definition: generics.h:392
T & move(T &src, T &to)
Convenience function to move objects.
Definition: generics.h:414
void zero_unsafe(T &object)
Convenience function to zero an object and restore type info.
Definition: generics.h:362
T copy(const T &src)
Convenience function to copy objects.
Definition: generics.h:400
T &() limit(T &value, T &low, T &high)
Convenience macro to range restrict values.
Definition: generics.h:473
bool isnull(T &object)
Convenience function to test pointer object.
Definition: generics.h:308
void copy_unsafe(T *target, const T *source)
Convenience function to copy class.
Definition: generics.h:372
bool is(T &object)
Convenience function to validate object assuming it is castable to bool.
Definition: generics.h:297
Automatic integer counting class.
Definition: counter.h:44
Generic smart pointer class.
Definition: generics.h:60
Generic smart array class.
Definition: generics.h:162
Save and restore global objects in function call stack frames.
Definition: generics.h:267
~save_restore()
Restore original when stack frame is released.
Definition: generics.h:286
save_restore(T &object)
Save object into local copy and keep reference to the original object.
Definition: generics.h:279