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