/
object.h
138 lines (124 loc) · 4.73 KB
/
object.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
* Copyright (C) 2008-2014 Tobias Brunner
* Copyright (C) 2008 Martin Willi
*
* Copyright (C) secunet Security Networks AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup object_i object
* @{ @ingroup utils_i
*/
#ifndef OBJECT_H_
#define OBJECT_H_
/**
* Call destructor of an object, if object != NULL
*/
#define DESTROY_IF(obj) if (obj) (obj)->destroy(obj)
/**
* Call offset destructor of an object, if object != NULL
*/
#define DESTROY_OFFSET_IF(obj, offset) if (obj) obj->destroy_offset(obj, offset)
/**
* Call function destructor of an object, if object != NULL
*/
#define DESTROY_FUNCTION_IF(obj, fn) if (obj) obj->destroy_function(obj, fn)
/**
* Object allocation/initialization macro, using designated initializer.
*/
#define INIT(this, ...) ({ (this) = malloc(sizeof(*(this))); \
*(this) = (typeof(*(this))){ __VA_ARGS__ }; (this); })
/**
* Aligning version of INIT().
*
* The returned pointer must be freed using free_align(), not free().
*
* @param this object to allocate/initialize
* @param align alignment for allocation, in bytes
* @param ... initializer
*/
#define INIT_ALIGN(this, align, ...) { \
(this) = malloc_align(sizeof(*(this)), align); \
*(this) = (typeof(*(this))){ __VA_ARGS__ }; }
/**
* Object allocation/initialization macro, with extra allocated bytes at tail.
*
* The extra space gets zero-initialized.
*
* @param this pointer to object to allocate memory for
* @param extra number of bytes to allocate at end of this
* @param ... initializer
*/
#define INIT_EXTRA(this, extra, ...) { \
typeof(extra) _extra = (extra); \
(this) = malloc(sizeof(*(this)) + _extra); \
*(this) = (typeof(*(this))){ __VA_ARGS__ }; \
memset((this) + 1, 0, _extra); }
/**
* Aligning version of INIT_EXTRA().
*
* The returned pointer must be freed using free_align(), not free().
*
* @param this object to allocate/initialize
* @param extra number of bytes to allocate at end of this
* @param align alignment for allocation, in bytes
* @param ... initializer
*/
#define INIT_EXTRA_ALIGN(this, extra, align, ...) { \
typeof(extra) _extra = (extra); \
(this) = malloc_align(sizeof(*(this)) + _extra, align); \
*(this) = (typeof(*(this))){ __VA_ARGS__ }; \
memset((this) + 1, 0, _extra); }
/**
* Method declaration/definition macro, providing private and public interface.
*
* Defines a method name with this as first parameter and a return value ret,
* and an alias for this method with a _ prefix, having the this argument
* safely casted to the public interface iface.
* _name is provided a function pointer, but will get optimized out by GCC.
*/
#define METHOD(iface, name, ret, this, ...) \
static ret name(union {iface *_public; this;} \
__attribute__((transparent_union)), ##__VA_ARGS__); \
static typeof(name) *_##name = (typeof(name)*)name; \
static ret name(this, ##__VA_ARGS__)
/**
* Same as METHOD(), but is defined for two public interfaces.
*/
#define METHOD2(iface1, iface2, name, ret, this, ...) \
static ret name(union {iface1 *_public1; iface2 *_public2; this;} \
__attribute__((transparent_union)), ##__VA_ARGS__); \
static typeof(name) *_##name = (typeof(name)*)name; \
static ret name(this, ##__VA_ARGS__)
/**
* Callback declaration/definition macro, allowing casted first parameter.
*
* This is very similar to METHOD, but instead of casting the first parameter
* to a public interface, it uses a void*. This allows type safe definition
* of a callback function, while using the real type for the first parameter.
*/
#define CALLBACK(name, ret, param1, ...) \
static ret _cb_##name(union {void *_generic; param1;} \
__attribute__((transparent_union)), ##__VA_ARGS__); \
static ret (*name)(void*, ##__VA_ARGS__) = _cb_##name; \
static ret _cb_##name(param1, ##__VA_ARGS__)
/**
* Same as CALLBACK(), but for two void* arguments (e.g. for comparisons).
*/
#define CALLBACK2(name, ret, param1, param2, ...) \
static ret _cb_##name(union {void *_generic; param1;} \
__attribute__((transparent_union)), \
union {void *_generic; param2;} \
__attribute__((transparent_union)), ##__VA_ARGS__); \
static ret (*name)(void*, void*, ##__VA_ARGS__) = _cb_##name; \
static ret _cb_##name(param1, param2, ##__VA_ARGS__)
#endif /** OBJECT_H_ @} */