chenqiyang
2021-08-20 7b95fb4d4549d3452ee17165236186afc1f2b393
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
/*
 * Copyright (c) 2010-2019 Belledonne Communications SARL.
 *
 * This file is part of Liblinphone.
 *
 * 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 3 of the License, or
 * (at your option) any later version.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
 
#ifndef _L_GENERAL_H_
#define _L_GENERAL_H_
 
#ifdef __cplusplus
    #include <memory>
    #include <type_traits>
#endif
 
// =============================================================================
 
// -----------------------------------------------------------------------------
// Namespace.
// -----------------------------------------------------------------------------
 
#ifdef __cplusplus
    #define LINPHONE_BEGIN_NAMESPACE namespace LinphonePrivate {
    #define LINPHONE_END_NAMESPACE }
#else
    #define LINPHONE_BEGIN_NAMESPACE
    #define LINPHONE_END_NAMESPACE
#endif
 
// -----------------------------------------------------------------------------
 
LINPHONE_BEGIN_NAMESPACE
 
// -----------------------------------------------------------------------------
// Export.
// -----------------------------------------------------------------------------
 
#ifndef LINPHONE_PUBLIC
    #if defined(_MSC_VER)
        #ifdef LINPHONE_STATIC
            #define LINPHONE_PUBLIC
        #else
            #ifdef LINPHONE_EXPORTS
                #define LINPHONE_PUBLIC __declspec(dllexport)
            #else
                #define LINPHONE_PUBLIC __declspec(dllimport)
            #endif
        #endif
    #else
        #define LINPHONE_PUBLIC
    #endif
#endif
 
#ifndef LINPHONE_DEPRECATED
    #if defined(_MSC_VER)
        #define LINPHONE_DEPRECATED __declspec(deprecated)
    #else
        #define LINPHONE_DEPRECATED __attribute__((deprecated))
    #endif
#endif
 
// -----------------------------------------------------------------------------
 
#ifdef __cplusplus
 
// -----------------------------------------------------------------------------
// Debug.
// -----------------------------------------------------------------------------
 
void lAssert (const char *condition, const char *file, int line);
 
#ifdef DEBUG
    #define L_ASSERT(CONDITION) ((CONDITION) ? static_cast<void>(0) : LinphonePrivate::lAssert(#CONDITION, __FILE__, __LINE__))
#else
    #define L_ASSERT(CONDITION) static_cast<void>(false && (CONDITION))
#endif
 
// -----------------------------------------------------------------------------
// Optimization.
// -----------------------------------------------------------------------------
 
#ifndef _MSC_VER
    #define L_LIKELY(EXPRESSION) __builtin_expect(static_cast<bool>(EXPRESSION), true)
    #define L_UNLIKELY(EXPRESSION)  __builtin_expect(static_cast<bool>(EXPRESSION), false)
#else
    #define L_LIKELY(EXPRESSION) EXPRESSION
    #define L_UNLIKELY(EXPRESSION) EXPRESSION
#endif
 
// -----------------------------------------------------------------------------
// Misc.
// -----------------------------------------------------------------------------
 
// Define an integer version like: 0xXXYYZZ, XX=MAJOR, YY=MINOR, and ZZ=PATCH.
constexpr unsigned int makeVersion (unsigned int major, unsigned int minor, unsigned int patch) {
    return ((major << 16) | (minor << 8) | patch);
}
 
// Not available in C++11...
template<typename T, typename... Args>
std::unique_ptr<T> makeUnique(Args && ...args) {
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
 
#define L_AUTO_RETURN(VALUE) -> decltype(VALUE) { return VALUE; }
 
// -----------------------------------------------------------------------------
// Class tools.
// -----------------------------------------------------------------------------
 
#define L_DISABLE_COPY(CLASS) \
    CLASS (const CLASS &) = delete; \
    CLASS &operator= (const CLASS &) = delete;
 
// -----------------------------------------------------------------------------
// PImpl tools.
// -----------------------------------------------------------------------------
 
class BaseObject;
class BaseObjectPrivate;
class ClonableObject;
class ClonableObjectPrivate;
class Object;
class ObjectPrivate;
 
namespace Private {
    template<typename T>
    using BetterPrivateAncestor = typename std::conditional<
        std::is_base_of<BaseObject, T>::value,
        BaseObject,
        typename std::conditional<
            std::is_base_of<ClonableObject, T>::value,
            ClonableObject,
            T
        >::type
    >::type;
 
    // Generic public helper.
    template<
        typename R,
        typename P,
        typename C
    >
    constexpr R *getPublicHelper (P *object, const C *) {
        return static_cast<R *>(object);
    }
 
    // Generic public helper. Deal with shared data.
    template<
        typename R,
        typename P,
        typename C
    >
    inline R *getPublicHelper (const P &objectSet, const C *) {
        auto it = objectSet.cbegin();
        L_ASSERT(it != objectSet.cend());
        return static_cast<R *>(*it);
    }
 
    template<typename T, typename U>
    struct AddConstMirror {
        typedef U type;
    };
 
    template<typename T, typename U>
    struct AddConstMirror<const T, U> {
        typedef typename std::add_const<U>::type type;
    };
}
 
#define L_INTERNAL_CHECK_OBJECT_INHERITANCE(CLASS) \
    static_assert( \
        !(std::is_base_of<BaseObject, CLASS>::value && std::is_base_of<ClonableObject, CLASS>::value), \
        "Multiple inheritance between BaseObject and ClonableObject is not allowed." \
    );
 
#define L_INTERNAL_DECLARE_PRIVATE(CLASS) \
    inline CLASS ## Private *getPrivate () { \
        L_INTERNAL_CHECK_OBJECT_INHERITANCE(CLASS); \
        using TypeAncestor = LinphonePrivate::Private::BetterPrivateAncestor<CLASS>; \
        return reinterpret_cast<CLASS ## Private *>(TypeAncestor::mPrivate); \
    } \
    inline const CLASS ## Private *getPrivate () const { \
        L_INTERNAL_CHECK_OBJECT_INHERITANCE(CLASS); \
        using TypeAncestor = LinphonePrivate::Private::BetterPrivateAncestor<CLASS>; \
        return reinterpret_cast<const CLASS ## Private *>(TypeAncestor::mPrivate); \
    } \
    friend class CLASS ## Private; \
    friend class Wrapper;
 
// Allows access to private internal data.
// Gives a control to C Wrapper.
#ifndef LINPHONE_TESTER
    #define L_DECLARE_PRIVATE(CLASS) L_INTERNAL_DECLARE_PRIVATE(CLASS)
#else
    #define L_DECLARE_PRIVATE(CLASS) \
        L_INTERNAL_DECLARE_PRIVATE(CLASS) \
        friend class Tester;
#endif
 
#define L_DECLARE_PUBLIC(CLASS) \
    CLASS *getPublic () { \
        return LinphonePrivate::Private::getPublicHelper<CLASS>(mPublic, this); \
    } \
    const CLASS *getPublic () const { \
        return LinphonePrivate::Private::getPublicHelper<const CLASS>(mPublic, this); \
    } \
    friend class CLASS;
 
// Get Private data.
#define L_D() decltype(getPrivate()) const d = getPrivate();
 
// Get Public data.
#define L_Q() decltype(getPublic()) const q = getPublic();
 
// Get Private data of class in a multiple inheritance case.
#define L_D_T(CLASS, NAME) \
    auto const NAME = static_cast< \
        LinphonePrivate::Private::AddConstMirror< \
            std::remove_reference<decltype(*this)>::type, \
            CLASS ## Private \
        >::type * \
    >(CLASS::mPrivate);
 
// Get Public data of class in a multiple inheritance case.
#define L_Q_T(CLASS, NAME) \
    auto const NAME = static_cast< \
        LinphonePrivate::Private::AddConstMirror< \
            std::remove_reference<decltype(*this)>::type, \
            CLASS \
        >::type * \
    >(getPublic());
// -----------------------------------------------------------------------------
// Macro.
// -----------------------------------------------------------------------------
 
#define EPHEMERAL_MESSAGE_TASKS_MAX_NB 10
 
// -----------------------------------------------------------------------------
// Overload.
// -----------------------------------------------------------------------------
 
#define L_OVERRIDE_SHARED_FROM_THIS(CLASS) \
    inline std::shared_ptr<CLASS> getSharedFromThis () { \
        return std::static_pointer_cast<CLASS>(Object::getSharedFromThis()); \
    } \
    inline std::shared_ptr<const CLASS> getSharedFromThis () const { \
        return std::static_pointer_cast<const CLASS>(Object::getSharedFromThis()); \
    }
 
namespace Private {
    template<typename... Args>
    struct ResolveMemberFunctionOverload {
        template<typename Ret, typename Obj>
        constexpr auto operator() (Ret (Obj::*func)(Args...)) const L_AUTO_RETURN(func);
    };
 
    template<typename... Args>
    struct ResolveConstMemberFunctionOverload {
        template<typename Ret, typename Obj>
        constexpr auto operator() (Ret (Obj::*func)(Args...) const) const L_AUTO_RETURN(func);
    };
 
    template<typename... Args>
    struct ResolveOverload : ResolveMemberFunctionOverload<Args...>, ResolveConstMemberFunctionOverload<Args...> {
        using ResolveMemberFunctionOverload<Args...>::operator();
        using ResolveConstMemberFunctionOverload<Args...>::operator();
 
        template<typename Ret>
        constexpr auto operator() (Ret (*func)(Args...)) const L_AUTO_RETURN(func);
    };
}
 
// Useful to select a specific overloaded function. (Avoid usage of static_cast.)
template<typename... Args>
using resolveOverload = Private::ResolveOverload<Args...>;
 
// -----------------------------------------------------------------------------
// Math.
// -----------------------------------------------------------------------------
 
// Get the length of one integer.
constexpr int getIntLength (int n) {
    return n < 0 ? 1 + getIntLength(-n) : (n < 10 ? 1 : 1 + getIntLength(n / 10));
}
 
namespace Private {
    constexpr int pow10Impl (int n, int acc) {
        return n == 0 ? acc : pow10Impl(n - 1, acc * 10);
    }
}
 
template<typename T>
constexpr T abs (const T &value) {
    return value < 0 ? -value : value;
}
 
constexpr int pow10 (int n) {
    return (n < 0 ? -1 : +1) * Private::pow10Impl(abs(n), 1);
}
 
// Returns the sum of n elements.
constexpr int sums () {
    return 0;
}
 
template<typename T, typename... Args>
constexpr int sums (T i, Args... args) {
    return i + sums(args...);
}
 
// -----------------------------------------------------------------------------
// Wrapper public.
// -----------------------------------------------------------------------------
 
#define L_DECL_C_STRUCT(STRUCT) typedef struct _ ## STRUCT STRUCT;
#define L_DECL_C_STRUCT_PREFIX_LESS(STRUCT) typedef struct STRUCT STRUCT;
 
#endif // ifdef __cplusplus
 
LINPHONE_END_NAMESPACE
 
#endif // ifndef _L_GENERAL_H_