1 /*
2 * The Doomsday Engine Project -- libcore
3 *
4 * Copyright © 2011-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
5 *
6 * @par License
7 * LGPL: http://www.gnu.org/licenses/lgpl.html
8 *
9 * <small>This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or (at your
12 * option) any later version. This program is distributed in the hope that it
13 * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
15 * General Public License for more details. You should have received a copy of
16 * the GNU Lesser General Public License along with this program; if not, see:
17 * http://www.gnu.org/licenses</small>
18 */
19
20 #ifndef LIBCORE_H
21 #define LIBCORE_H
22
23 /**
24 * @file libcore.h Common definitions for Doomsday 2.
25 */
26
27 /**
28 * @defgroup core Core
29 *
30 * @defgroup data Data Types and Structures
31 * Classes related to accessing, storing, and processing of data. @ingroup core
32 *
33 * @defgroup net Network
34 * Classes responsible for network communications. @ingroup core
35 *
36 * @defgroup math Math Utilities
37 * @ingroup core
38 *
39 * @defgroup types Basic Types
40 * Basic data types. @ingroup core
41 */
42
43 /**
44 * @mainpage Doomsday 2 SDK
45 *
46 * <p>This documentation covers all the functions and data that Doomsday 2 makes
47 * available for games and other plugins.</p>
48 *
49 * @section Overview
50 *
51 * <p>The SDK is composed of a set of shared libraries. The Core library is the
52 * only required one as it provides the foundation classes. GUI-dependent
53 * functionality (libgui and libappfw) are kept separate so that server-only
54 * builds can use the non-GUI ones.</p>
55 *
56 * <p>The documentation has been organized into <a href="modules.html">modules</a>.
57 * The primary ones are listed below:</p>
58 *
59 * - @ref core
60 * - @ref data
61 * - @ref script
62 * - @ref fs
63 * - @ref net
64 * - @ref appfw
65 */
66
67 #ifdef __cplusplus
68 # define DENG2_EXTERN_C extern "C"
69 #else
70 # define DENG2_EXTERN_C extern
71 #endif
72
73 #if defined(__cplusplus) && !defined(DENG2_C_API_ONLY)
74 # define DENG2_USE_QT
75 # include <cstddef> // size_t
76 # include <cstring> // memset
77 # include <functional>
78 # include <memory> // unique_ptr, shared_ptr
79 # include <typeinfo>
80 # include <stdexcept>
81 # include <string>
82 #endif
83
84 #if defined(__x86_64__) || defined(__x86_64) || defined(_LP64) || defined(DENG_64BIT_HOST)
85 # define DENG2_64BIT
86 #endif
87
88 #ifdef DENG2_USE_QT
89 # include <QtCore/qglobal.h>
90 # include <QScopedPointer>
91 # include <QDebug>
92 # include <QString>
93
94 // Qt versioning helper. Qt 4.8 is the oldest we support.
95 # if (QT_VERSION < QT_VERSION_CHECK(4, 8, 0))
96 # error "Unsupported version of Qt"
97 # endif
98 # define DENG2_QT_4_6_OR_NEWER
99 # define DENG2_QT_4_7_OR_NEWER
100 # define DENG2_QT_4_8_OR_NEWER
101 # if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
102 # define DENG2_QT_5_0_OR_NEWER
103 # endif
104 # if (QT_VERSION >= QT_VERSION_CHECK(5, 1, 0))
105 # define DENG2_QT_5_1_OR_NEWER
106 # endif
107 # if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
108 # define DENG2_QT_5_2_OR_NEWER
109 # endif
110 # if (QT_VERSION >= QT_VERSION_CHECK(5, 3, 0))
111 # define DENG2_QT_5_3_OR_NEWER
112 # endif
113 # if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0))
114 # define DENG2_QT_5_4_OR_NEWER
115 # endif
116 # if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
117 # define DENG2_QT_5_5_OR_NEWER
118 # endif
119 # if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
120 # define DENG2_QT_5_6_OR_NEWER
121 # endif
122 # if (QT_VERSION >= QT_VERSION_CHECK(5, 7, 0))
123 # define DENG2_QT_5_7_OR_NEWER
124 # endif
125 #endif
126
127 #ifndef _MSC_VER
128 # include <stdint.h> // Not MSVC so use C99 standard header
129 #endif
130
131 #include <assert.h>
132
133 /*
134 * When using the C API, the Qt string functions are not available, so we
135 * must use the platform-specific functions.
136 */
137 #if defined(UNIX) && defined(DENG2_C_API_ONLY)
138 # include <strings.h> // strcasecmp etc.
139 #endif
140
141 /**
142 * @def DENG2_PUBLIC
143 *
144 * Used for declaring exported symbols. It must be applied in all exported
145 * classes and functions. DEF files are not used for exporting symbols out
146 * of libcore.
147 */
148 #if defined(_WIN32) && defined(_MSC_VER)
149 # ifdef __DENG2__
150 // This is defined when compiling the library.
151 # define DENG2_PUBLIC __declspec(dllexport)
152 # else
153 # define DENG2_PUBLIC __declspec(dllimport)
154 # endif
155 # define DENG2_NORETURN __declspec(noreturn)
156 #else
157 // No need to use any special declarators.
158 # define DENG2_PUBLIC
159 # define DENG2_NORETURN __attribute__((__noreturn__))
160 #endif
161
162 #if defined (DENG_IOS)
163 # define DENG2_VISIBLE_SYMBOL __attribute__((visibility("default")))
164 #else
165 # define DENG2_VISIBLE_SYMBOL
166 #endif
167
168 #ifndef NDEBUG
169 # define DENG2_DEBUG
170 DENG2_EXTERN_C DENG2_PUBLIC void LogBuffer_Flush(void);
171 # ifdef DENG2_USE_QT
172 # define DENG2_ASSERT(x) {if (!(x)) {LogBuffer_Flush(); Q_ASSERT(x);}}
173 # else
174 # define DENG2_ASSERT(x) {if (!(x)) {LogBuffer_Flush(); assert(x);}}
175 # endif
176 # define DENG2_DEBUG_ONLY(x) x
177 #else
178 # define DENG2_NO_DEBUG
179 # define DENG2_ASSERT(x)
180 # define DENG2_DEBUG_ONLY(x)
181 #endif
182
183 #define DE_ASSERT(x) DENG2_ASSERT(x) // work/omega
184
185 #ifdef DENG2_USE_QT
186 # ifdef UNIX
187 # include <execinfo.h>
188 /**
189 * @macro DENG2_PRINT_BACKTRACE
190 * Debug utility for dumping the current backtrace using qDebug.
191 */
192 # define DENG2_PRINT_BACKTRACE() { \
193 void *callstack[128]; \
194 int i, frames = backtrace(callstack, 128); \
195 char** strs = backtrace_symbols(callstack, frames); \
196 for (i = 0; i < frames; ++i) qDebug("%s", strs[i]); \
197 free(strs); }
198 # define DENG2_BACKTRACE(n, out) { \
199 void *callstack[n]; \
200 int i, frames = backtrace(callstack, n); \
201 char** strs = backtrace_symbols(callstack, frames); \
202 out = ""; \
203 for (i = 0; i < frames; ++i) { out.append(strs[i]); out.append('\n'); } \
204 free(strs); }
205 # else
206 # define DENG2_PRINT_BACKTRACE()
207 # endif
208 #endif
209
210 /**
211 * Macro for determining the name of a type (using RTTI).
212 */
213 #define DENG2_TYPE_NAME(t) (typeid(t).name())
214
215 /**
216 * Macro for hiding the warning about an unused parameter.
217 */
218 #define DENG2_UNUSED(a) (void)a
219
220 /**
221 * Macro for hiding the warning about two unused parameters.
222 */
223 #define DENG2_UNUSED2(a, b) (void)a, (void)b
224
225 /**
226 * Macro for hiding the warning about three unused parameters.
227 */
228 #define DENG2_UNUSED3(a, b, c) (void)a, (void)b, (void)c
229
230 /**
231 * Macro for hiding the warning about four unused parameters.
232 */
233 #define DENG2_UNUSED4(a, b, c, d) (void)a, (void)b, (void)c, (void)d
234
235 #define DENG2_PLURAL_S(Count) ((Count) != 1? "s" : "")
236
237 #define DENG2_BOOL_YESNO(Yes) ((Yes)? "yes" : "no" )
238
239 /**
240 * Forms an escape sequence string literal. Escape sequences begin
241 * with an ASCII Escape character.
242 */
243 #define DENG2_ESC(StringLiteral) "\x1b" StringLiteral
244 #define _E(Code) DENG2_ESC(#Code)
245
246 #define DENG2_OFFSET_PTR(type, member) \
247 reinterpret_cast<const void *>(offsetof(type, member))
248
249 /**
250 * Macro for defining an opaque type in the C wrapper API.
251 */
252 #define DENG2_OPAQUE(Name) \
253 struct Name ## _s; \
254 typedef struct Name ## _s Name;
255
256 /**
257 * Macro for converting an opaque wrapper type to a de::type.
258 * Asserts that the object really exists (not null).
259 */
260 #define DENG2_SELF(Type, Var) \
261 DENG2_ASSERT(Var != 0); \
262 de::Type *self = reinterpret_cast<de::Type *>(Var);
263
264 /**
265 * Macro for iterating through an STL container. Note that @a ContainerRef should be a
266 * variable and not a temporary value returned from some function call -- otherwise the
267 * begin() and end() calls may not refer to the same container's beginning and end.
268 *
269 * @param IterClass Class being iterated.
270 * @param Iter Name/declaration of the iterator variable.
271 * @param ContainerRef Container.
272 */
273 #define DENG2_FOR_EACH(IterClass, Iter, ContainerRef) \
274 for (IterClass::iterator Iter = (ContainerRef).begin(); Iter != (ContainerRef).end(); ++Iter)
275
276 /// @copydoc DENG2_FOR_EACH
277 #define DENG2_FOR_EACH_CONST(IterClass, Iter, ContainerRef) \
278 for (IterClass::const_iterator Iter = (ContainerRef).begin(); Iter != (ContainerRef).end(); ++Iter)
279
280 /**
281 * Macro for iterating through an STL container in reverse. Note that @a ContainerRef
282 * should be a variable and not a temporary value returned from some function call --
283 * otherwise the begin() and end() calls may not refer to the same container's beginning
284 * and end.
285 *
286 * @param IterClass Class being iterated.
287 * @param Var Name/declaration of the iterator variable.
288 * @param ContainerRef Container.
289 */
290 #define DENG2_FOR_EACH_REVERSE(IterClass, Var, ContainerRef) \
291 for (IterClass::reverse_iterator Var = (ContainerRef).rbegin(); Var != (ContainerRef).rend(); ++Var)
292
293 /// @copydoc DENG2_FOR_EACH_REVERSE
294 #define DENG2_FOR_EACH_CONST_REVERSE(IterClass, Var, ContainerRef) \
295 for (IterClass::const_reverse_iterator Var = (ContainerRef).rbegin(); Var != (ContainerRef).rend(); ++Var)
296
297 #define DENG2_NO_ASSIGN(ClassName) \
298 ClassName &operator = (ClassName const &) = delete;
299
300 #define DENG2_NO_COPY(ClassName) \
301 ClassName(ClassName const &) = delete;
302
303 /**
304 * Macro for declaring methods for convenient casting:
305 *
306 * - `is` checks if the object can be casted.
307 * - `as` performs the cast as efficiently as possible (just a `static_cast`).
308 * Use this when the cast is always known to be legal.
309 * - `maybeAs` does a `dynamic_cast` (which has slower performance). Failure
310 * to cast simply results in nullptr.
311 * - `expectedAs` does a `dynamic_cast` and throws an exception if the cast fails.
312 * Slowest performance, but is the safest.
313 */
314 #define DENG2_CAST_METHODS() \
315 template <typename T_> \
316 T_ &as() { \
317 DENG2_ASSERT(de::is<T_>(this)); \
318 return *static_cast<T_ *>(this); \
319 } \
320 template <typename T_> \
321 T_ *asPtr() { \
322 DENG2_ASSERT(de::is<T_>(this)); \
323 return static_cast<T_ *>(this); \
324 } \
325 template <typename T_> \
326 T_ const &as() const { \
327 DENG2_ASSERT(de::is<T_>(this)); \
328 return *static_cast<T_ const *>(this); \
329 } \
330 template <typename T_> \
331 T_ const *asPtr() const { \
332 DENG2_ASSERT(de::is<T_>(this)); \
333 return static_cast<T_ const *>(this); \
334 }
335
336 /**
337 * Macro for starting the definition of a private implementation struct. The
338 * struct holds a reference to the public instance, which must be specified in
339 * the call to the base class constructor. @see de::Private
340 *
341 * Example:
342 * <pre>
343 * DENG2_PIMPL(MyClass)
344 * {
345 * Impl(Public &inst) : Base(inst) {
346 * // constructor
347 * }
348 * // private data and methods
349 * };
350 * </pre>
351 */
352 #define DENG2_PIMPL(ClassName) \
353 struct ClassName::Impl : public de::Private<ClassName>
354
355 /**
356 * Macro for starting the definition of a private implementation struct without
357 * a reference to the public instance. This is useful for simpler classes where
358 * the private implementation mostly holds member variables.
359 */
360 #define DENG2_PIMPL_NOREF(ClassName) \
361 struct ClassName::Impl : public de::IPrivate
362
363 /**
364 * Macro for publicly declaring a pointer to the private implementation.
365 * de::PrivateAutoPtr owns the private instance and will automatically delete
366 * it when the PrivateAutoPtr is destroyed.
367 */
368 #define DENG2_PRIVATE(Var) \
369 struct Impl; \
370 de::PrivateAutoPtr<Impl> Var;
371
372 #if defined(__cplusplus) && !defined(DENG2_C_API_ONLY)
373 namespace de {
374
375 /**
376 * @defgroup errors Exceptions
377 *
378 * These are exceptions thrown by libcore when a fatal error occurs.
379 */
380
381 /**
382 * Base class for error exceptions thrown by libcore. @ingroup errors
383 */
384 class DENG2_PUBLIC Error : public std::runtime_error
385 {
386 public:
387 Error(QString const &where, QString const &message);
388
389 QString name() const;
390 virtual QString asText() const;
391
392 protected:
393 void setName(QString const &name);
394
395 private:
396 std::string _name;
397 };
398
399 /**
400 * Macro for defining an exception class that belongs to a parent group of
401 * exceptions. This should be used so that whoever uses the class
402 * that throws an exception is able to choose the level of generality
403 * of the caught errors.
404 */
405 #define DENG2_SUB_ERROR(Parent, Name) \
406 class Name : public Parent { \
407 public: \
408 Name(QString const &message) \
409 : Parent("-", message) { Parent::setName(#Name); } \
410 Name(QString const &where, QString const &message) \
411 : Parent(where, message) { Parent::setName(#Name); } \
412 virtual void raise() const { throw *this; } \
413 } /**< @note One must put a semicolon after the macro invocation. */
414
415 /**
416 * Define a top-level exception class.
417 * @note One must put a semicolon after the macro invocation.
418 */
419 #define DENG2_ERROR(Name) DENG2_SUB_ERROR(de::Error, Name)
420
421 /// Thrown from the expectedAs() method if a cast cannot be made as expected.
422 DENG2_ERROR(CastError);
423
424 /*
425 * Convenience wrappers for dynamic_cast.
426 */
427
428 template <typename X_, typename T_>
is(T_ * ptr)429 inline bool is(T_ *ptr) {
430 return dynamic_cast<X_ *>(ptr) != nullptr;
431 }
432
433 template <typename X_, typename T_>
is(T_ const * ptr)434 inline bool is(T_ const *ptr) {
435 return dynamic_cast<X_ const *>(ptr) != nullptr;
436 }
437
438 template <typename X_, typename T_>
is(T_ & obj)439 inline bool is(T_ &obj) {
440 return dynamic_cast<X_ *>(&obj) != nullptr;
441 }
442
443 template <typename X_, typename T_>
is(T_ const & obj)444 inline bool is(T_ const &obj) {
445 return dynamic_cast<X_ const *>(&obj) != nullptr;
446 }
447
448 template <typename X_, typename T_>
maybeAs(T_ * ptr)449 inline X_ *maybeAs(T_ *ptr) {
450 return dynamic_cast<X_ *>(ptr);
451 }
452
453 template <typename X_, typename T_>
maybeAs(T_ const * ptr)454 inline X_ const *maybeAs(T_ const *ptr) {
455 return dynamic_cast<X_ const *>(ptr);
456 }
457
458 template <typename X_, typename T_>
maybeAs(T_ & obj)459 inline X_ *maybeAs(T_ &obj) {
460 return dynamic_cast<X_ *>(&obj);
461 }
462
463 template <typename X_, typename T_>
maybeAs(T_ const & obj)464 inline X_ const *maybeAs(T_ const &obj) {
465 return dynamic_cast<X_ const *>(&obj);
466 }
467
468 template <typename X_, typename T_>
expectedAs(T_ * ptr)469 inline X_ &expectedAs(T_ *ptr) {
470 if (auto *t = maybeAs<X_>(ptr)) return *t;
471 DENG2_ASSERT(false);
472 throw CastError(QString("Cannot cast %1 to %2").arg(DENG2_TYPE_NAME(T_)).arg(DENG2_TYPE_NAME(X_)));
473 }
474
475 template <typename X_, typename T_>
expectedAs(T_ const * ptr)476 inline X_ const &expectedAs(T_ const *ptr) {
477 if (auto const *t = maybeAs<X_>(ptr)) return *t;
478 DENG2_ASSERT(false);
479 throw CastError(QString("Cannot cast %1 to %2").arg(DENG2_TYPE_NAME(T_)).arg(DENG2_TYPE_NAME(X_)));
480 }
481
482 /**
483 * Interface for all private instance implementation structs.
484 * In a debug build, also contains a verification code that can be used
485 * to assert whether the pointed object really is derived from IPrivate.
486 */
487 struct IPrivate {
~IPrivateIPrivate488 virtual ~IPrivate() {}
489 #ifdef DENG2_DEBUG
490 # define DENG2_IPRIVATE_VERIFICATION 0xdeadbeef
491 unsigned int _privateImplVerification = DENG2_IPRIVATE_VERIFICATION;
privateImplVerificationIPrivate492 unsigned int privateImplVerification() const { return _privateImplVerification; }
493 #endif
494 };
495
496 /**
497 * Pointer to the private implementation. Behaves like std::unique_ptr, but with
498 * the additional requirement that the pointed/owned instance must be derived
499 * from de::IPrivate.
500 */
501 template <typename ImplType>
502 class PrivateAutoPtr
503 {
504 DENG2_NO_COPY (PrivateAutoPtr)
DENG2_NO_ASSIGN(PrivateAutoPtr)505 DENG2_NO_ASSIGN(PrivateAutoPtr)
506
507 public:
508 PrivateAutoPtr(ImplType *p) : ptr(p) {}
PrivateAutoPtr(PrivateAutoPtr && moved)509 PrivateAutoPtr(PrivateAutoPtr &&moved) : ptr(moved.ptr) {
510 moved.ptr = nullptr;
511 }
~PrivateAutoPtr()512 ~PrivateAutoPtr() { reset(); }
513
514 PrivateAutoPtr &operator = (PrivateAutoPtr &&moved) {
515 reset();
516 ptr = moved.ptr;
517 moved.ptr = nullptr;
518 return *this;
519 }
520 inline ImplType &operator * () const { return *ptr; }
521 inline ImplType *operator -> () const { return ptr; }
522 void reset(ImplType *p = 0) {
523 IPrivate *ip = reinterpret_cast<IPrivate *>(ptr);
524 if (ip)
525 {
526 DENG2_ASSERT(ip->privateImplVerification() == DENG2_IPRIVATE_VERIFICATION);
527 delete ip;
528 }
529 ptr = p;
530 }
get()531 inline ImplType *get() const {
532 return ptr;
533 }
getConst()534 inline ImplType const *getConst() const {
535 return ptr;
536 }
537 inline operator ImplType *() const {
538 return ptr;
539 }
release()540 ImplType *release() {
541 ImplType *p = ptr;
542 ptr = 0;
543 return p;
544 }
swap(PrivateAutoPtr & other)545 void swap(PrivateAutoPtr &other) {
546 std::swap(ptr, other.ptr);
547 }
isNull()548 inline bool isNull() const {
549 return !ptr;
550 }
551 #ifdef DENG2_DEBUG
isValid()552 bool isValid() const {
553 return ptr && reinterpret_cast<IPrivate *>(ptr)->privateImplVerification() == DENG2_IPRIVATE_VERIFICATION;
554 }
555 #endif
556
557 private:
558 ImplType *ptr;
559 };
560
561 /**
562 * Utility template for defining private implementation data (pimpl idiom). Use
563 * this in source files, not in headers.
564 */
565 template <typename PublicType>
566 struct Private : public IPrivate {
567 using Public = PublicType;
568 typedef Private<PublicType> Base;
569
570 Public *thisPublic;
selfPrivate571 inline Public &self() const { return *thisPublic; }
572
PrivatePrivate573 Private(PublicType &i) : thisPublic(&i) {}
PrivatePrivate574 Private(PublicType *i) : thisPublic(i) {}
575 };
576
577 template <typename ToType, typename FromType>
function_cast(FromType ptr)578 inline ToType function_cast(FromType ptr)
579 {
580 /**
581 * @note Casting to a pointer-to-function type: see
582 * http://www.trilithium.com/johan/2004/12/problem-with-dlsym/
583 */
584 // This is not 100% portable to all possible memory architectures; thus:
585 DENG2_ASSERT(sizeof(void *) == sizeof(ToType));
586
587 union { FromType original; ToType target; } forcedCast;
588 forcedCast.original = ptr;
589 return forcedCast.target;
590 }
591
592 template <typename ToType, typename FromType>
functionAssign(ToType & dest,FromType src)593 inline ToType functionAssign(ToType &dest, FromType src)
594 {
595 return dest = de::function_cast<ToType>(src);
596 }
597
598 /**
599 * Clears a region of memory. Size of the region is the size of Type.
600 * @param t Reference to the memory.
601 */
602 template <typename Type>
zap(Type & t)603 inline void zap(Type &t) {
604 std::memset(&t, 0, sizeof(Type));
605 }
606
607 /**
608 * Clears a region of memory. Size of the region is the size of Type.
609 * @param t Pointer to the start of the region of memory.
610 *
611 * @note An overloaded zap(Type *) would not work as the size of array
612 * types could not be correctly determined at compile time; thus this
613 * function is not an overload.
614 */
615 template <typename Type>
zapPtr(Type * t)616 inline void zapPtr(Type *t) {
617 std::memset(t, 0, sizeof(Type));
618 }
619
620 template <typename ContainerType>
mapInPlace(ContainerType & c,std::function<typename ContainerType::value_type (typename ContainerType::value_type const &)> func)621 inline ContainerType mapInPlace(ContainerType &c,
622 std::function<typename ContainerType::value_type (
623 typename ContainerType::value_type const &)> func) {
624 for (auto i = c.begin(); i != c.end(); ++i) {
625 *i = func(*i);
626 }
627 }
628
629 template <typename ContainerType>
map(ContainerType const & c,std::function<typename ContainerType::value_type (typename ContainerType::value_type const &)> func)630 inline ContainerType map(ContainerType const &c,
631 std::function<typename ContainerType::value_type (
632 typename ContainerType::value_type const &)> func) {
633 ContainerType out;
634 for (auto i = c.begin(); i != c.end(); ++i) {
635 out.push_back(func(*i));
636 }
637 return out;
638 }
639
640 template <typename OutContainer,
641 typename InContainer,
642 typename Func,
643 typename Inserter = std::back_insert_iterator<OutContainer>>
map(const InContainer & input,Func func)644 inline OutContainer map(const InContainer &input, Func func) {
645 OutContainer out;
646 Inserter ins(out);
647 for (const auto &i : input) {
648 *ins++ = func(i);
649 }
650 return out;
651 }
652
653 template <typename ContainerType>
filter(ContainerType const & c,std::function<bool (typename ContainerType::value_type const &)> func)654 inline ContainerType filter(ContainerType const &c,
655 std::function<bool (typename ContainerType::value_type const &)> func) {
656 ContainerType out;
657 for (auto i = c.begin(); i != c.end(); ++i) {
658 if (func(*i)) out.push_back(*i);
659 }
660 return out;
661 }
662
663 } // namespace de
664 #endif // __cplusplus
665
666 #if defined(__cplusplus) && !defined(DENG2_C_API_ONLY)
667 namespace de {
668
669 /**
670 * Operation performed on a flag set (e.g., QFlags).
671 */
672 enum FlagOp {
673 UnsetFlags = 0, ///< Specified flags are unset, leaving others unmodified.
674 SetFlags = 1, ///< Specified flags are set, leaving others unmodified.
675 ReplaceFlags = 2 ///< Specified flags become the new set of flags, replacing all previous flags.
676 };
677
678 struct FlagOpArg {
679 FlagOp op;
FlagOpArgFlagOpArg680 inline FlagOpArg(FlagOp op) : op(op) {}
FlagOpArgFlagOpArg681 inline FlagOpArg(bool set) : op(set? SetFlags : UnsetFlags) {}
FlagOpFlagOpArg682 inline operator FlagOp () const { return op; }
683 };
684
685 template <typename FlagsType, typename FlagsCompatibleType>
applyFlagOperation(FlagsType & flags,FlagsCompatibleType const & newFlags,FlagOpArg operation)686 void applyFlagOperation(FlagsType &flags, FlagsCompatibleType const &newFlags, FlagOpArg operation) {
687 switch (operation.op) {
688 case SetFlags: flags |= newFlags; break;
689 case UnsetFlags: flags &= ~newFlags; break;
690 case ReplaceFlags: flags = newFlags; break;
691 }
692 }
693
694 /**
695 * Clock-wise direction identifiers.
696 */
697 enum ClockDirection {
698 Anticlockwise = 0,
699 Clockwise = 1
700 };
701
702 /**
703 * Status to return from abortable iteration loops that use callbacks per iteration.
704 *
705 * The "for" pattern:
706 * <code>
707 * LoopResult forExampleObjects(std::function<LoopResult (ExampleObject &)> func);
708 *
709 * example.forExampleObjects([] (ExampleObject &ex) {
710 * // do stuff...
711 * return LoopContinue;
712 * });
713 * </code>
714 */
715 enum GenericLoopResult {
716 LoopContinue = 0,
717 LoopAbort = 1
718 };
719
720 /// Use as return type of iteration loop callbacks (a "for*" method).
721 struct LoopResult
722 {
723 int value;
724
valueLoopResult725 LoopResult(int val = LoopContinue) : value(val) {}
726 operator bool () const { return value != LoopContinue; }
727 operator int () const { return value; }
GenericLoopResultLoopResult728 operator GenericLoopResult () const { return GenericLoopResult(value); }
729 };
730
731 /**
732 * All serialization in all contexts use a common protocol version number.
733 * Whenever anything changes in serialization, the protocol version needs to be
734 * incremented. Therefore, deserialization routines shouldn't check for
735 * specific versions, but instead always use < and >.
736 *
737 * Do not reserve version numbers in advance; any build may need to increment
738 * the version, necessitating changing the subsequent numbers.
739 */
740 enum ProtocolVersion {
741 DENG2_PROTOCOL_1_9_10 = 0,
742
743 DENG2_PROTOCOL_1_10_0 = 0,
744
745 DENG2_PROTOCOL_1_11_0_Time_high_performance = 1,
746 DENG2_PROTOCOL_1_11_0 = 1,
747
748 DENG2_PROTOCOL_1_12_0 = 1,
749
750 DENG2_PROTOCOL_1_13_0 = 1,
751
752 DENG2_PROTOCOL_1_14_0_LogEntry_metadata = 2,
753 DENG2_PROTOCOL_1_14_0 = 2,
754
755 DENG2_PROTOCOL_1_15_0_NameExpression_with_scope_identifier = 3,
756 DENG2_PROTOCOL_1_15_0 = 3,
757
758 DENG2_PROTOCOL_2_0_0 = 3,
759
760 DENG2_PROTOCOL_2_1_0 = 3,
761
762 DENG2_PROTOCOL_2_2_0_NameExpression_identifier_sequence = 4,
763 DENG2_PROTOCOL_2_2_0 = 4,
764
765 DENG2_PROTOCOL_LATEST = DENG2_PROTOCOL_2_2_0
766 };
767
768 //@{
769 /// @ingroup types
770 typedef qint8 dchar; ///< 8-bit signed integer.
771 typedef quint8 dbyte; ///< 8-bit unsigned integer.
772 typedef quint8 duchar; ///< 8-bit unsigned integer.
773 typedef dchar dint8; ///< 8-bit signed integer.
774 typedef dbyte duint8; ///< 8-bit unsigned integer.
775 typedef qint16 dint16; ///< 16-bit signed integer.
776 typedef quint16 duint16; ///< 16-bit unsigned integer.
777 typedef dint16 dshort; ///< 16-bit signed integer.
778 typedef duint16 dushort; ///< 16-bit unsigned integer.
779 typedef qint32 dint32; ///< 32-bit signed integer.
780 typedef quint32 duint32; ///< 32-bit unsigned integer.
781 typedef dint32 dint; ///< 32-bit signed integer.
782 typedef duint32 duint; ///< 32-bit unsigned integer.
783 typedef qint64 dint64; ///< 64-bit signed integer.
784 typedef quint64 duint64; ///< 64-bit unsigned integer.
785 typedef float dfloat; ///< 32-bit floating point number.
786 typedef double ddouble; ///< 64-bit floating point number.
787 typedef size_t dsize; // Likely unsigned long.
788 typedef long dlong;
789
790 // Pointer-integer conversion (used for legacy code).
791 #ifdef DENG2_64BIT
792 typedef duint64 dintptr;
793 #else
794 typedef duint32 dintptr;
795 #endif
796 //@}
797
798 } // namespace de
799
800 #include "Error"
801
802 #else // !__cplusplus
803
804 /*
805 * Data types for C APIs.
806 */
807 #if _MSC_VER < 1900
808 typedef short dint16;
809 typedef unsigned short duint16;
810 typedef int dint32;
811 typedef unsigned int duint32;
812 typedef long long dint64;
813 typedef unsigned long long duint64;
814 #else
815 #include <stdint.h>
816 typedef int16_t dint16;
817 typedef uint16_t duint16;
818 typedef int32_t dint32;
819 typedef uint32_t duint32;
820 typedef int64_t dint64;
821 typedef uint64_t duint64;
822 #endif
823 typedef unsigned char dbyte;
824 typedef unsigned int duint; // 32-bit
825 typedef float dfloat;
826 typedef double ddouble;
827 typedef size_t dsize;
828 typedef long dlong;
829
830 #endif // !__cplusplus
831
832 #endif // LIBCORE_H
833