Skip to content
Snippets Groups Projects
easylogging++.h 278 KiB
Newer Older
  • Learn to ignore specific revisions
  • Radim Vavřík's avatar
    Radim Vavřík committed
    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 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000
    //
    //  Easylogging++ v9.75
    //  Single-header only, cross-platform logging library for C++ applications
    //
    //  Copyright (c) 2014 Majid Khan
    //
    //  This library is released under the MIT Licence.
    //  http://www.easylogging.org/licence.php
    //
    //  support@easylogging.org
    //  http://easylogging.org
    //  https://github.com/easylogging/easyloggingpp
    //
    #ifndef EASYLOGGINGPP_H  // NOLINT
    #define EASYLOGGINGPP_H
    // Compilers and C++0x/C++11 Evaluation
    #if defined(__GNUC__)
    #   define _ELPP_COMPILER_GCC 1
    #   define _ELPP_GCC_VERSION (__GNUC__ * 10000 \
                                   + __GNUC_MINOR__ * 100 \
                                   + __GNUC_PATCHLEVEL__)
    #   if defined(__GXX_EXPERIMENTAL_CXX0X__)
    #      define _ELPP_CXX0X 1
    #   elif(_ELPP_GCC_VERSION >= 40801)
    #      define _ELPP_CXX11 1
    #   endif  // defined(__GXX_EXPERIMENTAL_CXX0X__)
    #endif  // defined(__GNUC__)
    // Visual C++
    #if defined(_MSC_VER)
    #   define _ELPP_COMPILER_MSVC 1
    #   define _ELPP_CRT_DBG_WARNINGS 1
    #   if (_MSC_VER == 1600)
    #      define _ELPP_CXX0X 1
    #   elif(_MSC_VER >= 1700)
    #      define _ELPP_CXX11 1
    #   endif  // (_MSC_VER == 1600)
    #endif  // defined(_MSC_VER)
    // Clang++
    #if defined(__clang__) && (__clang__ == 1)
    #   define _ELPP_COMPILER_CLANG 1
    #   define _ELPP_CLANG_VERSION (__clang_major__ * 10000 \
                                    + __clang_minor__ * 100 \
                                    + __clang_patchlevel__)
    #   if (_ELPP_CLANG_VERSION >= 30300)
    #      define _ELPP_CXX11 1
    #   endif  // (_ELPP_CLANG_VERSION >= 30300)
    #endif  // defined(__clang__) && (__clang__ == 1)
    // MinGW
    #if defined(__MINGW32__) || defined(__MINGW64__)
    #   define _ELPP_MINGW 1
    #endif  // defined(__MINGW32__) || defined(__MINGW64__)
    // Cygwin
    #if defined(__CYGWIN__) && (__CYGWIN__ == 1)
    #   define _ELPP_CYGWIN 1
    #endif  // defined(__CYGWIN__) && (__CYGWIN__ == 1)
    // Intel C++
    #if defined(__INTEL_COMPILER)
    #   define _ELPP_COMPILER_INTEL 1
    #endif
    // Operating System Evaluation
    // Windows
    #if defined(_WIN32) || defined(_WIN64)
    #   define _ELPP_OS_WINDOWS 1
    #endif  // defined(_WIN32) || defined(_WIN64)
    // Linux
    #if (defined(__linux) || defined(__linux__))
    #   define _ELPP_OS_LINUX 1
    #endif  // (defined(__linux) || defined(__linux__))
    // Mac
    #if defined(__APPLE__)
    #   define _ELPP_OS_MAC 1
    #endif  // defined(__APPLE__)
    // FreeBSD
    #if defined(__FreeBSD__)
    #   define _ELPP_OS_FREEBSD 1
    #endif
    // Unix
    #if ((_ELPP_OS_LINUX || _ELPP_OS_MAC || _ELPP_OS_FREEBSD) && (!_ELPP_OS_WINDOWS))
    #   define _ELPP_OS_UNIX 1
    #endif  // ((_ELPP_OS_LINUX || _ELPP_OS_MAC || _ELPP_OS_FREEBSD) && (!_ELPP_OS_WINDOWS))
    // Android
    #if defined(__ANDROID__)
    #   define _ELPP_OS_ANDROID 1
    #endif  // defined(__ANDROID__)
    // Evaluating Cygwin as *nix OS
    #if !_ELPP_OS_UNIX && !_ELPP_OS_WINDOWS && _ELPP_CYGWIN
    #   undef _ELPP_OS_UNIX
    #   undef _ELPP_OS_LINUX
    #   define _ELPP_OS_UNIX 1
    #   define _ELPP_OS_LINUX 1
    #endif //  !_ELPP_OS_UNIX && !_ELPP_OS_WINDOWS && _ELPP_CYGWIN
    #if !defined(_ELPP_INTERNAL_DEBUGGING_OUT_INFO)
    #   define _ELPP_INTERNAL_DEBUGGING_OUT_INFO std::cout
    #endif // !defined(_ELPP_INTERNAL_DEBUGGING_OUT)
    #if !defined(_ELPP_INTERNAL_DEBUGGING_OUT_ERROR)
    #   define _ELPP_INTERNAL_DEBUGGING_OUT_ERROR std::cerr
    #endif // !defined(_ELPP_INTERNAL_DEBUGGING_OUT)
    #if !defined(_ELPP_INTERNAL_DEBUGGING_ENDL)
    #   define _ELPP_INTERNAL_DEBUGGING_ENDL std::endl
    #endif // !defined(_ELPP_INTERNAL_DEBUGGING_OUT)
    #if !defined(_ELPP_INTERNAL_DEBUGGING_MSG)
    #   define _ELPP_INTERNAL_DEBUGGING_MSG(msg) msg
    #endif // !defined(_ELPP_INTERNAL_DEBUGGING_OUT)
    // Internal Assertions and errors
    #if !defined(_ELPP_DISABLE_ASSERT)
    #   if (defined(_ELPP_DEBUG_ASSERT_FAILURE))
    #      define ELPP_ASSERT(expr, msg) if (!(expr)) { \
              std::stringstream internalInfoStream; internalInfoStream << msg; \
              _ELPP_INTERNAL_DEBUGGING_OUT_ERROR \
                  << "EASYLOGGING++ ASSERTION FAILED (LINE: " << __LINE__ << ") [" #expr << "] WITH MESSAGE \"" \
                  << _ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << "\"" << _ELPP_INTERNAL_DEBUGGING_ENDL; base::utils::abort(1, \
                      "ELPP Assertion failure, please define _ELPP_DEBUG_ASSERT_FAILURE"); }
    #   else
    #      define ELPP_ASSERT(expr, msg) if (!(expr)) { \
              std::stringstream internalInfoStream; internalInfoStream << msg; \
              _ELPP_INTERNAL_DEBUGGING_OUT_ERROR\
                 << "ASSERTION FAILURE FROM EASYLOGGING++ (LINE: " \
                 << __LINE__ << ") [" #expr << "] WITH MESSAGE \"" << _ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << "\"" \
                 << _ELPP_INTERNAL_DEBUGGING_ENDL; }
    #   endif  // (defined(_ELPP_DEBUG_ASSERT_FAILURE))
    #else
    #   define ELPP_ASSERT(x, y)
    #endif  //(!defined(_ELPP_DISABLE_ASSERT)
    #if _ELPP_COMPILER_MSVC
    #   define _ELPP_INTERNAL_DEBUGGING_WRITE_PERROR \
           { char buff[256]; strerror_s(buff, 256, errno); \
           _ELPP_INTERNAL_DEBUGGING_OUT_ERROR << ": " << buff << " [" << errno << "]";} (void)0
    #else
    #   define _ELPP_INTERNAL_DEBUGGING_WRITE_PERROR \
            _ELPP_INTERNAL_DEBUGGING_OUT_ERROR << ": " << strerror(errno) << " [" << errno << "]"; (void)0
    #endif  // _ELPP_COMPILER_MSVC
    #if defined(_ELPP_DEBUG_ERRORS)
    #   if !defined(ELPP_INTERNAL_ERROR)
    #      define ELPP_INTERNAL_ERROR(msg, pe) { \
              std::stringstream internalInfoStream; internalInfoStream << "<ERROR> " << msg; \
              _ELPP_INTERNAL_DEBUGGING_OUT_ERROR \
              << "ERROR FROM EASYLOGGING++ (LINE: " << __LINE__ << ") " \
              << _ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << _ELPP_INTERNAL_DEBUGGING_ENDL; \
              if (pe) { _ELPP_INTERNAL_DEBUGGING_OUT_ERROR << "    "; _ELPP_INTERNAL_DEBUGGING_WRITE_PERROR; }} (void)0
    #   endif
    #else
    #   undef ELPP_INTERNAL_INFO
    #   define ELPP_INTERNAL_ERROR(msg, pe)
    #endif  // defined(_ELPP_DEBUG_ERRORS)
    #if (defined(_ELPP_DEBUG_INFO))
    #   if !(defined(_ELPP_INTERNAL_INFO_LEVEL))
    #      define _ELPP_INTERNAL_INFO_LEVEL 9
    #   endif  // !(defined(_ELPP_INTERNAL_INFO_LEVEL))
    #   if !defined(ELPP_INTERNAL_INFO)
    #      define ELPP_INTERNAL_INFO(lvl, msg) { if (lvl <= _ELPP_INTERNAL_INFO_LEVEL) { \
              std::stringstream internalInfoStream; internalInfoStream << "<INFO> " << msg; \
              _ELPP_INTERNAL_DEBUGGING_OUT_INFO << _ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) \
                 << _ELPP_INTERNAL_DEBUGGING_ENDL; }}
    #   endif
    #else
    #   undef ELPP_INTERNAL_INFO
    #   define ELPP_INTERNAL_INFO(lvl, msg)
    #endif  // (defined(_ELPP_DEBUG_INFO))
    #if defined(_ELPP_STACKTRACE_ON_CRASH)
    #   if (_ELPP_COMPILER_GCC && !_ELPP_MINGW)
    #      define _ELPP_STACKTRACE 1
    #   else
    #      if _ELPP_COMPILER_MSVC
    #         pragma message("Stack trace not available for this compiler")
    #      else
    #         warning "Stack trace not available for this compiler";
    #      endif  // _ELPP_COMPILER_MSVC
    #   endif  // _ELPP_COMPILER_GCC
    #endif  // (defined(_ELPP_STACKTRACE_ON_CRASH))
    // Miscellaneous macros
    #define _ELPP_UNUSED(x) (void)x
    #if _ELPP_OS_UNIX
    // Log file permissions for unix-based systems
    #   define _ELPP_LOG_PERMS S_IRUSR | S_IWUSR | S_IXUSR | S_IWGRP | S_IRGRP | S_IXGRP | S_IWOTH | S_IXOTH
    #endif  // _ELPP_OS_UNIX
    #if defined(_ELPP_AS_DLL) && _ELPP_COMPILER_MSVC
    #   if defined(_ELPP_EXPORT_SYMBOLS)
    #      define _ELPP_EXPORT __declspec(dllexport)
    #   else
    #      define _ELPP_EXPORT __declspec(dllimport)
    #   endif  // defined(_ELPP_EXPORT_SYMBOLS)
    #else
    #   define _ELPP_EXPORT
    #endif  // defined(_ELPP_AS_DLL) && _ELPP_COMPILER_MSVC
    // Some special functions that are VC++ specific
    #undef STRTOK
    #undef STRERROR
    #undef STRCAT
    #undef STRCPY
    #if _ELPP_CRT_DBG_WARNINGS
    #   define STRTOK(a, b, c) strtok_s(a, b, c)
    #   define STRERROR(a, b, c) strerror_s(a, b, c)
    #   define STRCAT(a, b, len) strcat_s(a, len, b)
    #   define STRCPY(a, b, len) strcpy_s(a, len, b)
    #else
    #   define STRTOK(a, b, c) strtok(a, b)  // NOLINT
    #   define STRERROR(a, b, c) strerror(c)
    #   define STRCAT(a, b, len) strcat(a, b)  // NOLINT
    #   define STRCPY(a, b, len) strcpy(a, b)  // NOLINT
    #endif
    // Compiler specific support evaluations
    #if (!_ELPP_MINGW && !_ELPP_COMPILER_CLANG) || defined(_ELPP_FORCE_USE_STD_THREAD)
    #   define _ELPP_USE_STD_THREADING 1
    #endif  // (!_ELPP_MINGW && !_ELPP_COMPILER_CLANG) || defined(_ELPP_FORCE_USE_STD_THREAD)
    #undef ELPP_FINAL
    #if _ELPP_COMPILER_INTEL || (_ELPP_GCC_VERSION < 40702)
    #   define ELPP_FINAL
    #else
    #   define ELPP_FINAL final
    #endif  // _ELPP_COMPILER_INTEL || (_ELPP_GCC_VERSION < 40702)
    #if defined(_ELPP_THREAD_SAFE)
    #   define _ELPP_THREADING_ENABLED 1
    #endif  // defined(_ELPP_THREAD_SAFE)
    // Function macro _ELPP_FUNC
    #undef _ELPP_FUNC
    #if _ELPP_COMPILER_MSVC  // Visual C++
    #   define _ELPP_FUNC __FUNCSIG__
    #elif _ELPP_COMPILER_GCC  // GCC
    #   define _ELPP_FUNC __PRETTY_FUNCTION__
    #elif _ELPP_COMPILER_INTEL  // Intel C++
    #   define _ELPP_FUNC __PRETTY_FUNCTION__
    #elif _ELPP_COMPILER_CLANG  // Clang++
    #   define _ELPP_FUNC __PRETTY_FUNCTION__
    #else
    #   if defined(__func__)
    #      define _ELPP_FUNC __func__
    #   else
    #      define _ELPP_FUNC ""
    #   endif  // defined(__func__)
    #endif  // defined(_MSC_VER)
    #undef _ELPP_VARIADIC_TEMPLATES_SUPPORTED
    // Keep following line commented until features are fixed
    #if _ELPP_COMPILER_GCC || _ELPP_COMPILER_CLANG || _ELPP_COMPILER_INTEL || (_ELPP_COMPILER_MSVC && _MSC_VER >= 1800)
    #   define _ELPP_VARIADIC_TEMPLATES_SUPPORTED 1
    #endif  // _ELPP_COMPILER_GCC || _ELPP_COMPILER_CLANG || _ELPP_COMPILER_INTEL || (_ELPP_COMPILER_MSVC && _MSC_VER >= 1800)
    // Logging Enable/Disable macros
    #if (!defined(_ELPP_DISABLE_LOGS))
    #   define _ELPP_LOGGING_ENABLED 1
    #endif  // (!defined(_ELPP_DISABLE_LOGS))
    #if (!defined(_ELPP_DISABLE_DEBUG_LOGS) && (_ELPP_LOGGING_ENABLED) && ((defined(_DEBUG)) || (!defined(NDEBUG))))
    #   define _ELPP_DEBUG_LOG 1
    #else
    #   define _ELPP_DEBUG_LOG 0
    #endif  // (!defined(_ELPP_DISABLE_DEBUG_LOGS) && (_ELPP_LOGGING_ENABLED) && ((defined(_DEBUG)) || (!defined(NDEBUG))))
    #if (!defined(_ELPP_DISABLE_INFO_LOGS) && (_ELPP_LOGGING_ENABLED))
    #   define _ELPP_INFO_LOG 1
    #else
    #   define _ELPP_INFO_LOG 0
    #endif  // (!defined(_ELPP_DISABLE_INFO_LOGS) && (_ELPP_LOGGING_ENABLED))
    #if (!defined(_ELPP_DISABLE_WARNING_LOGS) && (_ELPP_LOGGING_ENABLED))
    #   define _ELPP_WARNING_LOG 1
    #else
    #   define _ELPP_WARNING_LOG 0
    #endif  // (!defined(_ELPP_DISABLE_WARNING_LOGS) && (_ELPP_LOGGING_ENABLED))
    #if (!defined(_ELPP_DISABLE_ERROR_LOGS) && (_ELPP_LOGGING_ENABLED))
    #   define _ELPP_ERROR_LOG 1
    #else
    #   define _ELPP_ERROR_LOG 0
    #endif  // (!defined(_ELPP_DISABLE_ERROR_LOGS) && (_ELPP_LOGGING_ENABLED))
    #if (!defined(_ELPP_DISABLE_FATAL_LOGS) && (_ELPP_LOGGING_ENABLED))
    #   define _ELPP_FATAL_LOG 1
    #else
    #   define _ELPP_FATAL_LOG 0
    #endif  // (!defined(_ELPP_DISABLE_FATAL_LOGS) && (_ELPP_LOGGING_ENABLED))
    #if (!defined(_ELPP_DISABLE_TRACE_LOGS) && (_ELPP_LOGGING_ENABLED))
    #   define _ELPP_TRACE_LOG 1
    #else
    #   define _ELPP_TRACE_LOG 0
    #endif  // (!defined(_ELPP_DISABLE_TRACE_LOGS) && (_ELPP_LOGGING_ENABLED))
    #if (!defined(_ELPP_DISABLE_VERBOSE_LOGS) && (_ELPP_LOGGING_ENABLED))
    #   define _ELPP_VERBOSE_LOG 1
    #else
    #   define _ELPP_VERBOSE_LOG 0
    #endif  // (!defined(_ELPP_DISABLE_VERBOSE_LOGS) && (_ELPP_LOGGING_ENABLED))
    #if (!(_ELPP_CXX0X || _ELPP_CXX11))
    #   error "Easylogging++ 9.0+ is only compatible with C++0x (or higher) compliant compiler"
    #endif  // (!(_ELPP_CXX0X || _ELPP_CXX11))
    // Headers
    #if defined(_ELPP_SYSLOG)
    #   include <syslog.h>
    #endif  // defined(_ELPP_SYSLOG)
    #include <ctime>
    #include <cstring>
    #include <cstdlib>
    #include <cctype>
    #include <cwchar>
    #include <csignal>
    #include <cerrno>
    #include <cstdarg>
    #if defined(_ELPP_UNICODE)
    #   include <locale>
    #endif  // defined(_ELPP_UNICODE)
    #if _ELPP_STACKTRACE
    #   include <cxxabi.h>
    #   include <execinfo.h>
    #endif  // _ELPP_STACKTRACE
    #if _ELPP_OS_ANDROID
    #   include <sys/system_properties.h>
    #endif  // _ELPP_OS_ANDROID
    #if _ELPP_OS_UNIX
    #   include <sys/stat.h>
    #   include <sys/time.h>
    #elif _ELPP_OS_WINDOWS
    #   include <direct.h>
    #   include <Windows.h>
    #   if defined(WIN32_LEAN_AND_MEAN)
    #      include <winsock.h>
    #   endif // defined(WIN32_LEAN_AND_MEAN)
    #endif  // _ELPP_OS_UNIX
    #include <string>
    #include <vector>
    #include <map>
    #include <utility>
    #include <functional>
    #include <algorithm>
    #include <fstream>  // NOLINT
    #include <iostream>  // NOLINT
    #include <sstream>
    #include <memory>
    #include <type_traits>
    #if _ELPP_THREADING_ENABLED
    #   if _ELPP_USE_STD_THREADING
    #      include <mutex>
    #      include <thread>
    #   else
    #      if _ELPP_OS_UNIX
    #         include <pthread.h>
    #      endif  // _ELPP_OS_UNIX
    #   endif  // _ELPP_USE_STD_THREADING
    #endif  // _ELPP_THREADING_ENABLED
    #if defined(_ELPP_STL_LOGGING)
    // For logging STL based templates
    #   include <list>
    #   include <queue>
    #   include <deque>
    #   include <set>
    #   include <bitset>
    #   include <stack>
    #   if defined(_ELPP_LOG_STD_ARRAY)
    #      include <array>
    #   endif  // defined(_ELPP_LOG_STD_ARRAY)
    #   if defined(_ELPP_LOG_UNORDERED_MAP)
    #      include <unordered_map>
    #   endif  // defined(_ELPP_LOG_UNORDERED_MAP)
    #   if defined(_ELPP_LOG_UNORDERED_SET)
    #      include <unordered_set>
    #   endif  // defined(_ELPP_UNORDERED_SET)
    #endif  // defined(_ELPP_STL_LOGGING)
    #if defined(_ELPP_QT_LOGGING)
    // For logging Qt based classes & templates
    #   include <QString>
    #   include <QByteArray>
    #   include <QVector>
    #   include <QList>
    #   include <QPair>
    #   include <QMap>
    #   include <QQueue>
    #   include <QSet>
    #   include <QLinkedList>
    #   include <QHash>
    #   include <QMultiHash>
    #   include <QStack>
    #endif  // defined(_ELPP_QT_LOGGING)
    #if defined(_ELPP_BOOST_LOGGING)
    // For logging boost based classes & templates
    #   include <boost/container/vector.hpp>
    #   include <boost/container/stable_vector.hpp>
    #   include <boost/container/list.hpp>
    #   include <boost/container/deque.hpp>
    #   include <boost/container/map.hpp>
    #   include <boost/container/flat_map.hpp>
    #   include <boost/container/set.hpp>
    #   include <boost/container/flat_set.hpp>
    #endif  // defined(_ELPP_BOOST_LOGGING)
    #if defined(_ELPP_WXWIDGETS_LOGGING)
    // For logging wxWidgets based classes & templates
    #   include <wx/vector.h>
    #endif  // defined(_ELPP_WXWIDGETS_LOGGING)
    // Forward declarations
    namespace el {
    class Logger;
    class LogMessage;
    class PerformanceTrackingData;
    class Loggers;
    class Helpers;
    template <typename T> class Callback;
    class LogDispatchCallback;
    class PerformanceTrackingCallback;
    class LogDispatchData;
    namespace base {
    class Storage;
    class RegisteredLoggers;
    class PerformanceTracker;
    class MessageBuilder;
    class Writer;
    class PErrorWriter;
    class LogDispatcher;
    class DefaultLogBuilder;
    class DefaultLogDispatchCallback;
    class DefaultPerformanceTrackingCallback;
    }  // namespace base
    }  // namespace el
    /// @brief Easylogging++ entry namespace
    namespace el {
    /// @brief Namespace containing base/internal functionality used by Easylogging++
    namespace base {
    /// @brief Data types used by Easylogging++
    namespace type {
    #undef ELPP_LITERAL
    #undef ELPP_STRLEN
    #undef ELPP_COUT
    #if defined(_ELPP_UNICODE)
    #   define ELPP_LITERAL(txt) L##txt
    #   define ELPP_STRLEN wcslen
    #   if defined ELPP_CUSTOM_COUT
    #      define ELPP_COUT ELPP_CUSTOM_COUT
    #   else
    #      define ELPP_COUT std::wcout
    #   endif  // defined ELPP_CUSTOM_COUT
    typedef wchar_t char_t;
    typedef std::wstring string_t;
    typedef std::wstringstream stringstream_t;
    typedef std::wfstream fstream_t;
    typedef std::wostream ostream_t;
    #else
    #   define ELPP_LITERAL(txt) txt
    #   define ELPP_STRLEN strlen
    #   if defined ELPP_CUSTOM_COUT
    #      define ELPP_COUT ELPP_CUSTOM_COUT
    #   else
    #      define ELPP_COUT std::cout
    #   endif  // defined ELPP_CUSTOM_COUT
    typedef char char_t;
    typedef std::string string_t;
    typedef std::stringstream stringstream_t;
    typedef std::fstream fstream_t;
    typedef std::ostream ostream_t;
    #endif  // defined(_ELPP_UNICODE)
    #if defined(ELPP_CUSTOM_COUT_LINE)
    #   define ELPP_COUT_LINE(logLine) ELPP_CUSTOM_COUT_LINE(logLine)
    #else
    #   define ELPP_COUT_LINE(logLine) logLine << std::flush
    #endif // defined(ELPP_CUSTOM_COUT_LINE)
    typedef unsigned short EnumType;  // NOLINT
    typedef std::shared_ptr<base::Storage> StoragePointer;
    typedef int VerboseLevel;
    typedef std::shared_ptr<LogDispatchCallback> LogDispatchCallbackPtr;
    typedef std::shared_ptr<PerformanceTrackingCallback> PerformanceTrackingCallbackPtr;
    }  // namespace type
    /// @brief Internal helper class that prevent copy constructor for class
    ///
    /// @detail When using this class simply inherit it privately
    class NoCopy {
    protected:
        NoCopy(void) {}
    private:
        NoCopy(const NoCopy&);
        NoCopy& operator=(const NoCopy&);
    };
    /// @brief Internal helper class that makes all default constructors private.
    ///
    /// @detail This prevents initializing class making it static unless an explicit constructor is declared.
    /// When using this class simply inherit it privately
    class StaticClass {
    private:
        StaticClass(void);
        StaticClass(const StaticClass&);
        StaticClass& operator=(const StaticClass&);
    };
    }  // namespace base
    /// @brief Represents enumeration for severity level used to determine level of logging
    ///
    /// @detail With Easylogging++, developers may disable or enable any level regardless of
    /// what the severity is. Or they can choose to log using hierarchical logging flag
    enum class Level : base::type::EnumType {
            /// @brief Generic level that represents all the levels. Useful when setting global configuration for all levels
            Global = 1,
            /// @brief Information that can be useful to back-trace certain events - mostly useful than debug logs.
            Trace = 2,
            /// @brief Informational events most useful for developers to debug application
            Debug = 4,
            /// @brief Severe error information that will presumably abort application
            Fatal = 8, 
            /// @brief Information representing errors in application but application will keep running
            Error = 16,
            /// @brief Useful when application has potentially harmful situtaions
            Warning = 32, 
            /// @brief Information that can be highly useful and vary with verbose logging level.
            Verbose = 64,
            /// @brief Mainly useful to represent current progress of application
            Info = 128, 
            /// @brief Represents unknown level
            Unknown = 1010
    };
    /// @brief Static class that contains helper functions for el::Level
    class LevelHelper : base::StaticClass {
    public:
        /// @brief Represents minimum valid level. Useful when iterating through enum.
        static const base::type::EnumType kMinValid = static_cast<base::type::EnumType>(Level::Trace);
        /// @brief Represents maximum valid level. This is used internally and you should not need it.
        static const base::type::EnumType kMaxValid = static_cast<base::type::EnumType>(Level::Info);
        /// @brief Casts level to int, useful for iterating through enum.
        static base::type::EnumType castToInt(Level level) {
            return static_cast<base::type::EnumType>(level);
        }
        /// @brief Casts int(ushort) to level, useful for iterating through enum.
        static Level castFromInt(base::type::EnumType l) {
            return static_cast<Level>(l);
        }
        /// @brief Converts level to associated const char*
        /// @return Upper case string based level.
        static const char* convertToString(Level level) {
           // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet.
            if (level == Level::Global) return "GLOBAL";
            if (level == Level::Debug) return "DEBUG";
            if (level == Level::Info) return "INFO";
            if (level == Level::Warning) return "WARNING";
            if (level == Level::Error) return "ERROR";
            if (level == Level::Fatal) return "FATAL";
            if (level == Level::Verbose) return "VERBOSE";
            if (level == Level::Trace) return "TRACE";
            return "UNKNOWN";
        }
        /// @brief Converts from levelStr to Level
        /// @param levelStr Upper case string based level.
        ///        Lower case is also valid but providing upper case is recommended.
        static Level convertFromString(const char* levelStr) {
            if ((strcmp(levelStr, "GLOBAL") == 0) || (strcmp(levelStr, "global") == 0))
                return Level::Global;
            if ((strcmp(levelStr, "DEBUG") == 0) || (strcmp(levelStr, "debug") == 0))
                return Level::Debug;
            if ((strcmp(levelStr, "INFO") == 0) || (strcmp(levelStr, "info") == 0))
                return Level::Info;
            if ((strcmp(levelStr, "WARNING") == 0) || (strcmp(levelStr, "warning") == 0))
                return Level::Warning;
            if ((strcmp(levelStr, "ERROR") == 0) || (strcmp(levelStr, "error") == 0))
                return Level::Error;
            if ((strcmp(levelStr, "FATAL") == 0) || (strcmp(levelStr, "fatal") == 0))
                return Level::Fatal;
            if ((strcmp(levelStr, "VERBOSE") == 0) || (strcmp(levelStr, "verbose") == 0))
                return Level::Verbose;
            if ((strcmp(levelStr, "TRACE") == 0) || (strcmp(levelStr, "trace") == 0))
                return Level::Trace;
            return Level::Unknown;
        }
        /// @brief Applies specified function to each level starting from startIndex
        /// @param startIndex initial value to start the iteration from. This is passed as pointer and 
        ///        is left-shifted so this can be used inside function (fn) to represent current level.
        /// @param fn function to apply with each level. This bool represent whether or not to stop iterating through levels.
        static inline void forEachLevel(base::type::EnumType* startIndex, const std::function<bool(void)>& fn) {
            base::type::EnumType lIndexMax = LevelHelper::kMaxValid;
            do {
                if (fn()) {
                    break;
                }
                *startIndex = static_cast<base::type::EnumType>(*startIndex << 1);
            } while (*startIndex <= lIndexMax);
        }
    };
    /// @brief Represents enumeration of ConfigurationType used to configure or access certain aspect
    /// of logging
    enum class ConfigurationType : base::type::EnumType {
       /// @brief Determines whether or not corresponding level and logger of logging is enabled
       /// You may disable all logs by using el::Level::Global
        Enabled = 1,
       /// @brief Whether or not to write corresponding log to log file
        ToFile = 2,
       /// @brief Whether or not to write corresponding level and logger log to standard output.
       /// By standard output meaning termnal, command prompt etc
        ToStandardOutput = 4,
       /// @brief Determines format of logging corresponding level and logger.
        Format = 8,
       /// @brief Determines log file (full path) to write logs to for correponding level and logger
        Filename = 16,
       /// @brief Specifies milliseconds width. Width can be within range (1-6)
        MillisecondsWidth = 32,
       /// @brief Determines whether or not performance tracking is enabled.
       ///
       /// @detail This does not depend on logger or level. Performance tracking always uses 'performance' logger
        PerformanceTracking = 64,
       /// @brief Specifies log file max size.
       ///
       /// @detail If file size of corresponding log file (for corresponding level) is >= specified size, log file will 
       /// be truncated and re-initiated.
        MaxLogFileSize = 128,
       /// @brief Specifies number of log entries to hold until we flush pending log data
        LogFlushThreshold = 256,
       /// @brief Represents unknown configuration
        Unknown = 1010
    };
    /// @brief Static class that contains helper functions for el::ConfigurationType
    class ConfigurationTypeHelper : base::StaticClass {
    public:
        /// @brief Represents minimum valid configuration type. Useful when iterating through enum.
        static const base::type::EnumType kMinValid = static_cast<base::type::EnumType>(ConfigurationType::Enabled);
        /// @brief Represents maximum valid configuration type. This is used internally and you should not need it.
        static const base::type::EnumType kMaxValid = static_cast<base::type::EnumType>(ConfigurationType::MaxLogFileSize);
        /// @brief Casts configuration type to int, useful for iterating through enum.
        static base::type::EnumType castToInt(ConfigurationType configurationType) {
            return static_cast<base::type::EnumType>(configurationType);
        }
        /// @brief Casts int(ushort) to configurationt type, useful for iterating through enum.
        static ConfigurationType castFromInt(base::type::EnumType c) {
            return static_cast<ConfigurationType>(c);
        }
        /// @brief Converts configuration type to associated const char*
        /// @returns Upper case string based configuration type.
        static const char* convertToString(ConfigurationType configurationType) {
            // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet.
            if (configurationType == ConfigurationType::Enabled) return "ENABLED";
            if (configurationType == ConfigurationType::Filename) return "FILENAME";
            if (configurationType == ConfigurationType::Format) return "FORMAT";
            if (configurationType == ConfigurationType::ToFile) return "TO_FILE";
            if (configurationType == ConfigurationType::ToStandardOutput) return "TO_STANDARD_OUTPUT";
            if (configurationType == ConfigurationType::MillisecondsWidth) return "MILLISECONDS_WIDTH";
            if (configurationType == ConfigurationType::PerformanceTracking) return "PERFORMANCE_TRACKING";
            if (configurationType == ConfigurationType::MaxLogFileSize) return "MAX_LOG_FILE_SIZE";
            if (configurationType == ConfigurationType::LogFlushThreshold) return "LOG_FLUSH_THRESHOLD";
            return "UNKNOWN";
        }
        /// @brief Converts from configStr to ConfigurationType
        /// @param configStr Upper case string based configuration type.
        ///        Lower case is also valid but providing upper case is recommended.
        static ConfigurationType convertFromString(const char* configStr) {
            if ((strcmp(configStr, "ENABLED") == 0) || (strcmp(configStr, "enabled") == 0))
                return ConfigurationType::Enabled;
            if ((strcmp(configStr, "TO_FILE") == 0) || (strcmp(configStr, "to_file") == 0))
                return ConfigurationType::ToFile;
            if ((strcmp(configStr, "TO_STANDARD_OUTPUT") == 0) || (strcmp(configStr, "to_standard_output") == 0))
                return ConfigurationType::ToStandardOutput;
            if ((strcmp(configStr, "FORMAT") == 0) || (strcmp(configStr, "format") == 0))
                return ConfigurationType::Format;
            if ((strcmp(configStr, "FILENAME") == 0) || (strcmp(configStr, "filename") == 0))
                return ConfigurationType::Filename;
            if ((strcmp(configStr, "MILLISECONDS_WIDTH") == 0) || (strcmp(configStr, "milliseconds_width") == 0))
                return ConfigurationType::MillisecondsWidth;
            if ((strcmp(configStr, "PERFORMANCE_TRACKING") == 0) || (strcmp(configStr, "performance_tracking") == 0))
                return ConfigurationType::PerformanceTracking;
            if ((strcmp(configStr, "MAX_LOG_FILE_SIZE") == 0) || (strcmp(configStr, "max_log_file_size") == 0))
                return ConfigurationType::MaxLogFileSize;
            if ((strcmp(configStr, "LOG_FLUSH_THRESHOLD") == 0) || (strcmp(configStr, "log_flush_threshold") == 0))
                return ConfigurationType::LogFlushThreshold;
            return ConfigurationType::Unknown;
        }
        /// @brief Applies specified function to each configuration type starting from startIndex
        /// @param startIndex initial value to start the iteration from. This is passed by pointer and is left-shifted
        ///        so this can be used inside function (fn) to represent current configuration type.
        /// @param fn function to apply with each configuration type. 
        ///        This bool represent whether or not to stop iterating through configurations.
        static inline void forEachConfigType(base::type::EnumType* startIndex, const std::function<bool(void)>& fn) {
            base::type::EnumType cIndexMax = ConfigurationTypeHelper::kMaxValid;
            do {
                if (fn()) {
                    break;
                }
                *startIndex = static_cast<base::type::EnumType>(*startIndex << 1);
            } while (*startIndex <= cIndexMax);
        }
    };
    /// @brief Flags used while writing logs. This flags are set by user
    enum class LoggingFlag : base::type::EnumType {
        /// @brief Makes sure we have new line for each container log entry
        NewLineForContainer = 1,
        /// @brief Makes sure if -vmodule is used and does not specifies a module, then verbose
        /// logging is allowed via that module.
        AllowVerboseIfModuleNotSpecified = 2,
        /// @brief When handling crashes by default, detailed crash reason will be logged as well
        LogDetailedCrashReason = 4,
        /// @brief Allows to disable application abortion when logged using FATAL level
        DisableApplicationAbortOnFatalLog = 8,
        /// @brief Flushes log with every log-entry (performance sensative) - Disabled by default
        ImmediateFlush = 16,
        /// @brief Enables strict file rolling
        StrictLogFileSizeCheck = 32,
        /// @brief Make terminal output colorful for supported terminals
        ColoredTerminalOutput = 64,
        /// @brief Supports use of multiple logging in same macro, e.g, CLOG(INFO, "default", "network")
        MultiLoggerSupport = 128,
        /// @brief Disables comparing performance tracker's checkpoints
        DisablePerformanceTrackingCheckpointComparison = 256,
        /// @brief Disable VModules
        DisableVModules = 512,
        /// @brief Disable VModules extensions
        DisableVModulesExtensions = 1024,
        /// @brief Enables hierarchical logging
        HierarchicalLogging = 2048,
        /// @brief Creates logger automatically when not available
        CreateLoggerAutomatically = 4096,
        /// @brief Adds spaces b/w logs that separated by left-shift operator
        AutoSpacing = 8192
    };
    namespace base {
    /// @brief Namespace containing constants used internally.
    namespace consts {
        // Level log values - These are values that are replaced in place of %level format specifier
        static const base::type::char_t* kInfoLevelLogValue     =   ELPP_LITERAL("INFO ");
        static const base::type::char_t* kDebugLevelLogValue    =   ELPP_LITERAL("DEBUG");
        static const base::type::char_t* kWarningLevelLogValue  =   ELPP_LITERAL("WARN ");
        static const base::type::char_t* kErrorLevelLogValue    =   ELPP_LITERAL("ERROR");
        static const base::type::char_t* kFatalLevelLogValue    =   ELPP_LITERAL("FATAL");
        static const base::type::char_t* kVerboseLevelLogValue  =   ELPP_LITERAL("VER");
        static const base::type::char_t* kTraceLevelLogValue    =   ELPP_LITERAL("TRACE");
        static const base::type::char_t* kInfoLevelShortLogValue     =   ELPP_LITERAL("I");
        static const base::type::char_t* kDebugLevelShortLogValue    =   ELPP_LITERAL("D");
        static const base::type::char_t* kWarningLevelShortLogValue  =   ELPP_LITERAL("W");
        static const base::type::char_t* kErrorLevelShortLogValue    =   ELPP_LITERAL("E");
        static const base::type::char_t* kFatalLevelShortLogValue    =   ELPP_LITERAL("F");
        static const base::type::char_t* kVerboseLevelShortLogValue  =   ELPP_LITERAL("V");
        static const base::type::char_t* kTraceLevelShortLogValue    =   ELPP_LITERAL("T");
        // Format specifiers - These are used to define log format
        static const base::type::char_t* kAppNameFormatSpecifier          =      ELPP_LITERAL("%app");
        static const base::type::char_t* kLoggerIdFormatSpecifier         =      ELPP_LITERAL("%logger");
        static const base::type::char_t* kThreadIdFormatSpecifier         =      ELPP_LITERAL("%thread");
        static const base::type::char_t* kSeverityLevelFormatSpecifier    =      ELPP_LITERAL("%level");
        static const base::type::char_t* kSeverityLevelShortFormatSpecifier    =      ELPP_LITERAL("%levshort");
        static const base::type::char_t* kDateTimeFormatSpecifier         =      ELPP_LITERAL("%datetime");
        static const base::type::char_t* kLogFileFormatSpecifier          =      ELPP_LITERAL("%file");
        static const base::type::char_t* kLogFileBaseFormatSpecifier      =      ELPP_LITERAL("%fbase");
        static const base::type::char_t* kLogLineFormatSpecifier          =      ELPP_LITERAL("%line");
        static const base::type::char_t* kLogLocationFormatSpecifier      =      ELPP_LITERAL("%loc");
        static const base::type::char_t* kLogFunctionFormatSpecifier      =      ELPP_LITERAL("%func");
        static const base::type::char_t* kCurrentUserFormatSpecifier      =      ELPP_LITERAL("%user");
        static const base::type::char_t* kCurrentHostFormatSpecifier      =      ELPP_LITERAL("%host");
        static const base::type::char_t* kMessageFormatSpecifier          =      ELPP_LITERAL("%msg");
        static const base::type::char_t* kVerboseLevelFormatSpecifier     =      ELPP_LITERAL("%vlevel");
        static const char* kDateTimeFormatSpecifierForFilename            =      "%datetime";
        // Date/time
        static const char* kDays[7]                         =      { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
        static const char* kDaysAbbrev[7]                   =      { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
        static const char* kMonths[12]                      =      { "January", "February", "March", "Apri", "May", "June", "July", "August",
                "September", "October", "November", "December" };
        static const char* kMonthsAbbrev[12]                =      { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
        static const char* kDefaultDateTimeFormat           =      "%d/%M/%Y %H:%m:%s,%g";
        static const char* kDefaultDateTimeFormatInFilename =      "%d-%M-%Y_%H-%m";
        static const int kYearBase                          =      1900;
        static const char* kAm                              =      "AM";
        static const char* kPm                              =      "PM";
        // Miscellaneous constants
        static const char* kDefaultLoggerId                        =      "default";
        static const char* kPerformanceLoggerId                    =      "performance";
        static const char* kSysLogLoggerId                         =      "syslog";
        static const char* kNullPointer                            =      "nullptr";
        static const char  kFormatSpecifierChar                    =      '%';
    #if _ELPP_VARIADIC_TEMPLATES_SUPPORTED
        static const char  kFormatSpecifierCharValue               =      'v';
    #endif  // _ELPP_VARIADIC_TEMPLATES_SUPPORTED
        static const unsigned int kMaxLogPerContainer              =      100;
        static const unsigned int kMaxLogPerCounter                =      100000;
        static const unsigned int  kDefaultMillisecondsWidth       =      3;
        static const base::type::VerboseLevel kMaxVerboseLevel     =      9;
        static const char* kUnknownUser                            =      "user";
        static const char* kUnknownHost                            =      "unknown-host";
    #if defined(_ELPP_DEFAULT_LOG_FILE)
        static const char* kDefaultLogFile                         =      _ELPP_DEFAULT_LOG_FILE;
    #else
    #   if _ELPP_OS_UNIX
    #      if _ELPP_OS_ANDROID
        static const char* kDefaultLogFile                         =      "logs/myeasylog.log";
    #      else
        static const char* kDefaultLogFile                         =      "logs/myeasylog.log";
    #      endif  // _ELPP_OS_ANDROID
    #   elif _ELPP_OS_WINDOWS
        static const char* kDefaultLogFile                         =      "logs\\myeasylog.log";
    #   endif  // _ELPP_OS_UNIX
    #endif  // defined(_ELPP_DEFAULT_LOG_FILE)
    #if !defined(_ELPP_DISABLE_LOG_FILE_FROM_ARG)
        static const char* kDefaultLogFileParam                    =      "--default-log-file";
    #endif  // !defined(_ELPP_DISABLE_LOG_FILE_FROM_ARG)
    #if defined(_ELPP_LOGGING_FLAGS_FROM_ARG)
        static const char* kLoggingFlagsParam                      =      "--logging-flags";
    #endif  // defined(_ELPP_LOGGING_FLAGS_FROM_ARG)
    #if _ELPP_OS_WINDOWS
        static const char* kFilePathSeperator                      =      "\\";
    #else
        static const char* kFilePathSeperator                      =      "/";
    #endif  // _ELPP_OS_WINDOWS
        static const char* kValidLoggerIdSymbols                   =      "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._";
        static const char* kConfigurationComment                   =      "##";
        static const char* kConfigurationLevel                     =      "*";
        static const char* kConfigurationLoggerId                  =      "--";
        static const std::size_t kSourceFilenameMaxLength          =      100;
        static const std::size_t kSourceLineMaxLength              =      10;
        static const Level kPerformanceTrackerDefaultLevel         =      Level::Info;
        const struct {
            double value;
            const base::type::char_t* unit;
        } kTimeFormats[] = {
           { 1000.0f, ELPP_LITERAL("mis") },
           { 1000.0f, ELPP_LITERAL("ms") },
           { 60.0f, ELPP_LITERAL("seconds") },
           { 60.0f, ELPP_LITERAL("minutes") },
           { 24.0f, ELPP_LITERAL("hours") },
           { 7.0f, ELPP_LITERAL("days") }
        };
        static const int kTimeFormatsCount                           =      sizeof(kTimeFormats) / sizeof(kTimeFormats[0]);
        const struct {
            int numb;
            const char* name;
            const char* brief;
            const char* detail;
        } kCrashSignals[] = {
            // NOTE: Do not re-order, if you do please check CrashHandler(bool) constructor and CrashHandler::setHandler(..)
            { SIGABRT, "SIGABRT", "Abnormal termination",
                    "Program was abnormally terminated." },
            { SIGFPE, "SIGFPE", "Erroneous arithmetic operation",
                    "Arithemetic operation issue such as division by zero or operation resulting in overflow." },
            { SIGILL, "SIGILL", "Illegal instruction",
                    "Generally due to a corruption in the code or to an attempt to execute data."},
            { SIGSEGV, "SIGSEGV", "Invalid access to memory",
                    "Program is trying to read an invalid (unallocated, deleted or corrupted) or inaccessible memory." },
            { SIGINT, "SIGINT", "Interactive attention signal",
                     "Interruption generated (generally) by user or operating system." },
        };
        static const int kCrashSignalsCount                          =      sizeof(kCrashSignals) / sizeof(kCrashSignals[0]);
    }  // namespace consts
    }  // namespace base
    typedef std::function<void(const char*, std::size_t)> PreRollOutCallback;
    namespace base {
    static inline void defaultPreRollOutCallback(const char*, std::size_t) {}
    /// @brief Enum to represent timestamp unit
    enum class TimestampUnit : base::type::EnumType {
        Microsecond = 0, Millisecond = 1, Second = 2, Minute = 3, Hour = 4, Day = 5
    };
    /// @brief Format flags used to determine specifiers that are active for performance improvements.
    enum class FormatFlags : base::type::EnumType {
        DateTime = 1<<1, LoggerId = 1<<2, File = 1<<3, Line = 1<<4, Location = 1<<5, Function = 1<<6,
        User = 1<<7, Host = 1<<8, LogMessage = 1<<9, VerboseLevel = 1<<10, AppName = 1<<11, ThreadId = 1<<12,
        Level = 1<<13, FileBase = 1<<14, LevelShort = 1<<15
    };
    /// @brief A milliseconds width class containing actual width and offset for date/time
    class MillisecondsWidth {
    public:
        MillisecondsWidth(void) { init(base::consts::kDefaultMillisecondsWidth); }
        explicit MillisecondsWidth(int width) { init(width); }
        bool operator==(const MillisecondsWidth& msWidth) { return m_width == msWidth.m_width && m_offset == msWidth.m_offset; }
        int m_width; unsigned int m_offset;
    private:
        void init(int width) {
            if (width < 1 || width > 6) {
                width = base::consts::kDefaultMillisecondsWidth;
            }
            m_width = width;
            switch (m_width) {
            case 3: m_offset = 1000; break;
            case 4: m_offset = 100; break;
            case 5: m_offset = 10; break;
            case 6: m_offset = 1; break;
            default: m_offset = 1000; break;
            }
        }
    };
    /// @brief Namespace containing utility functions/static classes used internally
    namespace utils {
    /// @brief Deletes memory safely and points to null
    template <typename T>
    static inline
    typename std::enable_if<std::is_pointer<T*>::value, void>::type
    safeDelete(T*& pointer) {  // NOLINT
        if (pointer == nullptr)
            return;
        delete pointer;
        pointer = nullptr;
    }
    /// @brief Gets value of const char* but if it is nullptr, a string nullptr is returned
    static inline const char* charPtrVal(const char* pointer) {
        return pointer == nullptr ? base::consts::kNullPointer : pointer;
    }
    /// @brief Aborts application due with user-defined status
    static inline void abort(int status, const std::string& reason = std::string()) {
        // Both status and reason params are there for debugging with tools like gdb etc
        _ELPP_UNUSED(status);
        _ELPP_UNUSED(reason);
    #if defined(_ELPP_COMPILER_MSVC) && defined(_M_IX86) && defined(_DEBUG)
       // Ignore msvc critical error dialog - break instead (on debug mode)
        _asm int 3
    #else
        ::abort();
    #endif  // defined(_ELPP_COMPILER_MSVC) && defined(_M_IX86) && defined(_DEBUG)
    }
    /// @brief Bitwise operations for C++11 strong enum class. This casts e into Flag_T and returns value after bitwise operation
    /// Use these function as <pre>flag = bitwise::Or<MyEnum>(MyEnum::val1, flag);</pre>
    namespace bitwise {
    template <typename Enum>
    static inline base::type::EnumType And(Enum e, base::type::EnumType flag) {
        return static_cast<base::type::EnumType>(flag) & static_cast<base::type::EnumType>(e);
    }
    template <typename Enum>
    static inline base::type::EnumType Not(Enum e, base::type::EnumType flag) {
        return static_cast<base::type::EnumType>(flag) & ~(static_cast<base::type::EnumType>(e));
    }
    template <typename Enum>
    static inline base::type::EnumType Or(Enum e, base::type::EnumType flag) {
        return static_cast<base::type::EnumType>(flag) | static_cast<base::type::EnumType>(e);
    }
    }  // namespace bitwise
    template <typename Enum>
    static inline void addFlag(Enum e, base::type::EnumType* flag) {
        *flag = base::utils::bitwise::Or<Enum>(e, *flag);
    }
    template <typename Enum>
    static inline void removeFlag(Enum e, base::type::EnumType* flag) {
        *flag = base::utils::bitwise::Not<Enum>(e, *flag);
    }
    template <typename Enum>
    static inline bool hasFlag(Enum e, base::type::EnumType flag) {
        return base::utils::bitwise::And<Enum>(e, flag) > 0x0;
    }
    }  // namespace utils
    namespace threading {
    #if _ELPP_THREADING_ENABLED
    #   if !_ELPP_USE_STD_THREADING
    namespace internal {
    /// @brief A mutex wrapper for compiler that dont yet support std::mutex
    class Mutex : base::NoCopy {
    public:
        Mutex(void) {
    #   if _ELPP_OS_UNIX
            pthread_mutex_init(&m_underlyingMutex, nullptr);
    #   elif _ELPP_OS_WINDOWS
            InitializeCriticalSection(&m_underlyingMutex);
    #   endif  // _ELPP_OS_UNIX
        }
    
        virtual ~Mutex(void) {
    #   if _ELPP_OS_UNIX
            pthread_mutex_destroy(&m_underlyingMutex);
    #   elif _ELPP_OS_WINDOWS
            DeleteCriticalSection(&m_underlyingMutex);
    #   endif  // _ELPP_OS_UNIX
        }
    
        inline void lock(void) {
    #   if _ELPP_OS_UNIX
            pthread_mutex_lock(&m_underlyingMutex);
    #   elif _ELPP_OS_WINDOWS
            EnterCriticalSection(&m_underlyingMutex);
    #   endif  // _ELPP_OS_UNIX
        }
    
        inline bool try_lock(void) {
    #   if _ELPP_OS_UNIX
            return (pthread_mutex_trylock(&m_underlyingMutex) == 0);
    #   elif _ELPP_OS_WINDOWS
            return TryEnterCriticalSection(&m_underlyingMutex);
    #   endif  // _ELPP_OS_UNIX
        }
    
        inline void unlock(void) {
    #   if _ELPP_OS_UNIX
            pthread_mutex_unlock(&m_underlyingMutex);
    #   elif _ELPP_OS_WINDOWS
            LeaveCriticalSection(&m_underlyingMutex);
    #   endif  // _ELPP_OS_UNIX
        }
    
    private:
    #   if _ELPP_OS_UNIX
        pthread_mutex_t m_underlyingMutex;
    #   elif _ELPP_OS_WINDOWS
        CRITICAL_SECTION m_underlyingMutex;
    #   endif  // _ELPP_OS_UNIX
    };
    /// @brief Scoped lock for compiler that dont yet support std::lock_guard
    template <typename M>
    class ScopedLock : base::NoCopy {
    public:
        explicit ScopedLock(M& mutex) {  // NOLINT
            m_mutex = &mutex;
            m_mutex->lock();
        }
    
        virtual ~ScopedLock(void) {
            m_mutex->unlock();
        }
    private:
        M* m_mutex;
        ScopedLock(void);
    };
    } // namespace internal
    /// @brief Gets ID of currently running threading in windows systems. On unix, nothing is returned.
    static inline std::string getCurrentThreadId(void) {
        std::stringstream ss;
    #      if (_ELPP_OS_WINDOWS)
        ss << GetCurrentThreadId();
    #      endif  // (_ELPP_OS_WINDOWS)
        return ss.str();
    }
    typedef base::threading::internal::Mutex Mutex;
    typedef base::threading::internal::ScopedLock<base::threading::Mutex> ScopedLock;
    #   else
    /// @brief Gets ID of currently running threading using std::this_thread::get_id()
    static inline std::string getCurrentThreadId(void) {
        std::stringstream ss;
        ss << std::this_thread::get_id();
        return ss.str();
    }
    typedef std::mutex Mutex;
    typedef std::lock_guard<std::mutex> ScopedLock;
    #   endif  // !_ELPP_USE_STD_THREADING
    #else