diff options
author | Clyne Sullivan <clyne@bitgloo.com> | 2022-08-19 19:51:50 -0400 |
---|---|---|
committer | Clyne Sullivan <clyne@bitgloo.com> | 2022-08-19 19:51:50 -0400 |
commit | abf136be66b78f9a1fb913dfad26225beeb2ca34 (patch) | |
tree | 7748910a0f077813c7b949fb0a6b731f5b712d49 | |
parent | c467671ae8b6ec161c17e86f3383fd0625f755b8 (diff) |
add sol2 submodule; remove entityx to add submodule
58 files changed, 3 insertions, 15475 deletions
diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..340f9cd --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/sol2"] + path = lib/sol2 + url = https://github.com/ThePhD/sol2 diff --git a/lib/entityx/.clang_complete b/lib/entityx/.clang_complete deleted file mode 100644 index 492390d..0000000 --- a/lib/entityx/.clang_complete +++ /dev/null @@ -1,2 +0,0 @@ --std=c++11 --I. diff --git a/lib/entityx/.travis.yml b/lib/entityx/.travis.yml deleted file mode 100644 index c06dba4..0000000 --- a/lib/entityx/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -language: cpp -compiler: - - clang - - gcc -before_install: - - sudo apt-add-repository -y ppa:jkeiren/ppa - - if test $CC = gcc; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi - - sudo add-apt-repository -y ppa:george-edison55/precise-backports - - sudo apt-get update -qq - - if test $CC = gcc; then sudo apt-get install --yes --force-yes gcc-4.7 g++-4.7; fi - - if test $CC = gcc; then sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.7 20; fi - - if test $CC = gcc; then sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.7 20; fi - - if test $CC = gcc; then sudo update-alternatives --config gcc; fi - - if test $CC = gcc; then sudo update-alternatives --config g++; fi - - sudo apt-get install --yes --force-yes cmake cmake-data - -script: ./scripts/travis.sh diff --git a/lib/entityx/Android.mk b/lib/entityx/Android.mk deleted file mode 100644 index df86427..0000000 --- a/lib/entityx/Android.mk +++ /dev/null @@ -1,19 +0,0 @@ -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_MODULE := entityx - -LOCAL_MODULE_FILENAME := libentityx - -LOCAL_SRC_FILES := \ -entityx/Entity.cc \ -entityx/Event.cc \ -entityx/System.cc \ -entityx/help/Pool.cc \ -entityx/help/Timer.cc \ - - -LOCAL_C_INCLUDES := $(LOCAL_PATH) - -include $(BUILD_STATIC_LIBRARY) diff --git a/lib/entityx/CHANGES.md b/lib/entityx/CHANGES.md deleted file mode 100644 index 1fcb597..0000000 --- a/lib/entityx/CHANGES.md +++ /dev/null @@ -1,45 +0,0 @@ -# Change Log - -## 2014-03-02 - 1.0.0alpha1 - Cache coherence + breaking changes - -EntityX has switched to a more cache-friendly memory layout for components. This is achieved by requiring the use of `assign<Component>(arg0, arg1, ...)` and removing `assign(component)`. This allows EntityX to explicitly control the layout of components. The current layout algorithm reserves space for components in chunks (8192 by default). - -This change also necessitated a move away from the use of `shared_ptr<>` for components, which I had never been that pleased with anyway. Replacing it is a very lightweight `ComponentHandle<C>` smart pointer. This checks for validity of the entity associated with the component, and validity of the component itself. It also allows future iterations of EntityX to do even more interesting things with memory layout if desirable. - - -## 2014-02-13 - Support for Visual C++ - -[Jarrett Chisholm](https://github.com/jarrettchisholm) has added conditional compilation support for VC++ and fixed some issues that prevented compilation, so EntityX now fully supports Visual C++! - -You will need at least [Visual Studio 2013](http://www.microsoft.com/en-ca/download/details.aspx?id=40787) with [Update 1](http://www.microsoft.com/en-us/download/details.aspx?id=41650) and [Update 2 CTP](http://www.microsoft.com/en-us/download/details.aspx?id=41699) installed. The usual CMake installation instructions should "just work" and correctly provide VC++ support. - -## 2013-10-29 [no-boost branch] - Removed boost dependency for everything except python integration. - -This branch requires C++11 support and has removed all the non-boost::python dependecies, reducing the overhead of running entityx. - -## 2013-08-22 - Remove `boost::signal` and switch to `Simple::Signal`. - -According to the [benchmarks](http://timj.testbit.eu/2013/cpp11-signal-system-performance/) Simple::Signal is an order of magnitude faster than `boost::signal`. Additionally, `boost::signal` is now deprecated in favor of `boost::signal2`, which is not supported on versions of Boost on a number of platforms. - -This is an implementation detail and should not affect EntityX users at all. - -## 2013-08-18 - Destroying an entity invalidates all other references - -Previously, `Entity::Id` was a simple integer index (slot) into vectors in the `EntityManager`. EntityX also maintains a list of deleted entity slots that are reused when new entities are created. This reduces the size and frequency of vector reallocation. The downside though, was that if a slot was reused, entity IDs referencing the entity before reallocation would be invalidated on reuse. - -Each slot now also has a version number and a "valid" bit associated with it. When an entity is allocated the version is incremented and the valid bit set. When an entity is destroyed, the valid bit is cleared. `Entity::Id` now contains all of this information and can correctly determine if an ID is still valid across destroy/create. - -## 2013-08-17 - Python scripting, and a more robust build system - -Two big changes in this release: - -1. Python scripting support (alpha). - - Bridges the EntityX entity-component system into Python. - - Components and entities can both be defined in Python. - - Systems must still be defined in C++, for performance reasons. - - Note that there is one major design difference between the Python ECS model and the C++ model: entities in Python can receive and handle events. - - See the [README](https://github.com/alecthomas/entityx/blob/master/entityx/python/README.md) for help, and the [C++](https://github.com/alecthomas/entityx/blob/master/entityx/python/PythonSystem_test.cc) and [Python](https://github.com/alecthomas/entityx/tree/master/entityx/python/entityx/tests) test source for more examples. - -2. Made the build system much more robust, including automatic feature selection with manual override. diff --git a/lib/entityx/CMakeLists.txt b/lib/entityx/CMakeLists.txt deleted file mode 100644 index 8a2b5d1..0000000 --- a/lib/entityx/CMakeLists.txt +++ /dev/null @@ -1,206 +0,0 @@ -cmake_minimum_required(VERSION 3.1) -set(ENTITYX_MAJOR_VERSION 1) -set(ENTITYX_MINOR_VERSION 1) -set(ENTITYX_PATCH_VERSION 2) -set(ENTITYX_VERSION ${ENTITYX_MAJOR_VERSION}.${ENTITYX_MINOR_VERSION}.${ENTITYX_PATCH_VERSION}) -set(CMAKE_CXX_EXTENSIONS OFF) - -project(EntityX) - -message(STATUS "EntityX version ${ENTITYX_VERSION}") - -if(NOT DEFINED CMAKE_MACOSX_RPATH) - set(CMAKE_MACOSX_RPATH 0) -endif() - - -include_directories(${CMAKE_CURRENT_LIST_DIR}) - -set_property(GLOBAL PROPERTY USE_FOLDERS ON) - -set(ENTITYX_BUILD_TESTING true CACHE BOOL "Enable building of tests.") -set(ENTITYX_RUN_BENCHMARKS false CACHE BOOL "Run benchmarks (in conjunction with -DENTITYX_BUILD_TESTING=1).") -set(ENTITYX_MAX_COMPONENTS 64 CACHE STRING "Set the maximum number of components.") -set(ENTITYX_DT_TYPE double CACHE STRING "The type used for delta time in EntityX update methods.") -set(ENTITYX_BUILD_SHARED true CACHE BOOL "Build shared libraries?") - -include(${CMAKE_ROOT}/Modules/CheckIncludeFile.cmake) -include(CheckCXXSourceCompiles) - -# Default compiler args -if (CMAKE_CXX_COMPILER_ID MATCHES "(GNU|.*Clang)") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic -Werror -Wall -Wextra -Wno-unused-parameter -Wno-error=unused-variable -Wno-error=sign-compare") - set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") - set(CMAKE_CXX_FLAGS_MINSIZEREL "-g -Os -DNDEBUG") - set(CMAKE_CXX_FLAGS_RELEASE "-g -O2 -DNDEBUG") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g") -elseif(CMAKE_CXX_COMPILER_ID STREQUAL 'MSVC') - # /Zi - Produces a program database (PDB) that contains type information and symbolic debugging information for use with the debugger. - # /FS - Allows multiple cl.exe processes to write to the same .pdb file - # /DEBUG - Enable debug during linking - # /Od - Disables optimization - set(CMAKE_CXX_FLAGS_DEBUG "/Zi /FS /DEBUG /Od /MDd") - # /Ox - Full optimization - set(CMAKE_CXX_FLAGS_RELEASE "/Ox -DNDEBUG") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/Ox /Zi /FS /DEBUG") -endif() - -# if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") -# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weverything -Wno-c++98-compat -Wno-shadow -Wno-padded -Wno-missing-noreturn -Wno-global-constructors") -# endif() - -# Library installation directory -if(NOT DEFINED CMAKE_INSTALL_LIBDIR) - set(CMAKE_INSTALL_LIBDIR lib) -endif(NOT DEFINED CMAKE_INSTALL_LIBDIR) -set(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) - -set(OLD_CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") -if ((MAKE_CXX_COMPILER_ID STREQUAL "GNU") OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") -endif() -check_cxx_source_compiles( -" -#include <memory> - -int main() { - std::shared_ptr<int>(); -} -" -ENTITYX_HAVE_CXX11_STDLIB -) - -if (NOT ENTITYX_HAVE_CXX11_STDLIB) - message(STATUS "-- Not using -stdlib=libc++ (test failed to build)") - set(CMAKE_CXX_FLAGS "${OLD_CMAKE_CXX_FLAGS}") -else () - message(STATUS "-- Using -stdlib=libc++") -endif () - - -# Misc features -check_include_file("stdint.h" HAVE_STDINT_H) - -macro(require FEATURE_NAME MESSAGE_STRING) - if (NOT ${${FEATURE_NAME}}) - message(FATAL_ERROR "${MESSAGE_STRING} required -- ${${FEATURE_NAME}}") - else() - message(STATUS "-- ${MESSAGE_STRING} found") - endif() -endmacro(require) - -macro(create_test TARGET_NAME SOURCE DEPENDENCIES) - add_executable(${TARGET_NAME} ${SOURCE}) - set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "entityx/tests") - target_link_libraries( - ${TARGET_NAME} - ${DEPENDENCIES} - ${ARGN} - ) - - # Special case for benchmark tests - if (${TARGET_NAME} MATCHES .*benchmark.*) - if(ENTITYX_RUN_BENCHMARKS) - add_test(${TARGET_NAME} ${TARGET_NAME}) - endif() - else() - add_test(${TARGET_NAME} ${TARGET_NAME}) - endif() -endmacro() - -if (NOT CMAKE_BUILD_TYPE) - message(STATUS "-- Defaulting to release build (use -DCMAKE_BUILD_TYPE:STRING=Debug for debug build)") - set(CMAKE_BUILD_TYPE "Release") -endif() - -message(STATUS "-- Checking misc features") -require(HAVE_STDINT_H "stdint.h") - -# Things to install - - -set(sources entityx/System.cc entityx/Event.cc entityx/Entity.cc entityx/help/Timer.cc entityx/help/Pool.cc) - -if (ENTITYX_BUILD_SHARED) - message(STATUS "-- Building shared libraries (-DENTITYX_BUILD_SHARED=0 to only build static libraries)") - add_library(entityx SHARED ${sources}) - - set_target_properties(entityx PROPERTIES - OUTPUT_NAME entityx - DEBUG_POSTFIX -d - VERSION ${ENTITYX_VERSION} - SOVERSION ${ENTITYX_MAJOR_VERSION} - FOLDER entityx) - set(install_libs entityx) - set_property(TARGET entityx APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES - $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>) -else() - add_library(entityx STATIC ${sources}) - set_target_properties(entityx PROPERTIES DEBUG_POSTFIX -d FOLDER entityx) - set(install_libs entityx) - set_property(TARGET entityx APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES - $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>) -endif (ENTITYX_BUILD_SHARED) - -# Make sure C++11 features are available -target_compile_features(entityx PUBLIC cxx_auto_type) -target_compile_features(entityx PUBLIC cxx_nullptr) -target_compile_features(entityx PUBLIC cxx_static_assert) -target_compile_features(entityx PUBLIC cxx_decltype) -target_compile_features(entityx PUBLIC cxx_constexpr) -target_compile_features(entityx PUBLIC cxx_sizeof_member) -target_compile_features(entityx PUBLIC cxx_variadic_templates) -target_compile_features(entityx PUBLIC cxx_rvalue_references) -target_compile_features(entityx PUBLIC cxx_long_long_type) -target_compile_features(entityx PUBLIC cxx_lambdas) -target_compile_features(entityx PUBLIC cxx_func_identifier) - -if (ENTITYX_BUILD_TESTING) - enable_testing() - create_test(pool_test entityx/help/Pool_test.cc ${install_libs}) - create_test(entity_test entityx/Entity_test.cc ${install_libs}) - create_test(event_test entityx/Event_test.cc ${install_libs}) - create_test(system_test entityx/System_test.cc ${install_libs}) - create_test(tags_component_test entityx/tags/TagsComponent_test.cc ${install_libs}) - create_test(dependencies_test entityx/deps/Dependencies_test.cc ${install_libs}) - create_test(benchmarks_test entityx/Benchmarks_test.cc ${install_libs}) - if (ENTITYX_RUN_BENCHMARKS) - message(STATUS "-- Running benchmarks") - else () - message(STATUS "-- Not running benchmarks (use -DENTITYX_RUN_BENCHMARKS=1 to enable)") - endif () -endif (ENTITYX_BUILD_TESTING) - - -configure_file( - ${CMAKE_CURRENT_SOURCE_DIR}/entityx/config.h.in - ${CMAKE_CURRENT_SOURCE_DIR}/entityx/config.h -) - - -if (NOT WINDOWS OR CYGWIN) - set(entityx_libs -lentityx) - - configure_file( - ${CMAKE_CURRENT_SOURCE_DIR}/entityx.pc.in - ${CMAKE_CURRENT_BINARY_DIR}/entityx.pc - ) - - install( - FILES ${CMAKE_CURRENT_BINARY_DIR}/entityx.pc - DESTINATION "${libdir}/pkgconfig" - ) -endif() - -install( - DIRECTORY "entityx" - DESTINATION "include" - FILES_MATCHING PATTERN "*.h" - ) - -install( - TARGETS ${install_libs} - LIBRARY DESTINATION "${libdir}" - ARCHIVE DESTINATION "${libdir}" - RUNTIME DESTINATION "bin" - ) diff --git a/lib/entityx/COPYING b/lib/entityx/COPYING deleted file mode 100644 index 1852bbf..0000000 --- a/lib/entityx/COPYING +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (C) 2012 Alec Thomas - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/lib/entityx/Doxyfile b/lib/entityx/Doxyfile deleted file mode 100644 index d115462..0000000 --- a/lib/entityx/Doxyfile +++ /dev/null @@ -1,1896 +0,0 @@ -# Doxyfile 1.8.4 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project. -# -# All text after a double hash (##) is considered a comment and is placed -# in front of the TAG it is preceding . -# All text after a hash (#) is considered a comment and will be ignored. -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" "). - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or sequence of words) that should -# identify the project. Note that if you do not use Doxywizard you need -# to put quotes around the project name if it contains spaces. - -PROJECT_NAME = "EntityX" - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = - -# Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer -# a quick idea about the purpose of the project. Keep the description short. - -PROJECT_BRIEF = - -# With the PROJECT_LOGO tag one can specify an logo or icon that is -# included in the documentation. The maximum height of the logo should not -# exceed 55 pixels and the maximum width should not exceed 200 pixels. -# Doxygen will copy the logo to the output directory. - -PROJECT_LOGO = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Latvian, Lithuanian, Norwegian, Macedonian, -# Persian, Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, -# Slovak, Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = YES - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. Note that you specify absolute paths here, but also -# relative paths, which will be relative from the directory where doxygen is -# started. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful if your file system -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) - -JAVADOC_AUTOBRIEF = YES - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 4 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding -# "class=itcl::class" will allow you to use the command class in the -# itcl::class meaning. - -TCL_SUBST = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given -# extension. Doxygen has a built-in mapping, but you can override or extend it -# using this tag. The format is ext=language, where ext is a file extension, -# and language is one of the parsers supported by doxygen: IDL, Java, -# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, -# C++. For instance to make doxygen treat .inc files as Fortran files (default -# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note -# that for custom extensions you also need to set FILE_PATTERNS otherwise the -# files are not read by doxygen. - -EXTENSION_MAPPING = - -# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all -# comments according to the Markdown format, which allows for more readable -# documentation. See http://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you -# can mix doxygen, HTML, and XML commands with Markdown formatting. -# Disable only in case of backward compatibilities issues. - -MARKDOWN_SUPPORT = YES - -# When enabled doxygen tries to link words that correspond to documented -# classes, or namespaces to their corresponding documentation. Such a link can -# be prevented in individual cases by by putting a % sign in front of the word -# or globally by setting AUTOLINK_SUPPORT to NO. - -AUTOLINK_SUPPORT = YES - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also makes the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate -# getter and setter methods for a property. Setting this option to YES (the -# default) will make doxygen replace the get and set methods by a property in -# the documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and -# unions are shown inside the group in which they are included (e.g. using -# @ingroup) instead of on a separate page (for HTML and Man pages) or -# section (for LaTeX and RTF). - -INLINE_GROUPED_CLASSES = NO - -# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and -# unions with only public data fields or simple typedef fields will be shown -# inline in the documentation of the scope in which they are defined (i.e. file, -# namespace, or group documentation), provided this scope is documented. If set -# to NO (the default), structs, classes, and unions are shown on a separate -# page (for HTML and Man pages) or section (for LaTeX and RTF). - -INLINE_SIMPLE_STRUCTS = NO - -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. - -TYPEDEF_HIDES_STRUCT = NO - -# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This -# cache is used to resolve symbols given their name and scope. Since this can -# be an expensive process and often the same symbol appear multiple times in -# the code, doxygen keeps a cache of pre-resolved symbols. If the cache is too -# small doxygen will become slower. If the cache is too large, memory is wasted. -# The cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid -# range is 0..9, the default is 0, corresponding to a cache size of 2^16 = 65536 -# symbols. - -LOOKUP_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal -# scope will be included in the documentation. - -EXTRACT_PACKAGE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespaces are hidden. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = NO - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen -# will list include files with double quotes in the documentation -# rather than with sharp brackets. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen -# will sort the (brief and detailed) documentation of class members so that -# constructors and destructors are listed first. If set to NO (the default) -# the constructors will appear in the respective orders defined by -# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. -# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO -# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to -# do proper type resolution of all parameters of a function it will reject a -# match between the prototype and the implementation of a member function even -# if there is only one candidate or it is obvious which candidate to choose -# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen -# will still accept a match between prototype and implementation in such cases. - -STRICT_PROTO_MATCHING = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if section-label ... \endif -# and \cond section-label ... \endcond blocks. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or macro consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and macros in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command <command> <input-file>, where <command> is the value of -# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. To create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. -# You can optionally specify a file name after the option, if omitted -# DoxygenLayout.xml will be used as the name of the layout file. - -LAYOUT_FILE = - -# The CITE_BIB_FILES tag can be used to specify one or more bib files -# containing the references data. This must be a list of .bib files. The -# .bib extension is automatically appended if omitted. Using this command -# requires the bibtex tool to be installed. See also -# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style -# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this -# feature you need bibtex and perl available in the search path. Do not use -# file names with spaces, bibtex cannot handle them. - -CITE_BIB_FILES = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# The WARN_NO_PARAMDOC option can be enabled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = entityx README.md entityx/python/README.md - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh -# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py -# *.f90 *.f *.for *.vhd *.vhdl - -FILE_PATTERNS = *.h - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should be -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. -# Note that relative paths are relative to the directory from which doxygen is -# run. - -EXCLUDE = *_test* - -# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or -# directories that are symbolic links (a Unix file system feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command <filter> <input-file>, where <filter> -# is the value of the INPUT_FILTER tag, and <input-file> is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be ignored. -# Note that the filter must not add or remove lines; it is applied before the -# code is scanned, but not when the output code is generated. If lines are added -# or removed, the anchors will not be placed correctly. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty or if -# non of the patterns match the file name, INPUT_FILTER is applied. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) -# and it is also possible to disable source filtering for a specific pattern -# using *.ext= (so without naming a filter). This option only has effect when -# FILTER_SOURCE_FILES is enabled. - -FILTER_SOURCE_PATTERNS = - -# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that -# is part of the input, its contents will be placed on the main page -# (index.html). This can be useful if you have a project on for instance GitHub -# and want reuse the introduction page also for the doxygen output. - -USE_MDFILE_AS_MAINPAGE = README.md - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C, C++ and Fortran comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. - -REFERENCES_LINK_SOURCE = YES - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = YES - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. Note that when using a custom header you are responsible -# for the proper inclusion of any scripts and style sheets that doxygen -# needs, which is dependent on the configuration options used. -# It is advised to generate a default header using "doxygen -w html -# header.html footer.html stylesheet.css YourConfigFile" and then modify -# that header. Note that the header is subject to change so you typically -# have to redo this when upgrading to a newer version of doxygen or when -# changing the value of configuration settings such as GENERATE_TREEVIEW! - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If left blank doxygen will -# generate a default style sheet. Note that it is recommended to use -# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this -# tag will in the future become obsolete. - -HTML_STYLESHEET = - -# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional -# user-defined cascading style sheet that is included after the standard -# style sheets created by doxygen. Using this option one can overrule -# certain style aspects. This is preferred over using HTML_STYLESHEET -# since it does not replace the standard style sheet and is therefor more -# robust against future updates. Doxygen will copy the style sheet file to -# the output directory. - -HTML_EXTRA_STYLESHEET = - -# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or -# other source files which should be copied to the HTML output directory. Note -# that these files will be copied to the base HTML output directory. Use the -# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that -# the files will be copied as-is; there are no commands or markers available. - -HTML_EXTRA_FILES = - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. -# Doxygen will adjust the colors in the style sheet and background images -# according to this color. Hue is specified as an angle on a colorwheel, -# see http://en.wikipedia.org/wiki/Hue for more information. -# For instance the value 0 represents red, 60 is yellow, 120 is green, -# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. -# The allowed range is 0 to 359. - -HTML_COLORSTYLE_HUE = 220 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of -# the colors in the HTML output. For a value of 0 the output will use -# grayscales only. A value of 255 will produce the most vivid colors. - -HTML_COLORSTYLE_SAT = 100 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to -# the luminance component of the colors in the HTML output. Values below -# 100 gradually make the output lighter, whereas values above 100 make -# the output darker. The value divided by 100 is the actual gamma applied, -# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, -# and 100 does not change the gamma. - -HTML_COLORSTYLE_GAMMA = 80 - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting -# this to NO can help when comparing the output of multiple runs. - -HTML_TIMESTAMP = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. - -HTML_DYNAMIC_SECTIONS = NO - -# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of -# entries shown in the various tree structured indices initially; the user -# can expand and collapse entries dynamically later on. Doxygen will expand -# the tree to such a level that at most the specified number of entries are -# visible (unless a fully collapsed tree already exceeds this amount). -# So setting the number of entries 1 will produce a full collapsed tree by -# default. 0 is a special value representing an infinite number of entries -# and will result in a full expanded tree by default. - -HTML_INDEX_NUM_ENTRIES = 100 - -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. - -GENERATE_DOCSET = NO - -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. - -DOCSET_BUNDLE_ID = org.swapoff.EntityX - -# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely -# identify the documentation publisher. This should be a reverse domain-name -# style string, e.g. com.mycompany.MyDocSet.documentation. - -DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. - -DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. - -CHM_INDEX_ENCODING = - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated -# that can be used as input for Qt's qhelpgenerator to generate a -# Qt Compressed Help (.qch) of the generated HTML documentation. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders - -QHP_VIRTUAL_FOLDER = doc - -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to -# add. For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see -# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters"> -# Qt Help Project / Custom Filters</a>. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's -# filter section matches. -# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes"> -# Qt Help Project / Filter Attributes</a>. - -QHP_SECT_FILTER_ATTRS = - -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files -# will be generated, which together with the HTML files, form an Eclipse help -# plugin. To install this plugin and make it available under the help contents -# menu in Eclipse, the contents of the directory containing the HTML and XML -# files needs to be copied into the plugins directory of eclipse. The name of -# the directory within the plugins directory should be the same as -# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before -# the help appears. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have -# this name. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) -# at top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. Since the tabs have the same information as the -# navigation tree you can set this option to NO if you already set -# GENERATE_TREEVIEW to YES. - -DISABLE_INDEX = NO - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. -# Since the tree basically has the same information as the tab index you -# could consider to set DISABLE_INDEX to NO when enabling this option. - -GENERATE_TREEVIEW = NO - -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values -# (range [0,1..20]) that doxygen will group on one line in the generated HTML -# documentation. Note that a value of 0 will completely suppress the enum -# values from appearing in the overview section. - -ENUM_VALUES_PER_LINE = 4 - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open -# links to external symbols imported via tag files in a separate window. - -EXT_LINKS_IN_WINDOW = NO - -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are -# not supported properly for IE 6.0, but are supported on all modern browsers. -# Note that when changing this option you need to delete any form_*.png files -# in the HTML output before the changes have effect. - -FORMULA_TRANSPARENT = YES - -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax -# (see http://www.mathjax.org) which uses client side Javascript for the -# rendering instead of using prerendered bitmaps. Use this if you do not -# have LaTeX installed or if you want to formulas look prettier in the HTML -# output. When enabled you may also need to install MathJax separately and -# configure the path to it using the MATHJAX_RELPATH option. - -USE_MATHJAX = NO - -# When MathJax is enabled you can set the default output format to be used for -# the MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and -# SVG. The default value is HTML-CSS, which is slower, but has the best -# compatibility. - -MATHJAX_FORMAT = HTML-CSS - -# When MathJax is enabled you need to specify the location relative to the -# HTML output directory using the MATHJAX_RELPATH option. The destination -# directory should contain the MathJax.js script. For instance, if the mathjax -# directory is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to -# the MathJax Content Delivery Network so you can quickly see the result without -# installing MathJax. -# However, it is strongly recommended to install a local -# copy of MathJax from http://www.mathjax.org before deployment. - -MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest - -# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension -# names that should be enabled during MathJax rendering. - -MATHJAX_EXTENSIONS = - -# The MATHJAX_CODEFILE tag can be used to specify a file with javascript -# pieces of code that will be used on startup of the MathJax code. - -MATHJAX_CODEFILE = - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box -# for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using -# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets -# (GENERATE_DOCSET) there is already a search function so this one should -# typically be disabled. For large projects the javascript based search engine -# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. - -SEARCHENGINE = YES - -# When the SERVER_BASED_SEARCH tag is enabled the search engine will be -# implemented using a web server instead of a web client using Javascript. -# There are two flavours of web server based search depending on the -# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for -# searching and an index file used by the script. When EXTERNAL_SEARCH is -# enabled the indexing and searching needs to be provided by external tools. -# See the manual for details. - -SERVER_BASED_SEARCH = NO - -# When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP -# script for searching. Instead the search results are written to an XML file -# which needs to be processed by an external indexer. Doxygen will invoke an -# external search engine pointed to by the SEARCHENGINE_URL option to obtain -# the search results. Doxygen ships with an example indexer (doxyindexer) and -# search engine (doxysearch.cgi) which are based on the open source search -# engine library Xapian. See the manual for configuration details. - -EXTERNAL_SEARCH = NO - -# The SEARCHENGINE_URL should point to a search engine hosted by a web server -# which will returned the search results when EXTERNAL_SEARCH is enabled. -# Doxygen ships with an example search engine (doxysearch) which is based on -# the open source search engine library Xapian. See the manual for configuration -# details. - -SEARCHENGINE_URL = - -# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed -# search data is written to a file for indexing by an external tool. With the -# SEARCHDATA_FILE tag the name of this file can be specified. - -SEARCHDATA_FILE = searchdata.xml - -# When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the -# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is -# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple -# projects and redirect the results back to the right project. - -EXTERNAL_SEARCH_ID = - -# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen -# projects other than the one defined by this configuration file, but that are -# all added to the same external search index. Each project needs to have a -# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id -# of to a relative location where the documentation can be found. -# The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ... - -EXTRA_SEARCH_MAPPINGS = - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. -# Note that when enabling USE_PDFLATEX this option is only used for -# generating bitmaps for formulas in the HTML output, but not in the -# Makefile that is written to the output directory. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, letter, legal and -# executive. If left blank a4 will be used. - -PAPER_TYPE = a4 - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for -# the generated latex document. The footer should contain everything after -# the last chapter. If it is left blank doxygen will generate a -# standard footer. Notice: only use this tag if you know what you are doing! - -LATEX_FOOTER = - -# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images -# or other source files which should be copied to the LaTeX output directory. -# Note that the files will be copied as-is; there are no commands or markers -# available. - -LATEX_EXTRA_FILES = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = YES - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = YES - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -# If LATEX_SOURCE_CODE is set to YES then doxygen will include -# source code with syntax highlighting in the LaTeX output. -# Note that which sources are shown also depends on other settings -# such as SOURCE_BROWSER. - -LATEX_SOURCE_CODE = NO - -# The LATEX_BIB_STYLE tag can be used to specify the style to use for the -# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See -# http://en.wikipedia.org/wiki/BibTeX for more info. - -LATEX_BIB_STYLE = plain - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load style sheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options related to the DOCBOOK output -#--------------------------------------------------------------------------- - -# If the GENERATE_DOCBOOK tag is set to YES Doxygen will generate DOCBOOK files -# that can be used to generate PDF. - -GENERATE_DOCBOOK = NO - -# The DOCBOOK_OUTPUT tag is used to specify where the DOCBOOK pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in -# front of it. If left blank docbook will be used as the default path. - -DOCBOOK_OUTPUT = docbook - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. -# This is useful -# if you want to understand what is going on. -# On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# pointed to by INCLUDE_PATH will be searched when a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition that -# overrules the definition found in the source code. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all references to function-like macros -# that are alone on a line, have an all uppercase name, and do not end with a -# semicolon, because these will confuse the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. For each -# tag file the location of the external documentation should be added. The -# format of a tag file without this location is as follows: -# -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths -# or URLs. Note that each tag file must have a unique name (where the name does -# NOT include the path). If a tag file is not located in the directory in which -# doxygen is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed -# in the related pages index. If set to NO, only the current project's -# pages will be listed. - -EXTERNAL_PAGES = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option also works with HAVE_DOT disabled, but it is recommended to -# install and use dot, since it yields more powerful graphs. - -CLASS_DIAGRAMS = YES - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see -# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = NO - -# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is -# allowed to run in parallel. When set to 0 (the default) doxygen will -# base this on the number of processors available in the system. You can set it -# explicitly to a value larger than 0 to get control over the balance -# between CPU load and processing speed. - -DOT_NUM_THREADS = 0 - -# By default doxygen will use the Helvetica font for all dot files that -# doxygen generates. When you want a differently looking font you can specify -# the font name using DOT_FONTNAME. You need to make sure dot is able to find -# the font, which can be done by putting it in a standard location or by setting -# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the -# directory containing the font. - -DOT_FONTNAME = Helvetica - -# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. -# The default size is 10pt. - -DOT_FONTSIZE = 10 - -# By default doxygen will tell dot to use the Helvetica font. -# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to -# set the path where dot can find it. - -DOT_FONTPATH = - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = NO - -# If the UML_LOOK tag is enabled, the fields and methods are shown inside -# the class node. If there are many fields or methods and many nodes the -# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS -# threshold limits the number of items for each type to make the size more -# manageable. Set this to 0 for no limit. Note that the threshold may be -# exceeded by 50% before the limit is enforced. - -UML_LIMIT_NUM_FIELDS = 10 - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = NO - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH and HAVE_DOT options are set to YES then -# doxygen will generate a call dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable call graphs -# for selected functions only using the \callgraph command. - -CALL_GRAPH = NO - -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -# doxygen will generate a caller dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable caller -# graphs for selected functions only using the \callergraph command. - -CALLER_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will generate a graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are svg, png, jpg, or gif. -# If left blank png will be used. If you choose svg you need to set -# HTML_FILE_EXTENSION to xhtml in order to make the SVG files -# visible in IE 9+ (other browsers do not have this requirement). - -DOT_IMAGE_FORMAT = png - -# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to -# enable generation of interactive SVG images that allow zooming and panning. -# Note that this requires a modern browser other than Internet Explorer. -# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you -# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files -# visible. Older versions of IE do not have SVG support. - -INTERACTIVE_SVG = NO - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The MSCFILE_DIRS tag can be used to specify one or more directories that -# contain msc files that are included in the documentation (see the -# \mscfile command). - -MSCFILE_DIRS = - -# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the -# number of direct children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. - -MAX_DOT_GRAPH_DEPTH = 0 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not -# seem to support this out of the box. Warning: Depending on the platform used, -# enabling this option may lead to badly anti-aliased labels on the edges of -# a graph (i.e. they become hard to read). - -DOT_TRANSPARENT = NO - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = NO - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES - -#GENERATE_DOCSET = YES -#DISABLE_INDEX = YES -#SEARCHENGINE = NO -#GENERATE_TREEVIEW = NO -# diff --git a/lib/entityx/README.md b/lib/entityx/README.md deleted file mode 100644 index 92dd3b6..0000000 --- a/lib/entityx/README.md +++ /dev/null @@ -1,419 +0,0 @@ -# EntityX - A fast, type-safe C++ Entity Component System -[](https://travis-ci.org/alecthomas/entityx) [](https://ci.appveyor.com/project/alecthomas/entityx/branch/master) [](https://gitter.im/alecthomas/Lobby) - - -***NOTE: The current stable release 1.0.0 breaks backwards compataibility with < 1.0.0. See the [change log](CHANGES.md) for details.*** - -Entity Component Systems (ECS) are a form of decomposition that completely decouples entity logic and data from the entity "objects" themselves. The [Evolve your Hierarchy](http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/) article provides a solid overview of EC systems and why you should use them. - -EntityX is an EC system that uses C++11 features to provide type-safe component management, event delivery, etc. It was built during the creation of a 2D space shooter. - -## Downloading - -You can acquire stable releases [here](https://github.com/alecthomas/entityx/releases). - -Alternatively, you can check out the current development version with: - -``` -git clone https://github.com/alecthomas/entityx.git -``` - -See [below](#installation) for installation instructions. - -## Contact - -Feel free to jump on my [Gitter channel](https://gitter.im/alecthomas/Lobby) if you have any questions/comments. This is a single channel for all of my projects, so please mention you're asking about EntityX to avoid (my) confusion. - -You can also contact me directly via [email](mailto:alec@swapoff.org) or [Twitter](https://twitter.com/alecthomas). - -## Benchmarks / Comparisons - -EntityX includes its own benchmarks, but @abeimler has created [a benchmark suite](https://github.com/abeimler/ecs_benchmark/blob/master/doc/BenchmarkResultDetails2.md) testing up to 2M entities in EntityX, the EntityX compile-time branch, Anax, and Artemis C++. - -## Recent Notable Changes - -- 2014-03-02 - (1.0.0alpha1) Switch to using cache friendly component storage (big breaking change). Also eradicated use of `std::shared_ptr` for components. -- 2014-02-13 - Visual C++ support thanks to [Jarrett Chisholm](https://github.com/jarrettchisholm)! -- 2013-10-29 - Boost has been removed as a primary dependency for builds not using python. -- 2013-08-21 - Remove dependency on `boost::signal` and switch to embedded [Simple::Signal](http://timj.testbit.eu/2013/cpp11-signal-system-performance/). -- 2013-08-18 - Destroying an entity invalidates all other references -- 2013-08-17 - Python scripting, and a more robust build system - -See the [ChangeLog](https://github.com/alecthomas/entityx/blob/master/CHANGES.md) for details. - -## EntityX extensions and example applications - -- [Will Usher](https://github.com/Twinklebear) has also written an [Asteroids clone](https://github.com/Twinklebear/asteroids). -- [Roc Solid Productions](https://github.com/RocSolidProductions) have written a [space shooter](https://github.com/RocSolidProductions/Space-Shooter)! -- Giovani Milanez's first [game](https://github.com/giovani-milanez/SpaceTD). -- [A game](https://github.com/ggc87/BattleCity2014) using Ogre3D and EntityX. - -**DEPRECATED - 0.1.x ONLY** - -- [Wu Zhenwei](https://github.com/acaly) has written [Lua bindings](https://github.com/acaly/entityx_lua) for EntityX, allowing entity logic to be extended through Lua scripts. -- [Python bindings](https://github.com/alecthomas/entityx_python) allowing entity logic to be extended through Python scripts. -- [Rodrigo Setti](https://github.com/rodrigosetti) has written an OpenGL [Asteroids clone](https://github.com/rodrigosetti/azteroids) which uses EntityX. - -## Example - -An SFML2 example application is [available](/examples/example.cc) that shows most of EntityX's concepts. It spawns random circles on a 2D plane moving in random directions. If two circles collide they will explode and emit particles. All circles and particles are entities. - -It illustrates: - -- Separation of data via components. -- Separation of logic via systems. -- Use of events (colliding bodies trigger a CollisionEvent). - -Compile with: - - c++ -O3 -std=c++11 -Wall -lsfml-system -lsfml-window -lsfml-graphics -lentityx example.cc -o example - -## Overview - -In EntityX data associated with an entity is called a `entityx::Component`. `Systems` encapsulate logic and can use as many component types as necessary. An `entityx::EventManager` allows systems to interact without being tightly coupled. Finally, a `Manager` object ties all of the systems together for convenience. - -As an example, a physics system might need *position* and *mass* data, while a collision system might only need *position* - the data would be logically separated into two components, but usable by any system. The physics system might emit *collision* events whenever two entities collide. - -## Tutorial - -Following is some skeleton code that implements `Position` and `Direction` components, a `MovementSystem` using these data components, and a `CollisionSystem` that emits `Collision` events when two entities collide. - -To start with, add the following line to your source file: - -```c++ -#include "entityx/entityx.h" -``` - -### Entities - -An `entityx::Entity` is a convenience class wrapping an opaque `uint64_t` value allocated by the `entityx::EntityManager`. Each entity has a set of components associated with it that can be added, queried or retrieved directly. - -Creating an entity is as simple as: - -```c++ -#include <entityx/entityx.h> - -entityx::EntityX ex; - -entityx::Entity entity = ex.entities.create(); -``` - -And destroying an entity is done with: - -```c++ -entity.destroy(); -``` - -#### Implementation details - -- Each `entityx::Entity` is a convenience class wrapping an `entityx::Entity::Id`. -- An `entityx::Entity` handle can be invalidated with `invalidate()`. This does not affect the underlying entity. -- When an entity is destroyed the manager adds its ID to a free list and invalidates the `entityx::Entity` handle. -- When an entity is created IDs are recycled from the free list first, before allocating new ones. -- An `entityx::Entity` ID contains an index and a version. When an entity is destroyed, the version associated with the index is incremented, invalidating all previous entities referencing the previous ID. -- To improve cache coherence, components are constructed in contiguous memory ranges by using `entityx::EntityManager::assign<C>(id, ...)`. - -### Components (entity data) - -The general idea with the EntityX interpretation of ECS is to have as little logic in components as possible. All logic should be contained in Systems. - -To that end Components are typically [POD types](http://en.wikipedia.org/wiki/Plain_Old_Data_Structures) consisting of self-contained sets of related data. Components can be any user defined struct/class. - -#### Creating components - -As an example, position and direction information might be represented as: - -```c++ -struct Position { - Position(float x = 0.0f, float y = 0.0f) : x(x), y(y) {} - - float x, y; -}; - -struct Direction { - Direction(float x = 0.0f, float y = 0.0f) : x(x), y(y) {} - - float x, y; -}; -``` - -#### Assigning components to entities - -To associate a component with a previously created entity call ``entityx::Entity::assign<C>()`` with the component type, and any component constructor arguments: - -```c++ -// Assign a Position with x=1.0f and y=2.0f to "entity" -entity.assign<Position>(1.0f, 2.0f); -``` - -#### Querying entities and their components - -To query all entities with a set of components assigned you can use two -methods. Both methods will return only those entities that have *all* of the -specified components associated with them. - -`entityx::EntityManager::each(f)` provides functional-style iteration over -entity components: - -```c++ -entities.each<Position, Direction>([](Entity entity, Position &position, Direction &direction) { - // Do things with entity, position and direction. -}); -``` - - -For iterator-style traversal of components, use -``entityx::EntityManager::entities_with_components()``: - -```c++ -ComponentHandle<Position> position; -ComponentHandle<Direction> direction; -for (Entity entity : entities.entities_with_components(position, direction)) { - // Do things with entity, position and direction. -} -``` - -To retrieve a component associated with an entity use ``entityx::Entity::component<C>()``: - -```c++ -ComponentHandle<Position> position = entity.component<Position>(); -if (position) { - // Do stuff with position -} -``` - -#### Component dependencies - -In the case where a component has dependencies on other components, a helper class exists that will automatically create these dependencies. - -eg. The following will also add `Position` and `Direction` components when a `Physics` component is added to an entity. - -```c++ -#include "entityx/deps/Dependencies.h" - -system_manager->add<entityx::deps::Dependency<Physics, Position, Direction>>(); -``` - -#### Implementation notes - -- Components must provide a no-argument constructor. -- The default implementation can handle up to 64 components in total. This can be extended by changing the `entityx::EntityManager::MAX_COMPONENTS` constant. -- Each type of component is allocated in (mostly) contiguous blocks to improve cache coherency. - -### Systems (implementing behavior) - -Systems implement behavior using one or more components. Implementations are subclasses of `System<T>` and *must* implement the `update()` method, as shown below. - -A basic movement system might be implemented with something like the following: - -```c++ -struct MovementSystem : public System<MovementSystem> { - void update(entityx::EntityManager &es, entityx::EventManager &events, TimeDelta dt) override { - es.each<Position, Direction>([dt](Entity entity, Position &position, Direction &direction) { - position.x += direction.x * dt; - position.y += direction.y * dt; - }); - }; -}; -``` - -### Events (communicating between systems) - -Events are objects emitted by systems, typically when some condition is met. Listeners subscribe to an event type and will receive a callback for each event object emitted. An ``entityx::EventManager`` coordinates subscription and delivery of events between subscribers and emitters. Typically subscribers will be other systems, but need not be. -Events are not part of the original ECS pattern, but they are an efficient alternative to component flags for sending infrequent data. - -As an example, we might want to implement a very basic collision system using our ``Position`` data from above. - -#### Creating event types - -First, we define the event type, which for our example is simply the two entities that collided: - -```c++ -struct Collision { - Collision(entityx::Entity left, entityx::Entity right) : left(left), right(right) {} - - entityx::Entity left, right; -}; -``` - -#### Emitting events - -Next we implement our collision system, which emits ``Collision`` objects via an ``entityx::EventManager`` instance whenever two entities collide. - -```c++ -class CollisionSystem : public System<CollisionSystem> { - public: - void update(entityx::EntityManager &es, entityx::EventManager &events, TimeDelta dt) override { - ComponentHandle<Position> left_position, right_position; - for (Entity left_entity : es.entities_with_components(left_position)) { - for (Entity right_entity : es.entities_with_components(right_position)) { - if (collide(left_position, right_position)) { - events.emit<Collision>(left_entity, right_entity); - } - } - } - }; -}; -``` - -#### Subscribing to events - -Objects interested in receiving collision information can subscribe to ``Collision`` events by first subclassing the CRTP class ``Receiver<T>``: - -```c++ -struct DebugSystem : public System<DebugSystem>, public Receiver<DebugSystem> { - void configure(entityx::EventManager &event_manager) { - event_manager.subscribe<Collision>(*this); - } - - void update(entityx::EntityManager &entities, entityx::EventManager &events, TimeDelta dt) {} - - void receive(const Collision &collision) { - LOG(DEBUG) << "entities collided: " << collision.left << " and " << collision.right << endl; - } -}; -``` - -#### Builtin events - -Several events are emitted by EntityX itself: - -- `EntityCreatedEvent` - emitted when a new entityx::Entity has been created. - - `entityx::Entity entity` - Newly created entityx::Entity. -- `EntityDestroyedEvent` - emitted when an entityx::Entity is *about to be* destroyed. - - `entityx::Entity entity` - entityx::Entity about to be destroyed. -- `ComponentAddedEvent<C>` - emitted when a new component is added to an entity. - - `entityx::Entity entity` - entityx::Entity that component was added to. - - `ComponentHandle<C> component` - The component added. -- `ComponentRemovedEvent<C>` - emitted when a component is removed from an entity. - - `entityx::Entity entity` - entityx::Entity that component was removed from. - - `ComponentHandle<C> component` - The component removed. - -#### Implementation notes - -- There can be more than one subscriber for an event; each one will be called. -- Event objects are destroyed after delivery, so references should not be retained. -- A single class can receive any number of types of events by implementing a ``receive(const EventType &)`` method for each event type. -- Any class implementing `Receiver` can receive events, but typical usage is to make `System`s also be `Receiver`s. -- When an `Entity` is destroyed it will cause all of its components to be removed. This triggers `ComponentRemovedEvent`s to be triggered for each of its components. These events are triggered before the `EntityDestroyedEvent`. - -### Manager (tying it all together) - -Managing systems, components and entities can be streamlined by using the -"quick start" class `EntityX`. It simply provides pre-initialized -`EventManager`, `EntityManager` and `SystemManager` instances. - -To use it, subclass `EntityX`: - -```c++ -class Level : public EntityX { -public: - explicit Level(filename string) { - systems.add<DebugSystem>(); - systems.add<MovementSystem>(); - systems.add<CollisionSystem>(); - systems.configure(); - - level.load(filename); - - for (auto e : level.entity_data()) { - entityx::Entity entity = entities.create(); - entity.assign<Position>(rand() % 100, rand() % 100); - entity.assign<Direction>((rand() % 10) - 5, (rand() % 10) - 5); - } - } - - void update(TimeDelta dt) { - systems.update<DebugSystem>(dt); - systems.update<MovementSystem>(dt); - systems.update<CollisionSystem>(dt); - } - - Level level; -}; -``` - - -You can then step the entities explicitly inside your own game loop: - -```c++ -while (true) { - level.update(0.1); -} -``` - -## Installation - -### Arch Linux - - pacman -S entityx - -### OSX - - brew install entityx - -### Windows - -Build it manually. - -Requirements: - -* [Visual Studio 2015](https://www.visualstudio.com/en-us/downloads/visual-studio-2015-downloads-vs.aspx) or later, or a C++ compiler that supports a basic set of C++11 features (ie. Clang >= 3.1 or GCC >= 4.7). -* [CMake](http://cmake.org/) - -### Other systems - -Build it manually. - -Requirements: - -* A C++ compiler that supports a basic set of C++11 features (ie. Clang >= 3.1, GCC >= 4.7). -* [CMake](http://cmake.org/) - -### C++11 compiler and library support - -C++11 support is quite...raw. To make life more interesting, C++ support really means two things: language features supported by the compiler, and library features. EntityX tries to support the most common options, including the default C++ library for the compiler/platform, and libstdc++. - -### Installing on Ubuntu 12.04 - -On Ubuntu LTS (12.04, Precise) you will need to add some PPAs to get either clang-3.1 or gcc-4.7. Respective versions prior to these do not work. - -For gcc-4.7: - -```bash -sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test -sudo apt-get update -qq -sudo apt-get install gcc-4.7 g++-4.7 -CC=gcc-4.7 CXX=g++4.7 cmake ... -``` - -For clang-3.1 (or 3.2 or 3.3): - -```bash -sudo apt-add-repository ppa:h-rayflood/llvm -sudo apt-get update -qq -sudo apt-get install clang-3.1 -CC=clang-3.1 CXX=clang++3.1 cmake ... -``` - -### Options - -Once these dependencies are installed you should be able to build and install EntityX as below. The following options can be passed to cmake to modify how EntityX is built: - -- `-DENTITYX_RUN_BENCHMARKS=1` - In conjunction with `-DENTITYX_BUILD_TESTING=1`, also build benchmarks. -- `-DENTITYX_MAX_COMPONENTS=64` - Override the maximum number of components that can be assigned to each entity. -- `-DENTITYX_BUILD_SHARED=1` - Whether to build shared libraries (defaults to 1). -- `-DENTITYX_BUILD_TESTING=1` - Whether to build tests (defaults to 0). Run with "make && make test". -- `-DENTITYX_DT_TYPE=double` - The type used for delta time in EntityX update methods. - -Once you have selected your flags, build and install with: - -```sh -mkdir build -cd build -cmake <flags> .. -make -make install -``` - -EntityX has currently only been tested on Mac OSX (Lion and Mountain Lion), Linux Debian 12.04 and Arch Linux. Reports and patches for builds on other platforms are welcome. diff --git a/lib/entityx/appveyor.yml b/lib/entityx/appveyor.yml deleted file mode 100644 index 313ca18..0000000 --- a/lib/entityx/appveyor.yml +++ /dev/null @@ -1,10 +0,0 @@ -version: 1.0.{build} -image: Visual Studio 2015 CTP 6 -build_script: -- cmd: >- - cmake -DENTITYX_BUILD_TESTING=1 -DENTITYX_BUILD_SHARED=0 - - cmake --build . --target ALL_BUILD --config Release - - cmake --build . --target RUN_TESTS --config Release - diff --git a/lib/entityx/build/Makefile b/lib/entityx/build/Makefile deleted file mode 100644 index 9f45d7e..0000000 --- a/lib/entityx/build/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -INC = -I.. -FLG = -std=gnu++11 - -all: - g++ $(INC) $(FLG) -c ../entityx/help/Pool.cc -o Pool.o - g++ $(INC) $(FLG) -c ../entityx/help/Timer.cc -o Timer.o - g++ $(INC) $(FLG) -c ../entityx/Event.cc -o Event.o - g++ $(INC) $(FLG) -c ../entityx/Entity.cc -o Entity.o - g++ $(INC) $(FLG) -c ../entityx/System.cc -o System.o - ar rvs ../../libentityx.a *.o - diff --git a/lib/entityx/cmake/FindEntityX.cmake b/lib/entityx/cmake/FindEntityX.cmake deleted file mode 100644 index fad310d..0000000 --- a/lib/entityx/cmake/FindEntityX.cmake +++ /dev/null @@ -1,34 +0,0 @@ -# Look for a version of EntityX on the local machine -# -# By default, this will look in all common places. If EntityX is built or -# installed in a custom location, you're able to either modify the -# CMakeCache.txt file yourself or simply pass the path to CMake using either the -# environment variable `ENTITYX_ROOT` or the CMake define with the same name. - -set(ENTITYX_PATHS - ${ENTITYX_ROOT} - $ENV{ENTITYX_ROOT} - ~/Library/Frameworks - /Library/Frameworks - /usr/local - /usr - /sw - /opt/local - /opt/csw - /opt -) - -find_path(ENTITYX_INCLUDE_DIR entityx/entityx.h PATH_SUFFIXES include PATHS ${ENTITYX_PATHS}) -find_library(ENTITYX_LIBRARY NAMES entityx PATH_SUFFIXES lib PATHS ${ENTITYX_PATHS}) -find_library(ENTITYX_LIBRARY_DEBUG NAMES entityx-d PATH_SUFFIXES lib PATHS ${ENTITYX_PATHS}) - -set(ENTITYX_LIBRARIES ${ENTITYX_LIBRARY}) -set(ENTITYX_INCLUDE_DIRS ${ENTITYX_INCLUDE_DIR}) - -include(FindPackageHandleStandardArgs) - -# handle the QUIETLY and REQUIRED arguments and set ENTITYX_FOUND to TRUE if -# all listed variables are TRUE -find_package_handle_standard_args(entityx DEFAULT_MSG ENTITYX_LIBRARY ENTITYX_INCLUDE_DIR) - -mark_as_advanced(ENTITYX_INCLUDE_DIR ENTITYX_LIBRARY) diff --git a/lib/entityx/cxx11/c++11-test-__func__-N2340.cpp b/lib/entityx/cxx11/c++11-test-__func__-N2340.cpp deleted file mode 100644 index d961df8..0000000 --- a/lib/entityx/cxx11/c++11-test-__func__-N2340.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include <cstring> - -int main() -{ - if (!__func__) { return 1; } - if(std::strlen(__func__) <= 0) { return 1; } - return 0; -} diff --git a/lib/entityx/cxx11/c++11-test-auto-N2546.cpp b/lib/entityx/cxx11/c++11-test-auto-N2546.cpp deleted file mode 100644 index 948648e..0000000 --- a/lib/entityx/cxx11/c++11-test-auto-N2546.cpp +++ /dev/null @@ -1,12 +0,0 @@ - -int main() -{ - auto i = 5; - auto f = 3.14159f; - auto d = 3.14159; - bool ret = ( - (sizeof(f) < sizeof(d)) && - (sizeof(i) == sizeof(int)) - ); - return ret ? 0 : 1; -} diff --git a/lib/entityx/cxx11/c++11-test-constexpr-N2235.cpp b/lib/entityx/cxx11/c++11-test-constexpr-N2235.cpp deleted file mode 100644 index ed62451..0000000 --- a/lib/entityx/cxx11/c++11-test-constexpr-N2235.cpp +++ /dev/null @@ -1,19 +0,0 @@ -constexpr int square(int x) -{ - return x*x; -} - -constexpr int the_answer() -{ - return 42; -} - -int main() -{ - int test_arr[square(3)]; - bool ret = ( - (square(the_answer()) == 1764) && - (sizeof(test_arr)/sizeof(test_arr[0]) == 9) - ); - return ret ? 0 : 1; -} diff --git a/lib/entityx/cxx11/c++11-test-cstdint.cpp b/lib/entityx/cxx11/c++11-test-cstdint.cpp deleted file mode 100644 index 6ba852f..0000000 --- a/lib/entityx/cxx11/c++11-test-cstdint.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include <cstdint> -int main() -{ - bool test = - (sizeof(std::int8_t) == 1) && - (sizeof(std::int16_t) == 2) && - (sizeof(std::int32_t) == 4) && - (sizeof(std::int64_t) == 8); - return test ? 0 : 1; -} diff --git a/lib/entityx/cxx11/c++11-test-decltype-N2343.cpp b/lib/entityx/cxx11/c++11-test-decltype-N2343.cpp deleted file mode 100644 index 843f83a..0000000 --- a/lib/entityx/cxx11/c++11-test-decltype-N2343.cpp +++ /dev/null @@ -1,11 +0,0 @@ - -bool check_size(int i) -{ - return sizeof(int) == sizeof(decltype(i)); -} - -int main() -{ - bool ret = check_size(42); - return ret ? 0 : 1; -} diff --git a/lib/entityx/cxx11/c++11-test-lambda-N2927.cpp b/lib/entityx/cxx11/c++11-test-lambda-N2927.cpp deleted file mode 100644 index 4c33ed5..0000000 --- a/lib/entityx/cxx11/c++11-test-lambda-N2927.cpp +++ /dev/null @@ -1,5 +0,0 @@ -int main() -{ - int ret = 0; - return ([&ret]() -> int { return ret; })(); -} diff --git a/lib/entityx/cxx11/c++11-test-long_long-N1811.cpp b/lib/entityx/cxx11/c++11-test-long_long-N1811.cpp deleted file mode 100644 index 0911127..0000000 --- a/lib/entityx/cxx11/c++11-test-long_long-N1811.cpp +++ /dev/null @@ -1,7 +0,0 @@ -int main(void) -{ - long long l; - unsigned long long ul; - - return ((sizeof(l) >= 8) && (sizeof(ul) >= 8)) ? 0 : 1; -} diff --git a/lib/entityx/cxx11/c++11-test-nullptr-N2431.cpp b/lib/entityx/cxx11/c++11-test-nullptr-N2431.cpp deleted file mode 100644 index c78fac4..0000000 --- a/lib/entityx/cxx11/c++11-test-nullptr-N2431.cpp +++ /dev/null @@ -1,5 +0,0 @@ -int main() -{ - int* test = nullptr; - return test ? 1 : 0; -} diff --git a/lib/entityx/cxx11/c++11-test-nullptr-N2431_fail_compile.cpp b/lib/entityx/cxx11/c++11-test-nullptr-N2431_fail_compile.cpp deleted file mode 100644 index 7ab77a2..0000000 --- a/lib/entityx/cxx11/c++11-test-nullptr-N2431_fail_compile.cpp +++ /dev/null @@ -1,5 +0,0 @@ -int main() -{ - int i = nullptr; - return 1; -} diff --git a/lib/entityx/cxx11/c++11-test-rvalue_references-N2118.cpp b/lib/entityx/cxx11/c++11-test-rvalue_references-N2118.cpp deleted file mode 100644 index 75fb555..0000000 --- a/lib/entityx/cxx11/c++11-test-rvalue_references-N2118.cpp +++ /dev/null @@ -1,15 +0,0 @@ -int foo(int& lvalue) -{ - return 123; -} - -int foo(int&& rvalue) -{ - return 321; -} - -int main() -{ - int i = 42; - return ((foo(i) == 123) && (foo(42) == 321)) ? 0 : 1; -} diff --git a/lib/entityx/cxx11/c++11-test-sizeof_member-N2253.cpp b/lib/entityx/cxx11/c++11-test-sizeof_member-N2253.cpp deleted file mode 100644 index a55fc09..0000000 --- a/lib/entityx/cxx11/c++11-test-sizeof_member-N2253.cpp +++ /dev/null @@ -1,14 +0,0 @@ -struct foo { - char bar; - int baz; -}; - -int main(void) -{ - bool ret = ( - (sizeof(foo::bar) == 1) && - (sizeof(foo::baz) >= sizeof(foo::bar)) && - (sizeof(foo) >= sizeof(foo::bar)+sizeof(foo::baz)) - ); - return ret ? 0 : 1; -} diff --git a/lib/entityx/cxx11/c++11-test-static_assert-N1720.cpp b/lib/entityx/cxx11/c++11-test-static_assert-N1720.cpp deleted file mode 100644 index c3d74ca..0000000 --- a/lib/entityx/cxx11/c++11-test-static_assert-N1720.cpp +++ /dev/null @@ -1,5 +0,0 @@ -int main() -{ - static_assert(0 < 1, "your ordering of integers is screwed"); - return 0; -} diff --git a/lib/entityx/cxx11/c++11-test-static_assert-N1720_fail_compile.cpp b/lib/entityx/cxx11/c++11-test-static_assert-N1720_fail_compile.cpp deleted file mode 100644 index 4cb1183..0000000 --- a/lib/entityx/cxx11/c++11-test-static_assert-N1720_fail_compile.cpp +++ /dev/null @@ -1,5 +0,0 @@ -int main() -{ - static_assert(1 < 0, "this should fail"); - return 0; -} diff --git a/lib/entityx/cxx11/c++11-test-variadic_templates-N2555.cpp b/lib/entityx/cxx11/c++11-test-variadic_templates-N2555.cpp deleted file mode 100644 index 4518e88..0000000 --- a/lib/entityx/cxx11/c++11-test-variadic_templates-N2555.cpp +++ /dev/null @@ -1,23 +0,0 @@ -int Accumulate() -{ - return 0; -} - -template<typename T, typename... Ts> -int Accumulate(T v, Ts... vs) -{ - return v + Accumulate(vs...); -} - -template<int... Is> -int CountElements() -{ - return sizeof...(Is); -} - -int main() -{ - int acc = Accumulate(1, 2, 3, 4, -5); - int count = CountElements<1,2,3,4,5>(); - return ((acc == 5) && (count == 5)) ? 0 : 1; -} diff --git a/lib/entityx/cxx11/demo.cpp b/lib/entityx/cxx11/demo.cpp deleted file mode 100644 index f647d15..0000000 --- a/lib/entityx/cxx11/demo.cpp +++ /dev/null @@ -1,23 +0,0 @@ - -#include <iostream> - -int main() -{ - std::cout << "Testing\n"; - std::cout << "Has static_assert: " << -#ifdef HAS_CXX11_STATIC_ASSERT - "yes :)" -#else - "no" -#endif - << "\n"; - std::cout << "Has variadic templates: " << -#ifdef HAS_CXX11_VARIADIC_TEMPLATES - "yes :)" -#else - "no" -#endif - << "\n"; - return 0; -} - diff --git a/lib/entityx/entityx.pc.in b/lib/entityx/entityx.pc.in deleted file mode 100644 index ebbf32a..0000000 --- a/lib/entityx/entityx.pc.in +++ /dev/null @@ -1,6 +0,0 @@ -# entityx pkg-config source file - -Name: entityx -Description: EntityX is an EC system that uses C++11 features to provide type-safe component management, event delivery, etc. -Version: @ENTITYX_VERSION@ -Libs: @entityx_libs@ diff --git a/lib/entityx/entityx/3rdparty/catch.hpp b/lib/entityx/entityx/3rdparty/catch.hpp deleted file mode 100644 index e329620..0000000 --- a/lib/entityx/entityx/3rdparty/catch.hpp +++ /dev/null @@ -1,8345 +0,0 @@ -/* - * CATCH v1.0 build 27 (master branch) - * Generated: 2014-03-01 10:36:25.999888 - * ---------------------------------------------------------- - * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. - * - * Distributed under the Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - */ -#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED -#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED - -#define TWOBLUECUBES_CATCH_HPP_INCLUDED - -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wglobal-constructors" -#pragma clang diagnostic ignored "-Wvariadic-macros" -#pragma clang diagnostic ignored "-Wc99-extensions" -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -// #included from: internal/catch_notimplemented_exception.h -#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED - -// #included from: catch_common.h -#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED - -#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line -#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) -#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) - -#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr -#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) - -#include <sstream> -#include <stdexcept> -#include <algorithm> - -// #included from: catch_compiler_capabilities.h -#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED - -// Much of the following code is based on Boost (1.53) - -#ifdef __clang__ - -#if __has_feature(cxx_nullptr) - -#define CATCH_CONFIG_CPP11_NULLPTR - -#endif - -#endif // __clang__ - -//////////////////////////////////////////////////////////////////////////////// -// Borland -#ifdef __BORLANDC__ - -#if (__BORLANDC__ > 0x582 ) -//#define CATCH_CONFIG_SFINAE // Not confirmed -#endif - -#endif // __BORLANDC__ - -//////////////////////////////////////////////////////////////////////////////// -// EDG -#ifdef __EDG_VERSION__ - -#if (__EDG_VERSION__ > 238 ) -//#define CATCH_CONFIG_SFINAE // Not confirmed -#endif - -#endif // __EDG_VERSION__ - -//////////////////////////////////////////////////////////////////////////////// -// Digital Mars -#ifdef __DMC__ - -#if (__DMC__ > 0x840 ) -//#define CATCH_CONFIG_SFINAE // Not confirmed -#endif - -#endif // __DMC__ - -//////////////////////////////////////////////////////////////////////////////// -// GCC -#ifdef __GNUC__ - -#if __GNUC__ < 3 - -#if (__GNUC_MINOR__ >= 96 ) -//#define CATCH_CONFIG_SFINAE -#endif - -#elif __GNUC__ >= 3 - -// #define CATCH_CONFIG_SFINAE // Taking this out completely for now - -#endif // __GNUC__ < 3 - -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) ) - -#define CATCH_CONFIG_CPP11_NULLPTR -#endif - -#endif // __GNUC__ - -//////////////////////////////////////////////////////////////////////////////// -// Visual C++ -#ifdef _MSC_VER - -#if (_MSC_VER >= 1310 ) // (VC++ 7.0+) -//#define CATCH_CONFIG_SFINAE // Not confirmed -#endif - -#endif // _MSC_VER - -// Use variadic macros if the compiler supports them -#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ - ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ - ( defined __GNUC__ && __GNUC__ >= 3 ) || \ - ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) - -#ifndef CATCH_CONFIG_NO_VARIADIC_MACROS -#define CATCH_CONFIG_VARIADIC_MACROS -#endif - -#endif - -namespace Catch { - - class NonCopyable { - NonCopyable( NonCopyable const& ); - void operator = ( NonCopyable const& ); - protected: - NonCopyable() {} - virtual ~NonCopyable(); - }; - - class SafeBool { - public: - typedef void (SafeBool::*type)() const; - - static type makeSafe( bool value ) { - return value ? &SafeBool::trueValue : 0; - } - private: - void trueValue() const {} - }; - - template<typename ContainerT> - inline void deleteAll( ContainerT& container ) { - typename ContainerT::const_iterator it = container.begin(); - typename ContainerT::const_iterator itEnd = container.end(); - for(; it != itEnd; ++it ) - delete *it; - } - template<typename AssociativeContainerT> - inline void deleteAllValues( AssociativeContainerT& container ) { - typename AssociativeContainerT::const_iterator it = container.begin(); - typename AssociativeContainerT::const_iterator itEnd = container.end(); - for(; it != itEnd; ++it ) - delete it->second; - } - - bool startsWith( std::string const& s, std::string const& prefix ); - bool endsWith( std::string const& s, std::string const& suffix ); - bool contains( std::string const& s, std::string const& infix ); - void toLowerInPlace( std::string& s ); - std::string toLower( std::string const& s ); - std::string trim( std::string const& str ); - - struct pluralise { - pluralise( std::size_t count, std::string const& label ); - - friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); - - std::size_t m_count; - std::string m_label; - }; - - struct SourceLineInfo { - - SourceLineInfo(); - SourceLineInfo( char const* _file, std::size_t _line ); - SourceLineInfo( SourceLineInfo const& other ); - bool empty() const; - bool operator == ( SourceLineInfo const& other ) const; - - std::string file; - std::size_t line; - }; - - std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); - - // This is just here to avoid compiler warnings with macro constants and boolean literals - inline bool isTrue( bool value ){ return value; } - - void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); - - // Use this in variadic streaming macros to allow - // >> +StreamEndStop - // as well as - // >> stuff +StreamEndStop - struct StreamEndStop { - std::string operator+() { - return std::string(); - } - }; - template<typename T> - T const& operator + ( T const& value, StreamEndStop ) { - return value; - } -} - -#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) ) -#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); - -#include <ostream> - -namespace Catch { - - class NotImplementedException : public std::exception - { - public: - NotImplementedException( SourceLineInfo const& lineInfo ); - - virtual ~NotImplementedException() throw() {} - - virtual const char* what() const throw(); - - private: - std::string m_what; - SourceLineInfo m_lineInfo; - }; - -} // end namespace Catch - -/////////////////////////////////////////////////////////////////////////////// -#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) - -// #included from: internal/catch_context.h -#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED - -// #included from: catch_interfaces_generators.h -#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED - -#include <string> - -namespace Catch { - - struct IGeneratorInfo { - virtual ~IGeneratorInfo(); - virtual bool moveNext() = 0; - virtual std::size_t getCurrentIndex() const = 0; - }; - - struct IGeneratorsForTest { - virtual ~IGeneratorsForTest(); - - virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; - virtual bool moveNext() = 0; - }; - - IGeneratorsForTest* createGeneratorsForTest(); - -} // end namespace Catch - -// #included from: catch_ptr.hpp -#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -namespace Catch { - - // An intrusive reference counting smart pointer. - // T must implement addRef() and release() methods - // typically implementing the IShared interface - template<typename T> - class Ptr { - public: - Ptr() : m_p( NULL ){} - Ptr( T* p ) : m_p( p ){ - if( m_p ) - m_p->addRef(); - } - Ptr( Ptr const& other ) : m_p( other.m_p ){ - if( m_p ) - m_p->addRef(); - } - ~Ptr(){ - if( m_p ) - m_p->release(); - } - void reset() { - if( m_p ) - m_p->release(); - m_p = NULL; - } - Ptr& operator = ( T* p ){ - Ptr temp( p ); - swap( temp ); - return *this; - } - Ptr& operator = ( Ptr const& other ){ - Ptr temp( other ); - swap( temp ); - return *this; - } - void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } - T* get() { return m_p; } - const T* get() const{ return m_p; } - T& operator*() const { return *m_p; } - T* operator->() const { return m_p; } - bool operator !() const { return m_p == NULL; } - operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); } - - private: - T* m_p; - }; - - struct IShared : NonCopyable { - virtual ~IShared(); - virtual void addRef() const = 0; - virtual void release() const = 0; - }; - - template<typename T = IShared> - struct SharedImpl : T { - - SharedImpl() : m_rc( 0 ){} - - virtual void addRef() const { - ++m_rc; - } - virtual void release() const { - if( --m_rc == 0 ) - delete this; - } - - mutable unsigned int m_rc; - }; - -} // end namespace Catch - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#include <memory> -#include <vector> -#include <stdlib.h> - -namespace Catch { - - class TestCase; - class Stream; - struct IResultCapture; - struct IRunner; - struct IGeneratorsForTest; - struct IConfig; - - struct IContext - { - virtual ~IContext(); - - virtual IResultCapture& getResultCapture() = 0; - virtual IRunner& getRunner() = 0; - virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; - virtual bool advanceGeneratorsForCurrentTest() = 0; - virtual Ptr<IConfig const> getConfig() const = 0; - }; - - struct IMutableContext : IContext - { - virtual ~IMutableContext(); - virtual void setResultCapture( IResultCapture* resultCapture ) = 0; - virtual void setRunner( IRunner* runner ) = 0; - virtual void setConfig( Ptr<IConfig const> const& config ) = 0; - }; - - IContext& getCurrentContext(); - IMutableContext& getCurrentMutableContext(); - void cleanUpContext(); - Stream createStream( std::string const& streamName ); - -} - -// #included from: internal/catch_test_registry.hpp -#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED - -// #included from: catch_interfaces_testcase.h -#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED - -#include <vector> - -namespace Catch { - - class TestCaseFilters; - - struct ITestCase : IShared { - virtual void invoke () const = 0; - protected: - virtual ~ITestCase(); - }; - - class TestCase; - - struct ITestCaseRegistry { - virtual ~ITestCaseRegistry(); - virtual std::vector<TestCase> const& getAllTests() const = 0; - virtual std::vector<TestCase> getMatchingTestCases( std::string const& rawTestSpec ) const = 0; - }; -} - -namespace Catch { - -template<typename C> -class MethodTestCase : public SharedImpl<ITestCase> { - -public: - MethodTestCase( void (C::*method)() ) : m_method( method ) {} - - virtual void invoke() const { - C obj; - (obj.*m_method)(); - } - -private: - virtual ~MethodTestCase() {} - - void (C::*m_method)(); -}; - -typedef void(*TestFunction)(); - -struct NameAndDesc { - NameAndDesc( const char* _name = "", const char* _description= "" ) - : name( _name ), description( _description ) - {} - - const char* name; - const char* description; -}; - -struct AutoReg { - - AutoReg( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ); - - template<typename C> - AutoReg( void (C::*method)(), - char const* className, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ) { - registerTestCase( new MethodTestCase<C>( method ), - className, - nameAndDesc, - lineInfo ); - } - - void registerTestCase( ITestCase* testCase, - char const* className, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ); - - ~AutoReg(); - -private: - AutoReg( AutoReg const& ); - void operator= ( AutoReg const& ); -}; - -} // end namespace Catch - -#ifdef CATCH_CONFIG_VARIADIC_MACROS - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TESTCASE( ... ) \ - static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ - static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\ - namespace{ \ - struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ - void test(); \ - }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ - } \ - void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() - -#else - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ - static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ - static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ - namespace{ \ - struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ - void test(); \ - }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ - } \ - void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() - -#endif - -// #included from: internal/catch_capture.hpp -#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED - -// #included from: catch_expression_decomposer.hpp -#define TWOBLUECUBES_CATCH_EXPRESSION_DECOMPOSER_HPP_INCLUDED - -// #included from: catch_expression_lhs.hpp -#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED - -// #included from: catch_expressionresult_builder.h -#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_BUILDER_H_INCLUDED - -// #included from: catch_tostring.hpp -#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED - -// #included from: catch_sfinae.hpp -#define TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED - -// Try to detect if the current compiler supports SFINAE - -namespace Catch { - - struct TrueType { - static const bool value = true; - typedef void Enable; - char sizer[1]; - }; - struct FalseType { - static const bool value = false; - typedef void Disable; - char sizer[2]; - }; - -#ifdef CATCH_CONFIG_SFINAE - - template<bool> struct NotABooleanExpression; - - template<bool c> struct If : NotABooleanExpression<c> {}; - template<> struct If<true> : TrueType {}; - template<> struct If<false> : FalseType {}; - - template<int size> struct SizedIf; - template<> struct SizedIf<sizeof(TrueType)> : TrueType {}; - template<> struct SizedIf<sizeof(FalseType)> : FalseType {}; - -#endif // CATCH_CONFIG_SFINAE - -} // end namespace Catch - -#include <sstream> -#include <iomanip> -#include <limits> -#include <vector> - -#ifdef __OBJC__ -// #included from: catch_objc_arc.hpp -#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED - -#import <Foundation/Foundation.h> - -#ifdef __has_feature -#define CATCH_ARC_ENABLED __has_feature(objc_arc) -#else -#define CATCH_ARC_ENABLED 0 -#endif - -void arcSafeRelease( NSObject* obj ); -id performOptionalSelector( id obj, SEL sel ); - -#if !CATCH_ARC_ENABLED -inline void arcSafeRelease( NSObject* obj ) { - [obj release]; -} -inline id performOptionalSelector( id obj, SEL sel ) { - if( [obj respondsToSelector: sel] ) - return [obj performSelector: sel]; - return nil; -} -#define CATCH_UNSAFE_UNRETAINED -#define CATCH_ARC_STRONG -#else -inline void arcSafeRelease( NSObject* ){} -inline id performOptionalSelector( id obj, SEL sel ) { -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Warc-performSelector-leaks" -#endif - if( [obj respondsToSelector: sel] ) - return [obj performSelector: sel]; -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - return nil; -} -#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained -#define CATCH_ARC_STRONG __strong -#endif - -#endif - -namespace Catch { -namespace Detail { - -// SFINAE is currently disabled by default for all compilers. -// If the non SFINAE version of IsStreamInsertable is ambiguous for you -// and your compiler supports SFINAE, try #defining CATCH_CONFIG_SFINAE -#ifdef CATCH_CONFIG_SFINAE - - template<typename T> - class IsStreamInsertableHelper { - template<int N> struct TrueIfSizeable : TrueType {}; - - template<typename T2> - static TrueIfSizeable<sizeof((*(std::ostream*)0) << *((T2 const*)0))> dummy(T2*); - static FalseType dummy(...); - - public: - typedef SizedIf<sizeof(dummy((T*)0))> type; - }; - - template<typename T> - struct IsStreamInsertable : IsStreamInsertableHelper<T>::type {}; - -#else - - struct BorgType { - template<typename T> BorgType( T const& ); - }; - - TrueType& testStreamable( std::ostream& ); - FalseType testStreamable( FalseType ); - - FalseType operator<<( std::ostream const&, BorgType const& ); - - template<typename T> - struct IsStreamInsertable { - static std::ostream &s; - static T const&t; - enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; - }; - -#endif - - template<bool C> - struct StringMakerBase { - template<typename T> - static std::string convert( T const& ) { return "{?}"; } - }; - - template<> - struct StringMakerBase<true> { - template<typename T> - static std::string convert( T const& _value ) { - std::ostringstream oss; - oss << _value; - return oss.str(); - } - }; - - // For display purposes only. - // Does not consider endian-ness - template<typename T> - std::string rawMemoryToString( T value ) { - union { - T typedValue; - unsigned char bytes[sizeof(T)]; - }; - - typedValue = value; - - std::ostringstream oss; - oss << "0x"; - for( unsigned char* cp = bytes; cp < bytes+sizeof(T); ++cp ) - oss << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)*cp; - return oss.str(); - } - -} // end namespace Detail - -template<typename T> -std::string toString( T const& value ); - -template<typename T> -struct StringMaker : - Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {}; - -template<typename T> -struct StringMaker<T*> { - template<typename U> - static std::string convert( U* p ) { - if( !p ) - return INTERNAL_CATCH_STRINGIFY( NULL ); - else - return Detail::rawMemoryToString( p ); - } -}; - -template<typename R, typename C> -struct StringMaker<R C::*> { - static std::string convert( R C::* p ) { - if( !p ) - return INTERNAL_CATCH_STRINGIFY( NULL ); - else - return Detail::rawMemoryToString( p ); - } -}; - -namespace Detail { - template<typename InputIterator> - std::string rangeToString( InputIterator first, InputIterator last ); -} - -template<typename T, typename Allocator> -struct StringMaker<std::vector<T, Allocator> > { - static std::string convert( std::vector<T,Allocator> const& v ) { - return Detail::rangeToString( v.begin(), v.end() ); - } -}; - -namespace Detail { - template<typename T> - inline std::string makeString( T const& value ) { - return StringMaker<T>::convert( value ); - } -} // end namespace Detail - -/// \brief converts any type to a string -/// -/// The default template forwards on to ostringstream - except when an -/// ostringstream overload does not exist - in which case it attempts to detect -/// that and writes {?}. -/// Overload (not specialise) this template for custom typs that you don't want -/// to provide an ostream overload for. -template<typename T> -std::string toString( T const& value ) { - return StringMaker<T>::convert( value ); -} - -// Built in overloads - -inline std::string toString( std::string const& value ) { - return "\"" + value + "\""; -} - -inline std::string toString( std::wstring const& value ) { - std::ostringstream oss; - oss << "\""; - for(size_t i = 0; i < value.size(); ++i ) - oss << static_cast<char>( value[i] <= 0xff ? value[i] : '?'); - oss << "\""; - return oss.str(); -} - -inline std::string toString( const char* const value ) { - return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); -} - -inline std::string toString( char* const value ) { - return Catch::toString( static_cast<const char*>( value ) ); -} - -inline std::string toString( int value ) { - std::ostringstream oss; - oss << value; - return oss.str(); -} - -inline std::string toString( unsigned long value ) { - std::ostringstream oss; - if( value > 8192 ) - oss << "0x" << std::hex << value; - else - oss << value; - return oss.str(); -} - -inline std::string toString( unsigned int value ) { - return toString( static_cast<unsigned long>( value ) ); -} - -inline std::string toString( const double value ) { - std::ostringstream oss; - oss << std::setprecision( 10 ) - << std::fixed - << value; - std::string d = oss.str(); - std::size_t i = d.find_last_not_of( '0' ); - if( i != std::string::npos && i != d.size()-1 ) { - if( d[i] == '.' ) - i++; - d = d.substr( 0, i+1 ); - } - return d; -} - -inline std::string toString( bool value ) { - return value ? "true" : "false"; -} - -inline std::string toString( char value ) { - return value < ' ' - ? toString( static_cast<unsigned int>( value ) ) - : Detail::makeString( value ); -} - -inline std::string toString( signed char value ) { - return toString( static_cast<char>( value ) ); -} - -inline std::string toString( unsigned char value ) { - return toString( static_cast<char>( value ) ); -} - -#ifdef CATCH_CONFIG_CPP11_NULLPTR -inline std::string toString( std::nullptr_t ) { - return "nullptr"; -} -#endif - -#ifdef __OBJC__ - inline std::string toString( NSString const * const& nsstring ) { - if( !nsstring ) - return "nil"; - return std::string( "@\"" ) + [nsstring UTF8String] + "\""; - } - inline std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { - if( !nsstring ) - return "nil"; - return std::string( "@\"" ) + [nsstring UTF8String] + "\""; - } - inline std::string toString( NSObject* const& nsObject ) { - return toString( [nsObject description] ); - } -#endif - - namespace Detail { - template<typename InputIterator> - std::string rangeToString( InputIterator first, InputIterator last ) { - std::ostringstream oss; - oss << "{ "; - if( first != last ) { - oss << toString( *first ); - for( ++first ; first != last ; ++first ) { - oss << ", " << toString( *first ); - } - } - oss << " }"; - return oss.str(); - } -} - -} // end namespace Catch - -// #included from: catch_assertionresult.h -#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED - -#include <string> -// #included from: catch_result_type.h -#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED - -namespace Catch { - - // ResultWas::OfType enum - struct ResultWas { enum OfType { - Unknown = -1, - Ok = 0, - Info = 1, - Warning = 2, - - FailureBit = 0x10, - - ExpressionFailed = FailureBit | 1, - ExplicitFailure = FailureBit | 2, - - Exception = 0x100 | FailureBit, - - ThrewException = Exception | 1, - DidntThrowException = Exception | 2 - - }; }; - - inline bool isOk( ResultWas::OfType resultType ) { - return ( resultType & ResultWas::FailureBit ) == 0; - } - inline bool isJustInfo( int flags ) { - return flags == ResultWas::Info; - } - - // ResultAction::Value enum - struct ResultAction { enum Value { - None, - Failed = 1, // Failure - but no debug break if Debug bit not set - Debug = 2, // If this bit is set, invoke the debugger - Abort = 4 // Test run should abort - }; }; - - // ResultDisposition::Flags enum - struct ResultDisposition { enum Flags { - Normal = 0x00, - - ContinueOnFailure = 0x01, // Failures fail test, but execution continues - NegateResult = 0x02, // Prefix expressiom with ! - SuppressFail = 0x04 // Failures are reported but do not fail the test - }; }; - - inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { - return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) ); - } - - inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } - inline bool shouldNegate( int flags ) { return ( flags & ResultDisposition::NegateResult ) != 0; } - inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } - -} // end namespace Catch - - -namespace Catch { - - struct AssertionInfo - { - AssertionInfo() {} - AssertionInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - std::string const& _capturedExpression, - ResultDisposition::Flags _resultDisposition ); - - std::string macroName; - SourceLineInfo lineInfo; - std::string capturedExpression; - ResultDisposition::Flags resultDisposition; - }; - - struct AssertionResultData - { - AssertionResultData() : resultType( ResultWas::Unknown ) {} - - std::string reconstructedExpression; - std::string message; - ResultWas::OfType resultType; - }; - - class AssertionResult { - public: - AssertionResult(); - AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); - ~AssertionResult(); - - bool isOk() const; - bool succeeded() const; - ResultWas::OfType getResultType() const; - bool hasExpression() const; - bool hasMessage() const; - std::string getExpression() const; - std::string getExpressionInMacro() const; - bool hasExpandedExpression() const; - std::string getExpandedExpression() const; - std::string getMessage() const; - SourceLineInfo getSourceInfo() const; - std::string getTestMacroName() const; - - protected: - AssertionInfo m_info; - AssertionResultData m_resultData; - }; - -} // end namespace Catch - -// #included from: catch_evaluate.hpp -#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4389) // '==' : signed/unsigned mismatch -#endif - -namespace Catch { -namespace Internal { - - enum Operator { - IsEqualTo, - IsNotEqualTo, - IsLessThan, - IsGreaterThan, - IsLessThanOrEqualTo, - IsGreaterThanOrEqualTo - }; - - template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } }; - template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } }; - template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } }; - template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } }; - template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } }; - template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } }; - template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } }; - - template<typename T> - inline T& opCast(T const& t) { return const_cast<T&>(t); } - -// nullptr_t support based on pull request #154 from Konstantin Baumann -#ifdef CATCH_CONFIG_CPP11_NULLPTR - inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } -#endif // CATCH_CONFIG_CPP11_NULLPTR - - // So the compare overloads can be operator agnostic we convey the operator as a template - // enum, which is used to specialise an Evaluator for doing the comparison. - template<typename T1, typename T2, Operator Op> - class Evaluator{}; - - template<typename T1, typename T2> - struct Evaluator<T1, T2, IsEqualTo> { - static bool evaluate( T1 const& lhs, T2 const& rhs) { - return opCast( lhs ) == opCast( rhs ); - } - }; - template<typename T1, typename T2> - struct Evaluator<T1, T2, IsNotEqualTo> { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return opCast( lhs ) != opCast( rhs ); - } - }; - template<typename T1, typename T2> - struct Evaluator<T1, T2, IsLessThan> { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return opCast( lhs ) < opCast( rhs ); - } - }; - template<typename T1, typename T2> - struct Evaluator<T1, T2, IsGreaterThan> { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return opCast( lhs ) > opCast( rhs ); - } - }; - template<typename T1, typename T2> - struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return opCast( lhs ) >= opCast( rhs ); - } - }; - template<typename T1, typename T2> - struct Evaluator<T1, T2, IsLessThanOrEqualTo> { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return opCast( lhs ) <= opCast( rhs ); - } - }; - - template<Operator Op, typename T1, typename T2> - bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { - return Evaluator<T1, T2, Op>::evaluate( lhs, rhs ); - } - - // This level of indirection allows us to specialise for integer types - // to avoid signed/ unsigned warnings - - // "base" overload - template<Operator Op, typename T1, typename T2> - bool compare( T1 const& lhs, T2 const& rhs ) { - return Evaluator<T1, T2, Op>::evaluate( lhs, rhs ); - } - - // unsigned X to int - template<Operator Op> bool compare( unsigned int lhs, int rhs ) { - return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); - } - template<Operator Op> bool compare( unsigned long lhs, int rhs ) { - return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); - } - template<Operator Op> bool compare( unsigned char lhs, int rhs ) { - return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); - } - - // unsigned X to long - template<Operator Op> bool compare( unsigned int lhs, long rhs ) { - return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); - } - template<Operator Op> bool compare( unsigned long lhs, long rhs ) { - return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); - } - template<Operator Op> bool compare( unsigned char lhs, long rhs ) { - return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); - } - - // int to unsigned X - template<Operator Op> bool compare( int lhs, unsigned int rhs ) { - return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); - } - template<Operator Op> bool compare( int lhs, unsigned long rhs ) { - return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); - } - template<Operator Op> bool compare( int lhs, unsigned char rhs ) { - return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); - } - - // long to unsigned X - template<Operator Op> bool compare( long lhs, unsigned int rhs ) { - return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); - } - template<Operator Op> bool compare( long lhs, unsigned long rhs ) { - return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); - } - template<Operator Op> bool compare( long lhs, unsigned char rhs ) { - return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); - } - - // pointer to long (when comparing against NULL) - template<Operator Op, typename T> bool compare( long lhs, T* rhs ) { - return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); - } - template<Operator Op, typename T> bool compare( T* lhs, long rhs ) { - return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); - } - - // pointer to int (when comparing against NULL) - template<Operator Op, typename T> bool compare( int lhs, T* rhs ) { - return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); - } - template<Operator Op, typename T> bool compare( T* lhs, int rhs ) { - return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); - } - -#ifdef CATCH_CONFIG_CPP11_NULLPTR - // pointer to nullptr_t (when comparing against nullptr) - template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) { - return Evaluator<T*, T*, Op>::evaluate( NULL, rhs ); - } - template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) { - return Evaluator<T*, T*, Op>::evaluate( lhs, NULL ); - } -#endif // CATCH_CONFIG_CPP11_NULLPTR - -} // end of namespace Internal -} // end of namespace Catch - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -namespace Catch { - -struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; - -// Wraps the (stringised versions of) the lhs, operator and rhs of an expression - as well as -// the result of evaluating it. This is used to build an AssertionResult object -class ExpressionResultBuilder { -public: - - ExpressionResultBuilder( ResultWas::OfType resultType = ResultWas::Unknown ); - ExpressionResultBuilder( ExpressionResultBuilder const& other ); - ExpressionResultBuilder& operator=(ExpressionResultBuilder const& other ); - - ExpressionResultBuilder& setResultType( ResultWas::OfType result ); - ExpressionResultBuilder& setResultType( bool result ); - ExpressionResultBuilder& setLhs( std::string const& lhs ); - ExpressionResultBuilder& setRhs( std::string const& rhs ); - ExpressionResultBuilder& setOp( std::string const& op ); - - ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition ); - - template<typename T> - ExpressionResultBuilder& operator << ( T const& value ) { - m_stream << value; - return *this; - } - - std::string reconstructExpression( AssertionInfo const& info ) const; - - AssertionResult buildResult( AssertionInfo const& info ) const; - - template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); - template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); - -private: - AssertionResultData m_data; - struct ExprComponents { - ExprComponents() : shouldNegate( false ) {} - bool shouldNegate; - std::string lhs, rhs, op; - } m_exprComponents; - std::ostringstream m_stream; -}; - -} // end namespace Catch - -namespace Catch { - -// Wraps the LHS of an expression and captures the operator and RHS (if any) - wrapping them all -// in an ExpressionResultBuilder object -template<typename T> -class ExpressionLhs { - void operator = ( ExpressionLhs const& ); - -public: - ExpressionLhs( T lhs ) : m_lhs( lhs ) {} - - template<typename RhsT> - ExpressionResultBuilder& operator == ( RhsT const& rhs ) { - return captureExpression<Internal::IsEqualTo>( rhs ); - } - - template<typename RhsT> - ExpressionResultBuilder& operator != ( RhsT const& rhs ) { - return captureExpression<Internal::IsNotEqualTo>( rhs ); - } - - template<typename RhsT> - ExpressionResultBuilder& operator < ( RhsT const& rhs ) { - return captureExpression<Internal::IsLessThan>( rhs ); - } - - template<typename RhsT> - ExpressionResultBuilder& operator > ( RhsT const& rhs ) { - return captureExpression<Internal::IsGreaterThan>( rhs ); - } - - template<typename RhsT> - ExpressionResultBuilder& operator <= ( RhsT const& rhs ) { - return captureExpression<Internal::IsLessThanOrEqualTo>( rhs ); - } - - template<typename RhsT> - ExpressionResultBuilder& operator >= ( RhsT const& rhs ) { - return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs ); - } - - ExpressionResultBuilder& operator == ( bool rhs ) { - return captureExpression<Internal::IsEqualTo>( rhs ); - } - - ExpressionResultBuilder& operator != ( bool rhs ) { - return captureExpression<Internal::IsNotEqualTo>( rhs ); - } - - ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition ) { - bool value = m_lhs ? true : false; - return m_result - .setLhs( Catch::toString( value ) ) - .setResultType( value ) - .endExpression( resultDisposition ); - } - - // Only simple binary expressions are allowed on the LHS. - // If more complex compositions are required then place the sub expression in parentheses - template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& ); - template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& ); - template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& ); - template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& ); - template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); - template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); - -private: - template<Internal::Operator Op, typename RhsT> - ExpressionResultBuilder& captureExpression( RhsT const& rhs ) { - return m_result - .setResultType( Internal::compare<Op>( m_lhs, rhs ) ) - .setLhs( Catch::toString( m_lhs ) ) - .setRhs( Catch::toString( rhs ) ) - .setOp( Internal::OperatorTraits<Op>::getName() ); - } - -private: - ExpressionResultBuilder m_result; - T m_lhs; -}; - -} // end namespace Catch - -namespace Catch { - -// Captures the LHS of the expression and wraps it in an Expression Lhs object -class ExpressionDecomposer { -public: - - template<typename T> - ExpressionLhs<T const&> operator->* ( T const& operand ) { - return ExpressionLhs<T const&>( operand ); - } - - ExpressionLhs<bool> operator->* ( bool value ) { - return ExpressionLhs<bool>( value ); - } -}; - -} // end namespace Catch - -// #included from: catch_message.h -#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED - -#include <string> - -namespace Catch { - - struct MessageInfo { - MessageInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - ResultWas::OfType _type ); - - std::string macroName; - SourceLineInfo lineInfo; - ResultWas::OfType type; - std::string message; - unsigned int sequence; - - bool operator == ( MessageInfo const& other ) const { - return sequence == other.sequence; - } - bool operator < ( MessageInfo const& other ) const { - return sequence < other.sequence; - } - private: - static unsigned int globalCount; - }; - - struct MessageBuilder { - MessageBuilder( std::string const& macroName, - SourceLineInfo const& lineInfo, - ResultWas::OfType type ) - : m_info( macroName, lineInfo, type ) - {} - - template<typename T> - MessageBuilder& operator << ( T const& value ) { - m_stream << value; - return *this; - } - - MessageInfo m_info; - std::ostringstream m_stream; - }; - - class ScopedMessage { - public: - ScopedMessage( MessageBuilder const& builder ); - ~ScopedMessage(); - - MessageInfo m_info; - }; - -} // end namespace Catch - -// #included from: catch_interfaces_capture.h -#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED - -#include <string> - -namespace Catch { - - class TestCase; - class ExpressionResultBuilder; - class AssertionResult; - struct AssertionInfo; - struct SectionInfo; - struct MessageInfo; - class ScopedMessageBuilder; - struct Counts; - - struct IResultCapture { - - virtual ~IResultCapture(); - - virtual void assertionEnded( AssertionResult const& result ) = 0; - virtual bool sectionStarted( SectionInfo const& sectionInfo, - Counts& assertions ) = 0; - virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 0; - virtual void pushScopedMessage( MessageInfo const& message ) = 0; - virtual void popScopedMessage( MessageInfo const& message ) = 0; - - virtual bool shouldDebugBreak() const = 0; - - virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& assertionResult, AssertionInfo const& assertionInfo ) = 0; - - virtual std::string getCurrentTestName() const = 0; - virtual const AssertionResult* getLastResult() const = 0; - }; -} - -// #included from: catch_debugger.h -#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED - -// #included from: catch_platform.h -#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED - -#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) -#define CATCH_PLATFORM_MAC -#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) -#define CATCH_PLATFORM_IPHONE -#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) -#define CATCH_PLATFORM_WINDOWS -#endif - -#include <string> - -namespace Catch{ - - bool isDebuggerActive(); - void writeToDebugConsole( std::string const& text ); -} - -#ifdef CATCH_PLATFORM_MAC - - // The following code snippet based on: - // http://cocoawithlove.com/2008/03/break-into-debugger.html - #ifdef DEBUG - #if defined(__ppc64__) || defined(__ppc__) - #define CATCH_BREAK_INTO_DEBUGGER() \ - if( Catch::isDebuggerActive() ) { \ - __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ - : : : "memory","r0","r3","r4" ); \ - } - #else - #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} - #endif - #endif - -#elif defined(_MSC_VER) - #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); } -#elif defined(__MINGW32__) - extern "C" __declspec(dllimport) void __stdcall DebugBreak(); - #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); } -#endif - -#ifndef CATCH_BREAK_INTO_DEBUGGER -#define CATCH_BREAK_INTO_DEBUGGER() Catch::isTrue( true ); -#endif - -// #included from: catch_interfaces_registry_hub.h -#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED - -#include <string> - -namespace Catch { - - class TestCase; - struct ITestCaseRegistry; - struct IExceptionTranslatorRegistry; - struct IExceptionTranslator; - struct IReporterRegistry; - struct IReporterFactory; - - struct IRegistryHub { - virtual ~IRegistryHub(); - - virtual IReporterRegistry const& getReporterRegistry() const = 0; - virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; - }; - - struct IMutableRegistryHub { - virtual ~IMutableRegistryHub(); - virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0; - virtual void registerTest( TestCase const& testInfo ) = 0; - virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; - }; - - IRegistryHub& getRegistryHub(); - IMutableRegistryHub& getMutableRegistryHub(); - void cleanUp(); - std::string translateActiveException(); - -} - -// #included from: catch_interfaces_config.h -#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED - -#include <iostream> -#include <string> - -namespace Catch { - - struct Verbosity { enum Level { - NoOutput = 0, - Quiet, - Normal - }; }; - - struct WarnAbout { enum What { - Nothing = 0x00, - NoAssertions = 0x01 - }; }; - - struct ShowDurations { enum OrNot { - DefaultForReporter, - Always, - Never - }; }; - - struct IConfig : IShared { - - virtual ~IConfig(); - - virtual bool allowThrows() const = 0; - virtual std::ostream& stream() const = 0; - virtual std::string name() const = 0; - virtual bool includeSuccessfulResults() const = 0; - virtual bool shouldDebugBreak() const = 0; - virtual bool warnAboutMissingAssertions() const = 0; - virtual int abortAfter() const = 0; - virtual ShowDurations::OrNot showDurations() const = 0; - }; -} - -#include <ostream> - -namespace Catch { - - inline IResultCapture& getResultCapture() { - return getCurrentContext().getResultCapture(); - } - - template<typename MatcherT> - ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher, - std::string const& matcherCallAsString ) { - std::string matcherAsString = matcher.toString(); - if( matcherAsString == "{?}" ) - matcherAsString = matcherCallAsString; - return ExpressionResultBuilder() - .setRhs( matcherAsString ) - .setOp( "matches" ); - } - - template<typename MatcherT, typename ArgT> - ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher, - ArgT const& arg, - std::string const& matcherCallAsString ) { - return expressionResultBuilderFromMatcher( matcher, matcherCallAsString ) - .setLhs( Catch::toString( arg ) ) - .setResultType( matcher.match( arg ) ); - } - - template<typename MatcherT, typename ArgT> - ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher, - ArgT* arg, - std::string const& matcherCallAsString ) { - return expressionResultBuilderFromMatcher( matcher, matcherCallAsString ) - .setLhs( Catch::toString( arg ) ) - .setResultType( matcher.match( arg ) ); - } - -struct TestFailureException{}; - -} // end namespace Catch - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ASSERTIONINFO_NAME INTERNAL_CATCH_UNIQUE_NAME( __assertionInfo ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ACCEPT_EXPR( evaluatedExpr, resultDisposition, originalExpr ) \ - if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr, INTERNAL_CATCH_ASSERTIONINFO_NAME ) ) { \ - if( internal_catch_action & Catch::ResultAction::Debug ) CATCH_BREAK_INTO_DEBUGGER(); \ - if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \ - if( !Catch::shouldContinueOnFailure( resultDisposition ) ) throw Catch::TestFailureException(); \ - Catch::isTrue( false && originalExpr ); \ - } - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ACCEPT_INFO( expr, macroName, resultDisposition ) \ - Catch::AssertionInfo INTERNAL_CATCH_ASSERTIONINFO_NAME( macroName, CATCH_INTERNAL_LINEINFO, expr, resultDisposition ); - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ - do { \ - INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \ - try { \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionDecomposer()->*expr ).endExpression( resultDisposition ), resultDisposition, expr ); \ - } catch( Catch::TestFailureException& ) { \ - throw; \ - } catch( ... ) { \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), \ - resultDisposition | Catch::ResultDisposition::ContinueOnFailure, expr ); \ - } \ - } while( Catch::isTrue( false ) ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ - INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ - if( Catch::getResultCapture().getLastResult()->succeeded() ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ - INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ - if( !Catch::getResultCapture().getLastResult()->succeeded() ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ - do { \ - INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \ - try { \ - expr; \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \ - } \ - catch( ... ) { \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), resultDisposition, false ); \ - } \ -} while( Catch::isTrue( false ) ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \ - try { \ - if( Catch::getCurrentContext().getConfig()->allowThrows() ) { \ - expr; \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::DidntThrowException ), resultDisposition, false ); \ - } \ - } \ - catch( Catch::TestFailureException& ) { \ - throw; \ - } \ - catch( exceptionType ) { \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \ - } - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS( expr, exceptionType, resultDisposition, macroName ) \ - do { \ - INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \ - INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \ - } while( Catch::isTrue( false ) ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ - do { \ - INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \ - INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \ - catch( ... ) { \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \ - resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \ - } \ - } while( Catch::isTrue( false ) ) - -/////////////////////////////////////////////////////////////////////////////// -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ - do { \ - INTERNAL_CATCH_ACCEPT_INFO( "", macroName, resultDisposition ); \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << __VA_ARGS__ +::Catch::StreamEndStop(), resultDisposition, true ) \ - } while( Catch::isTrue( false ) ) -#else - #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ - do { \ - INTERNAL_CATCH_ACCEPT_INFO( "", macroName, resultDisposition ); \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << log, resultDisposition, true ) \ - } while( Catch::isTrue( false ) ) -#endif - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_INFO( log, macroName ) \ - Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ - do { \ - INTERNAL_CATCH_ACCEPT_INFO( #arg " " #matcher, macroName, resultDisposition ); \ - try { \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::expressionResultBuilderFromMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), resultDisposition, false ); \ - } catch( Catch::TestFailureException& ) { \ - throw; \ - } catch( ... ) { \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \ - resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \ - } \ - } while( Catch::isTrue( false ) ) - -// #included from: internal/catch_section.h -#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED - -// #included from: catch_section_info.h -#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED - -namespace Catch { - - struct SectionInfo { - SectionInfo( std::string const& _name, - std::string const& _description, - SourceLineInfo const& _lineInfo ) - : name( _name ), - description( _description ), - lineInfo( _lineInfo ) - {} - - std::string name; - std::string description; - SourceLineInfo lineInfo; - }; - -} // end namespace Catch - -// #included from: catch_totals.hpp -#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED - -#include <cstddef> - -namespace Catch { - - struct Counts { - Counts() : passed( 0 ), failed( 0 ) {} - - Counts operator - ( Counts const& other ) const { - Counts diff; - diff.passed = passed - other.passed; - diff.failed = failed - other.failed; - return diff; - } - Counts& operator += ( Counts const& other ) { - passed += other.passed; - failed += other.failed; - return *this; - } - - std::size_t total() const { - return passed + failed; - } - - std::size_t passed; - std::size_t failed; - }; - - struct Totals { - - Totals operator - ( Totals const& other ) const { - Totals diff; - diff.assertions = assertions - other.assertions; - diff.testCases = testCases - other.testCases; - return diff; - } - - Totals delta( Totals const& prevTotals ) const { - Totals diff = *this - prevTotals; - if( diff.assertions.failed > 0 ) - ++diff.testCases.failed; - else - ++diff.testCases.passed; - return diff; - } - - Totals& operator += ( Totals const& other ) { - assertions += other.assertions; - testCases += other.testCases; - return *this; - } - - Counts assertions; - Counts testCases; - }; -} - -// #included from: catch_timer.h -#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED - -#ifdef CATCH_PLATFORM_WINDOWS -typedef unsigned long long uint64_t; -#else -#include <stdint.h> -#endif - -namespace Catch { - - class Timer { - public: - Timer() : m_ticks( 0 ) {} - void start(); - unsigned int getElapsedNanoseconds() const; - unsigned int getElapsedMilliseconds() const; - double getElapsedSeconds() const; - - private: - uint64_t m_ticks; - }; - -} // namespace Catch - -#include <string> - -namespace Catch { - - class Section { - public: - Section( SourceLineInfo const& lineInfo, - std::string const& name, - std::string const& description = "" ); - ~Section(); - - // This indicates whether the section should be executed or not - operator bool(); - - private: - - SectionInfo m_info; - - std::string m_name; - Counts m_assertions; - bool m_sectionIncluded; - Timer m_timer; - }; - -} // end namespace Catch - -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define INTERNAL_CATCH_SECTION( ... ) \ - if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) -#else - #define INTERNAL_CATCH_SECTION( name, desc ) \ - if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, name, desc ) ) -#endif - -// #included from: internal/catch_generators.hpp -#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED - -#include <iterator> -#include <vector> -#include <string> -#include <stdlib.h> - -namespace Catch { - -template<typename T> -struct IGenerator { - virtual ~IGenerator() {} - virtual T getValue( std::size_t index ) const = 0; - virtual std::size_t size () const = 0; -}; - -template<typename T> -class BetweenGenerator : public IGenerator<T> { -public: - BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} - - virtual T getValue( std::size_t index ) const { - return m_from+static_cast<int>( index ); - } - - virtual std::size_t size() const { - return static_cast<std::size_t>( 1+m_to-m_from ); - } - -private: - - T m_from; - T m_to; -}; - -template<typename T> -class ValuesGenerator : public IGenerator<T> { -public: - ValuesGenerator(){} - - void add( T value ) { - m_values.push_back( value ); - } - - virtual T getValue( std::size_t index ) const { - return m_values[index]; - } - - virtual std::size_t size() const { - return m_values.size(); - } - -private: - std::vector<T> m_values; -}; - -template<typename T> -class CompositeGenerator { -public: - CompositeGenerator() : m_totalSize( 0 ) {} - - // *** Move semantics, similar to auto_ptr *** - CompositeGenerator( CompositeGenerator& other ) - : m_fileInfo( other.m_fileInfo ), - m_totalSize( 0 ) - { - move( other ); - } - - CompositeGenerator& setFileInfo( const char* fileInfo ) { - m_fileInfo = fileInfo; - return *this; - } - - ~CompositeGenerator() { - deleteAll( m_composed ); - } - - operator T () const { - size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); - - typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin(); - typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end(); - for( size_t index = 0; it != itEnd; ++it ) - { - const IGenerator<T>* generator = *it; - if( overallIndex >= index && overallIndex < index + generator->size() ) - { - return generator->getValue( overallIndex-index ); - } - index += generator->size(); - } - CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); - return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so - } - - void add( const IGenerator<T>* generator ) { - m_totalSize += generator->size(); - m_composed.push_back( generator ); - } - - CompositeGenerator& then( CompositeGenerator& other ) { - move( other ); - return *this; - } - - CompositeGenerator& then( T value ) { - ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); - valuesGen->add( value ); - add( valuesGen ); - return *this; - } - -private: - - void move( CompositeGenerator& other ) { - std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); - m_totalSize += other.m_totalSize; - other.m_composed.clear(); - } - - std::vector<const IGenerator<T>*> m_composed; - std::string m_fileInfo; - size_t m_totalSize; -}; - -namespace Generators -{ - template<typename T> - CompositeGenerator<T> between( T from, T to ) { - CompositeGenerator<T> generators; - generators.add( new BetweenGenerator<T>( from, to ) ); - return generators; - } - - template<typename T> - CompositeGenerator<T> values( T val1, T val2 ) { - CompositeGenerator<T> generators; - ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); - valuesGen->add( val1 ); - valuesGen->add( val2 ); - generators.add( valuesGen ); - return generators; - } - - template<typename T> - CompositeGenerator<T> values( T val1, T val2, T val3 ){ - CompositeGenerator<T> generators; - ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); - valuesGen->add( val1 ); - valuesGen->add( val2 ); - valuesGen->add( val3 ); - generators.add( valuesGen ); - return generators; - } - - template<typename T> - CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) { - CompositeGenerator<T> generators; - ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); - valuesGen->add( val1 ); - valuesGen->add( val2 ); - valuesGen->add( val3 ); - valuesGen->add( val4 ); - generators.add( valuesGen ); - return generators; - } - -} // end namespace Generators - -using namespace Generators; - -} // end namespace Catch - -#define INTERNAL_CATCH_LINESTR2( line ) #line -#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) - -#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) - -// #included from: internal/catch_interfaces_exception.h -#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED - -#include <string> - -namespace Catch { - - typedef std::string(*exceptionTranslateFunction)(); - - struct IExceptionTranslator { - virtual ~IExceptionTranslator(); - virtual std::string translate() const = 0; - }; - - struct IExceptionTranslatorRegistry { - virtual ~IExceptionTranslatorRegistry(); - - virtual std::string translateActiveException() const = 0; - }; - - class ExceptionTranslatorRegistrar { - template<typename T> - class ExceptionTranslator : public IExceptionTranslator { - public: - - ExceptionTranslator( std::string(*translateFunction)( T& ) ) - : m_translateFunction( translateFunction ) - {} - - virtual std::string translate() const { - try { - throw; - } - catch( T& ex ) { - return m_translateFunction( ex ); - } - } - - protected: - std::string(*m_translateFunction)( T& ); - }; - - public: - template<typename T> - ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { - getMutableRegistryHub().registerTranslator - ( new ExceptionTranslator<T>( translateFunction ) ); - } - }; -} - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \ - static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \ - namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\ - static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ) - -// #included from: internal/catch_approx.hpp -#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED - -#include <cmath> -#include <limits> - -namespace Catch { -namespace Detail { - - class Approx { - public: - explicit Approx ( double value ) - : m_epsilon( std::numeric_limits<float>::epsilon()*100 ), - m_scale( 1.0 ), - m_value( value ) - {} - - Approx( Approx const& other ) - : m_epsilon( other.m_epsilon ), - m_scale( other.m_scale ), - m_value( other.m_value ) - {} - - static Approx custom() { - return Approx( 0 ); - } - - Approx operator()( double value ) { - Approx approx( value ); - approx.epsilon( m_epsilon ); - approx.scale( m_scale ); - return approx; - } - - friend bool operator == ( double lhs, Approx const& rhs ) { - // Thanks to Richard Harris for his help refining this formula - return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); - } - - friend bool operator == ( Approx const& lhs, double rhs ) { - return operator==( rhs, lhs ); - } - - friend bool operator != ( double lhs, Approx const& rhs ) { - return !operator==( lhs, rhs ); - } - - friend bool operator != ( Approx const& lhs, double rhs ) { - return !operator==( rhs, lhs ); - } - - Approx& epsilon( double newEpsilon ) { - m_epsilon = newEpsilon; - return *this; - } - - Approx& scale( double newScale ) { - m_scale = newScale; - return *this; - } - - std::string toString() const { - std::ostringstream oss; - oss << "Approx( " << Catch::toString( m_value ) << " )"; - return oss.str(); - } - - private: - double m_epsilon; - double m_scale; - double m_value; - }; -} - -template<> -inline std::string toString<Detail::Approx>( Detail::Approx const& value ) { - return value.toString(); -} - -} // end namespace Catch - -// #included from: internal/catch_matchers.hpp -#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED - -namespace Catch { -namespace Matchers { - namespace Impl { - - template<typename ExpressionT> - struct Matcher : SharedImpl<IShared> - { - typedef ExpressionT ExpressionType; - - virtual ~Matcher() {} - virtual Ptr<Matcher> clone() const = 0; - virtual bool match( ExpressionT const& expr ) const = 0; - virtual std::string toString() const = 0; - }; - - template<typename DerivedT, typename ExpressionT> - struct MatcherImpl : Matcher<ExpressionT> { - - virtual Ptr<Matcher<ExpressionT> > clone() const { - return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) ); - } - }; - - namespace Generic { - - template<typename ExpressionT> - class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> { - public: - - AllOf() {} - AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} - - AllOf& add( Matcher<ExpressionT> const& matcher ) { - m_matchers.push_back( matcher.clone() ); - return *this; - } - virtual bool match( ExpressionT const& expr ) const - { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) - if( !m_matchers[i]->match( expr ) ) - return false; - return true; - } - virtual std::string toString() const { - std::ostringstream oss; - oss << "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) - oss << " and "; - oss << m_matchers[i]->toString(); - } - oss << " )"; - return oss.str(); - } - - private: - std::vector<Ptr<Matcher<ExpressionT> > > m_matchers; - }; - - template<typename ExpressionT> - class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> { - public: - - AnyOf() {} - AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} - - AnyOf& add( Matcher<ExpressionT> const& matcher ) { - m_matchers.push_back( matcher.clone() ); - return *this; - } - virtual bool match( ExpressionT const& expr ) const - { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) - if( m_matchers[i]->match( expr ) ) - return true; - return false; - } - virtual std::string toString() const { - std::ostringstream oss; - oss << "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) - oss << " or "; - oss << m_matchers[i]->toString(); - } - oss << " )"; - return oss.str(); - } - - private: - std::vector<Ptr<Matcher<ExpressionT> > > m_matchers; - }; - - } - - namespace StdString { - - inline std::string makeString( std::string const& str ) { return str; } - inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } - - struct Equals : MatcherImpl<Equals, std::string> { - Equals( std::string const& str ) : m_str( str ){} - Equals( Equals const& other ) : m_str( other.m_str ){} - - virtual ~Equals(); - - virtual bool match( std::string const& expr ) const { - return m_str == expr; - } - virtual std::string toString() const { - return "equals: \"" + m_str + "\""; - } - - std::string m_str; - }; - - struct Contains : MatcherImpl<Contains, std::string> { - Contains( std::string const& substr ) : m_substr( substr ){} - Contains( Contains const& other ) : m_substr( other.m_substr ){} - - virtual ~Contains(); - - virtual bool match( std::string const& expr ) const { - return expr.find( m_substr ) != std::string::npos; - } - virtual std::string toString() const { - return "contains: \"" + m_substr + "\""; - } - - std::string m_substr; - }; - - struct StartsWith : MatcherImpl<StartsWith, std::string> { - StartsWith( std::string const& substr ) : m_substr( substr ){} - StartsWith( StartsWith const& other ) : m_substr( other.m_substr ){} - - virtual ~StartsWith(); - - virtual bool match( std::string const& expr ) const { - return expr.find( m_substr ) == 0; - } - virtual std::string toString() const { - return "starts with: \"" + m_substr + "\""; - } - - std::string m_substr; - }; - - struct EndsWith : MatcherImpl<EndsWith, std::string> { - EndsWith( std::string const& substr ) : m_substr( substr ){} - EndsWith( EndsWith const& other ) : m_substr( other.m_substr ){} - - virtual ~EndsWith(); - - virtual bool match( std::string const& expr ) const { - return expr.find( m_substr ) == expr.size() - m_substr.size(); - } - virtual std::string toString() const { - return "ends with: \"" + m_substr + "\""; - } - - std::string m_substr; - }; - } // namespace StdString - } // namespace Impl - - // The following functions create the actual matcher objects. - // This allows the types to be inferred - template<typename ExpressionT> - inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1, - Impl::Matcher<ExpressionT> const& m2 ) { - return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ); - } - template<typename ExpressionT> - inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1, - Impl::Matcher<ExpressionT> const& m2, - Impl::Matcher<ExpressionT> const& m3 ) { - return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 ); - } - template<typename ExpressionT> - inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1, - Impl::Matcher<ExpressionT> const& m2 ) { - return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ); - } - template<typename ExpressionT> - inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1, - Impl::Matcher<ExpressionT> const& m2, - Impl::Matcher<ExpressionT> const& m3 ) { - return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 ); - } - - inline Impl::StdString::Equals Equals( std::string const& str ) { - return Impl::StdString::Equals( str ); - } - inline Impl::StdString::Equals Equals( const char* str ) { - return Impl::StdString::Equals( Impl::StdString::makeString( str ) ); - } - inline Impl::StdString::Contains Contains( std::string const& substr ) { - return Impl::StdString::Contains( substr ); - } - inline Impl::StdString::Contains Contains( const char* substr ) { - return Impl::StdString::Contains( Impl::StdString::makeString( substr ) ); - } - inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { - return Impl::StdString::StartsWith( substr ); - } - inline Impl::StdString::StartsWith StartsWith( const char* substr ) { - return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); - } - inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { - return Impl::StdString::EndsWith( substr ); - } - inline Impl::StdString::EndsWith EndsWith( const char* substr ) { - return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); - } - -} // namespace Matchers - -using namespace Matchers; - -} // namespace Catch - -// These files are included here so the single_include script doesn't put them -// in the conditionally compiled sections -// #included from: internal/catch_test_case_info.h -#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED - -#include <string> -#include <set> - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -namespace Catch { - - struct ITestCase; - - struct TestCaseInfo { - TestCaseInfo( std::string const& _name, - std::string const& _className, - std::string const& _description, - std::set<std::string> const& _tags, - bool _isHidden, - SourceLineInfo const& _lineInfo ); - - TestCaseInfo( TestCaseInfo const& other ); - - std::string name; - std::string className; - std::string description; - std::set<std::string> tags; - std::string tagsAsString; - SourceLineInfo lineInfo; - bool isHidden; - }; - - class TestCase : protected TestCaseInfo { - public: - - TestCase( ITestCase* testCase, TestCaseInfo const& info ); - TestCase( TestCase const& other ); - - TestCase withName( std::string const& _newName ) const; - - void invoke() const; - - TestCaseInfo const& getTestCaseInfo() const; - - bool isHidden() const; - bool hasTag( std::string const& tag ) const; - bool matchesTags( std::string const& tagPattern ) const; - std::set<std::string> const& getTags() const; - - void swap( TestCase& other ); - bool operator == ( TestCase const& other ) const; - bool operator < ( TestCase const& other ) const; - TestCase& operator = ( TestCase const& other ); - - private: - Ptr<ITestCase> test; - }; - - TestCase makeTestCase( ITestCase* testCase, - std::string const& className, - std::string const& name, - std::string const& description, - SourceLineInfo const& lineInfo ); -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -// #included from: internal/catch_interfaces_runner.h -#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED - -namespace Catch { - class TestCase; - - struct IRunner { - virtual ~IRunner(); - }; -} - - -#ifdef __OBJC__ -// #included from: internal/catch_objc.hpp -#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED - -#import <objc/runtime.h> - -#include <string> - -// NB. Any general catch headers included here must be included -// in catch.hpp first to make sure they are included by the single -// header for non obj-usage - -/////////////////////////////////////////////////////////////////////////////// -// This protocol is really only here for (self) documenting purposes, since -// all its methods are optional. -@protocol OcFixture - -@optional - --(void) setUp; --(void) tearDown; - -@end - -namespace Catch { - - class OcMethod : public SharedImpl<ITestCase> { - - public: - OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} - - virtual void invoke() const { - id obj = [[m_cls alloc] init]; - - performOptionalSelector( obj, @selector(setUp) ); - performOptionalSelector( obj, m_sel ); - performOptionalSelector( obj, @selector(tearDown) ); - - arcSafeRelease( obj ); - } - private: - virtual ~OcMethod() {} - - Class m_cls; - SEL m_sel; - }; - - namespace Detail{ - - inline std::string getAnnotation( Class cls, - std::string const& annotationName, - std::string const& testCaseName ) { - NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; - SEL sel = NSSelectorFromString( selStr ); - arcSafeRelease( selStr ); - id value = performOptionalSelector( cls, sel ); - if( value ) - return [(NSString*)value UTF8String]; - return ""; - } - } - - inline size_t registerTestMethods() { - size_t noTestMethods = 0; - int noClasses = objc_getClassList( NULL, 0 ); - - Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); - objc_getClassList( classes, noClasses ); - - for( int c = 0; c < noClasses; c++ ) { - Class cls = classes[c]; - { - u_int count; - Method* methods = class_copyMethodList( cls, &count ); - for( u_int m = 0; m < count ; m++ ) { - SEL selector = method_getName(methods[m]); - std::string methodName = sel_getName(selector); - if( startsWith( methodName, "Catch_TestCase_" ) ) { - std::string testCaseName = methodName.substr( 15 ); - std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); - std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); - const char* className = class_getName( cls ); - - getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); - noTestMethods++; - } - } - free(methods); - } - } - return noTestMethods; - } - - namespace Matchers { - namespace Impl { - namespace NSStringMatchers { - - template<typename MatcherT> - struct StringHolder : MatcherImpl<MatcherT, NSString*>{ - StringHolder( NSString* substr ) : m_substr( [substr copy] ){} - StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} - StringHolder() { - arcSafeRelease( m_substr ); - } - - NSString* m_substr; - }; - - struct Equals : StringHolder<Equals> { - Equals( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( ExpressionType const& str ) const { - return (str != nil || m_substr == nil ) && - [str isEqualToString:m_substr]; - } - - virtual std::string toString() const { - return "equals string: \"" + Catch::toString( m_substr ) + "\""; - } - }; - - struct Contains : StringHolder<Contains> { - Contains( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( ExpressionType const& str ) const { - return (str != nil || m_substr == nil ) && - [str rangeOfString:m_substr].location != NSNotFound; - } - - virtual std::string toString() const { - return "contains string: \"" + Catch::toString( m_substr ) + "\""; - } - }; - - struct StartsWith : StringHolder<StartsWith> { - StartsWith( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( ExpressionType const& str ) const { - return (str != nil || m_substr == nil ) && - [str rangeOfString:m_substr].location == 0; - } - - virtual std::string toString() const { - return "starts with: \"" + Catch::toString( m_substr ) + "\""; - } - }; - struct EndsWith : StringHolder<EndsWith> { - EndsWith( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( ExpressionType const& str ) const { - return (str != nil || m_substr == nil ) && - [str rangeOfString:m_substr].location == [str length] - [m_substr length]; - } - - virtual std::string toString() const { - return "ends with: \"" + Catch::toString( m_substr ) + "\""; - } - }; - - } // namespace NSStringMatchers - } // namespace Impl - - inline Impl::NSStringMatchers::Equals - Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } - - inline Impl::NSStringMatchers::Contains - Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } - - inline Impl::NSStringMatchers::StartsWith - StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } - - inline Impl::NSStringMatchers::EndsWith - EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } - - } // namespace Matchers - - using namespace Matchers; - -} // namespace Catch - -/////////////////////////////////////////////////////////////////////////////// -#define OC_TEST_CASE( name, desc )\ -+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ -{\ -return @ name; \ -}\ -+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ -{ \ -return @ desc; \ -} \ --(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) - -#endif - -#if defined( CATCH_CONFIG_MAIN ) || defined( CATCH_CONFIG_RUNNER ) -// #included from: internal/catch_impl.hpp -#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED - -// Collect all the implementation files together here -// These are the equivalent of what would usually be cpp files - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wweak-vtables" -#endif - -// #included from: catch_runner.hpp -#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED - -// #included from: internal/catch_commandline.hpp -#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED - -// #included from: catch_config.hpp -#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED - -// #included from: catch_test_spec.h -#define TWOBLUECUBES_CATCH_TEST_SPEC_H_INCLUDED - -// #included from: catch_tags.h -#define TWOBLUECUBES_CATCH_TAGS_H_INCLUDED - -#include <string> -#include <set> -#include <map> -#include <vector> - -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wpadded" -#endif - -namespace Catch { - class TagParser { - public: - virtual ~TagParser(); - - void parse( std::string const& str ); - - protected: - virtual void acceptTag( std::string const& tag ) = 0; - virtual void acceptChar( char c ) = 0; - virtual void endParse() {} - - private: - }; - - class TagExtracter : public TagParser { - public: - - TagExtracter( std::set<std::string>& tags ); - virtual ~TagExtracter(); - - void parse( std::string& description ); - - private: - virtual void acceptTag( std::string const& tag ); - virtual void acceptChar( char c ); - - TagExtracter& operator=(TagExtracter const&); - - std::set<std::string>& m_tags; - std::string m_remainder; - }; - - class Tag { - public: - Tag(); - Tag( std::string const& name, bool isNegated ); - std::string getName() const; - bool isNegated() const; - bool operator ! () const; - - private: - std::string m_name; - bool m_isNegated; - }; - - class TagSet { - typedef std::map<std::string, Tag> TagMap; - public: - void add( Tag const& tag ); - bool empty() const; - bool matches( std::set<std::string> const& tags ) const; - - private: - TagMap m_tags; - }; - - class TagExpression { - public: - bool matches( std::set<std::string> const& tags ) const; - - private: - friend class TagExpressionParser; - - std::vector<TagSet> m_tagSets; - }; - - class TagExpressionParser : public TagParser { - public: - TagExpressionParser( TagExpression& exp ); - ~TagExpressionParser(); - - private: - virtual void acceptTag( std::string const& tag ); - virtual void acceptChar( char c ); - virtual void endParse(); - - TagExpressionParser& operator=(TagExpressionParser const&); - - bool m_isNegated; - TagSet m_currentTagSet; - TagExpression& m_exp; - }; - -} // end namespace Catch - -#include <string> -#include <vector> - -namespace Catch { - - class TestCase; - - struct IfFilterMatches{ enum DoWhat { - AutoDetectBehaviour, - IncludeTests, - ExcludeTests - }; }; - - class TestCaseFilter { - enum WildcardPosition { - NoWildcard = 0, - WildcardAtStart = 1, - WildcardAtEnd = 2, - WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd - }; - - public: - TestCaseFilter( std::string const& testSpec, IfFilterMatches::DoWhat matchBehaviour = IfFilterMatches::AutoDetectBehaviour ); - - IfFilterMatches::DoWhat getFilterType() const; - bool shouldInclude( TestCase const& testCase ) const; - - private: - bool isMatch( TestCase const& testCase ) const; - - std::string m_stringToMatch; - IfFilterMatches::DoWhat m_filterType; - WildcardPosition m_wildcardPosition; - }; - - class TestCaseFilters { - public: - TestCaseFilters( std::string const& name ); - std::string getName() const; - void addFilter( TestCaseFilter const& filter ); - void addTags( std::string const& tagPattern ); - bool shouldInclude( TestCase const& testCase ) const; - - private: - std::vector<TagExpression> m_tagExpressions; - std::vector<TestCaseFilter> m_inclusionFilters; - std::vector<TestCaseFilter> m_exclusionFilters; - std::string m_name; - }; - -} - -// #included from: catch_stream.h -#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED - -#include <streambuf> - -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wpadded" -#endif - -namespace Catch { - - class Stream { - public: - Stream(); - Stream( std::streambuf* _streamBuf, bool _isOwned ); - void release(); - - std::streambuf* streamBuf; - - private: - bool isOwned; - }; -} - -#include <memory> -#include <vector> -#include <string> -#include <iostream> - -#ifndef CATCH_CONFIG_CONSOLE_WIDTH -#define CATCH_CONFIG_CONSOLE_WIDTH 80 -#endif - -namespace Catch { - - struct ConfigData { - - ConfigData() - : listTests( false ), - listTags( false ), - listReporters( false ), - listTestNamesOnly( false ), - showSuccessfulTests( false ), - shouldDebugBreak( false ), - noThrow( false ), - showHelp( false ), - abortAfter( -1 ), - verbosity( Verbosity::Normal ), - warnings( WarnAbout::Nothing ), - showDurations( ShowDurations::DefaultForReporter ) - {} - - bool listTests; - bool listTags; - bool listReporters; - bool listTestNamesOnly; - - bool showSuccessfulTests; - bool shouldDebugBreak; - bool noThrow; - bool showHelp; - - int abortAfter; - - Verbosity::Level verbosity; - WarnAbout::What warnings; - ShowDurations::OrNot showDurations; - - std::string reporterName; - std::string outputFilename; - std::string name; - std::string processName; - - std::vector<std::string> testsOrTags; - }; - - class Config : public SharedImpl<IConfig> { - private: - Config( Config const& other ); - Config& operator = ( Config const& other ); - virtual void dummy(); - public: - - Config() - : m_os( std::cout.rdbuf() ) - {} - - Config( ConfigData const& data ) - : m_data( data ), - m_os( std::cout.rdbuf() ) - { - if( !data.testsOrTags.empty() ) { - std::string groupName; - for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) { - if( i != 0 ) - groupName += " "; - groupName += data.testsOrTags[i]; - } - TestCaseFilters filters( groupName ); - for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) { - std::string filter = data.testsOrTags[i]; - if( startsWith( filter, "[" ) || startsWith( filter, "~[" ) ) - filters.addTags( filter ); - else - filters.addFilter( TestCaseFilter( filter ) ); - } - m_filterSets.push_back( filters ); - } - } - - virtual ~Config() { - m_os.rdbuf( std::cout.rdbuf() ); - m_stream.release(); - } - - void setFilename( std::string const& filename ) { - m_data.outputFilename = filename; - } - - std::string const& getFilename() const { - return m_data.outputFilename ; - } - - bool listTests() const { return m_data.listTests; } - bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } - bool listTags() const { return m_data.listTags; } - bool listReporters() const { return m_data.listReporters; } - - std::string getProcessName() const { - return m_data.processName; - } - - bool shouldDebugBreak() const { - return m_data.shouldDebugBreak; - } - - void setStreamBuf( std::streambuf* buf ) { - m_os.rdbuf( buf ? buf : std::cout.rdbuf() ); - } - - void useStream( std::string const& streamName ) { - Stream stream = createStream( streamName ); - setStreamBuf( stream.streamBuf ); - m_stream.release(); - m_stream = stream; - } - - std::string getReporterName() const { return m_data.reporterName; } - - void addTestSpec( std::string const& testSpec ) { - TestCaseFilters filters( testSpec ); - filters.addFilter( TestCaseFilter( testSpec ) ); - m_filterSets.push_back( filters ); - } - - int abortAfter() const { - return m_data.abortAfter; - } - - std::vector<TestCaseFilters> const& filters() const { - return m_filterSets; - } - - bool showHelp() const { return m_data.showHelp; } - - // IConfig interface - virtual bool allowThrows() const { return !m_data.noThrow; } - virtual std::ostream& stream() const { return m_os; } - virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } - virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } - virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } - virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } - - private: - ConfigData m_data; - - Stream m_stream; - mutable std::ostream m_os; - std::vector<TestCaseFilters> m_filterSets; - }; - -} // end namespace Catch - -// #included from: catch_clara.h -#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED - -#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH - -// Declare Clara inside the Catch namespace -#define STITCH_CLARA_OUTER_NAMESPACE Catch -// #included from: clara.h - -// Only use header guard if we are not using an outer namespace -#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OUTER_NAMESPACE) -#ifndef STITCH_CLARA_OUTER_NAMESPACE -#define TWOBLUECUBES_CLARA_H_INCLUDED -#endif - -#define STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE Clara - -// ----------- #included from tbc_text_format.h ----------- - -// Only use header guard if we are not using an outer namespace -#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) -#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE -#define TBC_TEXT_FORMAT_H_INCLUDED -#endif - -#include <string> -#include <vector> -#include <sstream> - -// Use optional outer namespace -#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE -namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { -#endif - -namespace Tbc { - -#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH - const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; -#else - const unsigned int consoleWidth = 80; -#endif - - struct TextAttributes { - TextAttributes() - : initialIndent( std::string::npos ), - indent( 0 ), - width( consoleWidth-1 ), - tabChar( '\t' ) - {} - - TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } - TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } - TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } - TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } - - std::size_t initialIndent; // indent of first line, or npos - std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos - std::size_t width; // maximum width of text, including indent. Longer text will wrap - char tabChar; // If this char is seen the indent is changed to current pos - }; - - class Text { - public: - Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) - : attr( _attr ) - { - std::string wrappableChars = " [({.,/|\\-"; - std::size_t indent = _attr.initialIndent != std::string::npos - ? _attr.initialIndent - : _attr.indent; - std::string remainder = _str; - - while( !remainder.empty() ) { - if( lines.size() >= 1000 ) { - lines.push_back( "... message truncated due to excessive size" ); - return; - } - std::size_t tabPos = std::string::npos; - std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); - std::size_t pos = remainder.find_first_of( '\n' ); - if( pos <= width ) { - width = pos; - } - pos = remainder.find_last_of( _attr.tabChar, width ); - if( pos != std::string::npos ) { - tabPos = pos; - if( remainder[width] == '\n' ) - width--; - remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); - } - - if( width == remainder.size() ) { - spliceLine( indent, remainder, width ); - } - else if( remainder[width] == '\n' ) { - spliceLine( indent, remainder, width ); - if( width <= 1 || remainder.size() != 1 ) - remainder = remainder.substr( 1 ); - indent = _attr.indent; - } - else { - pos = remainder.find_last_of( wrappableChars, width ); - if( pos != std::string::npos && pos > 0 ) { - spliceLine( indent, remainder, pos ); - if( remainder[0] == ' ' ) - remainder = remainder.substr( 1 ); - } - else { - spliceLine( indent, remainder, width-1 ); - lines.back() += "-"; - } - if( lines.size() == 1 ) - indent = _attr.indent; - if( tabPos != std::string::npos ) - indent += tabPos; - } - } - } - - void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { - lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); - _remainder = _remainder.substr( _pos ); - } - - typedef std::vector<std::string>::const_iterator const_iterator; - - const_iterator begin() const { return lines.begin(); } - const_iterator end() const { return lines.end(); } - std::string const& last() const { return lines.back(); } - std::size_t size() const { return lines.size(); } - std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } - std::string toString() const { - std::ostringstream oss; - oss << *this; - return oss.str(); - } - - inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { - for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); - it != itEnd; ++it ) { - if( it != _text.begin() ) - _stream << "\n"; - _stream << *it; - } - return _stream; - } - - private: - std::string str; - TextAttributes attr; - std::vector<std::string> lines; - }; - -} // end namespace Tbc - -#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE -} // end outer namespace -#endif - -#endif // TBC_TEXT_FORMAT_H_INCLUDED - -// ----------- end of #include from tbc_text_format.h ----------- -// ........... back in /Users/philnash/Dev/OSS/Clara/srcs/clara.h - -#undef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE - -#include <map> -#include <algorithm> -#include <stdexcept> -#include <memory> - -// Use optional outer namespace -#ifdef STITCH_CLARA_OUTER_NAMESPACE -namespace STITCH_CLARA_OUTER_NAMESPACE { -#endif - -namespace Clara { - namespace Detail { - -#ifdef CLARA_CONSOLE_WIDTH - const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; -#else - const unsigned int consoleWidth = 80; -#endif - - using namespace ::Clara::Tbc; - - template<typename T> struct RemoveConstRef{ typedef T type; }; - template<typename T> struct RemoveConstRef<T&>{ typedef T type; }; - template<typename T> struct RemoveConstRef<T const&>{ typedef T type; }; - template<typename T> struct RemoveConstRef<T const>{ typedef T type; }; - - template<typename T> struct IsBool { static const bool value = false; }; - template<> struct IsBool<bool> { static const bool value = true; }; - - template<typename T> - void convertInto( std::string const& _source, T& _dest ) { - std::stringstream ss; - ss << _source; - ss >> _dest; - if( ss.fail() ) - throw std::runtime_error( "Unable to convert " + _source + " to destination type" ); - } - inline void convertInto( std::string const& _source, std::string& _dest ) { - _dest = _source; - } - inline void convertInto( std::string const& _source, bool& _dest ) { - std::string sourceLC = _source; - std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower ); - if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) - _dest = true; - else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) - _dest = false; - else - throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); - } - inline void convertInto( bool _source, bool& _dest ) { - _dest = _source; - } - template<typename T> - inline void convertInto( bool, T& ) { - throw std::runtime_error( "Invalid conversion" ); - } - - template<typename ConfigT> - struct IArgFunction { - virtual ~IArgFunction() {} - virtual void set( ConfigT& config, std::string const& value ) const = 0; - virtual void setFlag( ConfigT& config ) const = 0; - virtual bool takesArg() const = 0; - virtual IArgFunction* clone() const = 0; - }; - - template<typename ConfigT> - class BoundArgFunction { - public: - BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {} - BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj->clone() ) {} - BoundArgFunction& operator = ( BoundArgFunction const& other ) { - IArgFunction<ConfigT>* newFunctionObj = other.functionObj->clone(); - delete functionObj; - functionObj = newFunctionObj; - return *this; - } - ~BoundArgFunction() { delete functionObj; } - - void set( ConfigT& config, std::string const& value ) const { - functionObj->set( config, value ); - } - void setFlag( ConfigT& config ) const { - functionObj->setFlag( config ); - } - bool takesArg() const { return functionObj->takesArg(); } - private: - IArgFunction<ConfigT>* functionObj; - }; - - template<typename C> - struct NullBinder : IArgFunction<C>{ - virtual void set( C&, std::string const& ) const {} - virtual void setFlag( C& ) const {} - virtual bool takesArg() const { return true; } - virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); } - }; - - template<typename C, typename M> - struct BoundDataMember : IArgFunction<C>{ - BoundDataMember( M C::* _member ) : member( _member ) {} - virtual void set( C& p, std::string const& stringValue ) const { - convertInto( stringValue, p.*member ); - } - virtual void setFlag( C& p ) const { - convertInto( true, p.*member ); - } - virtual bool takesArg() const { return !IsBool<M>::value; } - virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); } - M C::* member; - }; - template<typename C, typename M> - struct BoundUnaryMethod : IArgFunction<C>{ - BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} - virtual void set( C& p, std::string const& stringValue ) const { - typename RemoveConstRef<M>::type value; - convertInto( stringValue, value ); - (p.*member)( value ); - } - virtual void setFlag( C& p ) const { - typename RemoveConstRef<M>::type value; - convertInto( true, value ); - (p.*member)( value ); - } - virtual bool takesArg() const { return !IsBool<M>::value; } - virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); } - void (C::*member)( M ); - }; - template<typename C> - struct BoundNullaryMethod : IArgFunction<C>{ - BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} - virtual void set( C& p, std::string const& stringValue ) const { - bool value; - convertInto( stringValue, value ); - if( value ) - (p.*member)(); - } - virtual void setFlag( C& p ) const { - (p.*member)(); - } - virtual bool takesArg() const { return false; } - virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); } - void (C::*member)(); - }; - - template<typename C> - struct BoundUnaryFunction : IArgFunction<C>{ - BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} - virtual void set( C& obj, std::string const& stringValue ) const { - bool value; - convertInto( stringValue, value ); - if( value ) - function( obj ); - } - virtual void setFlag( C& p ) const { - function( p ); - } - virtual bool takesArg() const { return false; } - virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); } - void (*function)( C& ); - }; - - template<typename C, typename T> - struct BoundBinaryFunction : IArgFunction<C>{ - BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} - virtual void set( C& obj, std::string const& stringValue ) const { - typename RemoveConstRef<T>::type value; - convertInto( stringValue, value ); - function( obj, value ); - } - virtual void setFlag( C& obj ) const { - typename RemoveConstRef<T>::type value; - convertInto( true, value ); - function( obj, value ); - } - virtual bool takesArg() const { return !IsBool<T>::value; } - virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); } - void (*function)( C&, T ); - }; - - template<typename C, typename M> - BoundArgFunction<C> makeBoundField( M C::* _member ) { - return BoundArgFunction<C>( new BoundDataMember<C,M>( _member ) ); - } - template<typename C, typename M> - BoundArgFunction<C> makeBoundField( void (C::*_member)( M ) ) { - return BoundArgFunction<C>( new BoundUnaryMethod<C,M>( _member ) ); - } - template<typename C> - BoundArgFunction<C> makeBoundField( void (C::*_member)() ) { - return BoundArgFunction<C>( new BoundNullaryMethod<C>( _member ) ); - } - template<typename C> - BoundArgFunction<C> makeBoundField( void (*_function)( C& ) ) { - return BoundArgFunction<C>( new BoundUnaryFunction<C>( _function ) ); - } - template<typename C, typename T> - BoundArgFunction<C> makeBoundField( void (*_function)( C&, T ) ) { - return BoundArgFunction<C>( new BoundBinaryFunction<C, T>( _function ) ); - } - } // namespace Detail - - struct Parser { - Parser() : separators( " \t=:" ) {} - - struct Token { - enum Type { Positional, ShortOpt, LongOpt }; - Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} - Type type; - std::string data; - }; - - void parseIntoTokens( int argc, char const * const * argv, std::vector<Parser::Token>& tokens ) const { - const std::string doubleDash = "--"; - for( int i = 1; i < argc && argv[i] != doubleDash; ++i ) - parseIntoTokens( argv[i] , tokens); - } - void parseIntoTokens( std::string arg, std::vector<Parser::Token>& tokens ) const { - while( !arg.empty() ) { - Parser::Token token( Parser::Token::Positional, arg ); - arg = ""; - if( token.data[0] == '-' ) { - if( token.data.size() > 1 && token.data[1] == '-' ) { - token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) ); - } - else { - token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) ); - if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) { - arg = "-" + token.data.substr( 1 ); - token.data = token.data.substr( 0, 1 ); - } - } - } - if( token.type != Parser::Token::Positional ) { - std::size_t pos = token.data.find_first_of( separators ); - if( pos != std::string::npos ) { - arg = token.data.substr( pos+1 ); - token.data = token.data.substr( 0, pos ); - } - } - tokens.push_back( token ); - } - } - std::string separators; - }; - - template<typename ConfigT> - class CommandLine { - - struct Arg { - Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ), position( -1 ) {} - - bool hasShortName( std::string const& shortName ) const { - for( std::vector<std::string>::const_iterator - it = shortNames.begin(), itEnd = shortNames.end(); - it != itEnd; - ++it ) - if( *it == shortName ) - return true; - return false; - } - bool hasLongName( std::string const& _longName ) const { - return _longName == longName; - } - bool takesArg() const { - return !hint.empty(); - } - bool isFixedPositional() const { - return position != -1; - } - bool isAnyPositional() const { - return position == -1 && shortNames.empty() && longName.empty(); - } - std::string dbgName() const { - if( !longName.empty() ) - return "--" + longName; - if( !shortNames.empty() ) - return "-" + shortNames[0]; - return "positional args"; - } - void validate() const { - if( boundField.takesArg() && !takesArg() ) - throw std::logic_error( "command line argument '" + dbgName() + "' must specify a hint" ); - } - std::string commands() const { - std::ostringstream oss; - bool first = true; - std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end(); - for(; it != itEnd; ++it ) { - if( first ) - first = false; - else - oss << ", "; - oss << "-" << *it; - } - if( !longName.empty() ) { - if( !first ) - oss << ", "; - oss << "--" << longName; - } - if( !hint.empty() ) - oss << " <" << hint << ">"; - return oss.str(); - } - - Detail::BoundArgFunction<ConfigT> boundField; - std::vector<std::string> shortNames; - std::string longName; - std::string description; - std::string hint; - int position; - }; - - // NOTE: std::auto_ptr is deprecated in c++11/c++0x -#if defined(__cplusplus) && __cplusplus > 199711L - typedef std::unique_ptr<Arg> ArgAutoPtr; -#else - typedef std::auto_ptr<Arg> ArgAutoPtr; -#endif - - class ArgBinder { - public: - template<typename F> - ArgBinder( CommandLine* cl, F f ) - : m_cl( cl ), - m_arg( Detail::makeBoundField( f ) ) - {} - ArgBinder( ArgBinder& other ) - : m_cl( other.m_cl ), - m_arg( other.m_arg ) - { - other.m_cl = NULL; - } - // !TBD: Need to include workarounds to be able to declare this - // destructor as able to throw exceptions - ~ArgBinder() noexcept(false) { - if( m_cl && !std::uncaught_exception() ) { - m_arg.validate(); - if( m_arg.isFixedPositional() ) { - m_cl->m_positionalArgs.insert( std::make_pair( m_arg.position, m_arg ) ); - if( m_arg.position > m_cl->m_highestSpecifiedArgPosition ) - m_cl->m_highestSpecifiedArgPosition = m_arg.position; - } - else if( m_arg.isAnyPositional() ) { - if( m_cl->m_arg.get() ) - throw std::logic_error( "Only one unpositional argument can be added" ); - m_cl->m_arg = ArgAutoPtr( new Arg( m_arg ) ); - } - else - m_cl->m_options.push_back( m_arg ); - } - } - ArgBinder& shortOpt( std::string const& name ) { - m_arg.shortNames.push_back( name ); - return *this; - } - ArgBinder& longOpt( std::string const& name ) { - m_arg.longName = name; - return *this; - } - ArgBinder& describe( std::string const& description ) { - m_arg.description = description; - return *this; - } - ArgBinder& hint( std::string const& hint ) { - m_arg.hint = hint; - return *this; - } - ArgBinder& position( int position ) { - m_arg.position = position; - return *this; - } - private: - CommandLine* m_cl; - Arg m_arg; - }; - - public: - - CommandLine() - : m_boundProcessName( new Detail::NullBinder<ConfigT>() ), - m_highestSpecifiedArgPosition( 0 ), - m_throwOnUnrecognisedTokens( false ) - {} - CommandLine( CommandLine const& other ) - : m_boundProcessName( other.m_boundProcessName ), - m_options ( other.m_options ), - m_positionalArgs( other.m_positionalArgs ), - m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), - m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) - { - if( other.m_arg.get() ) - m_arg = ArgAutoPtr( new Arg( *other.m_arg ) ); - } - - CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { - m_throwOnUnrecognisedTokens = shouldThrow; - return *this; - } - - template<typename F> - ArgBinder bind( F f ) { - ArgBinder binder( this, f ); - return binder; - } - template<typename F> - void bindProcessName( F f ) { - m_boundProcessName = Detail::makeBoundField( f ); - } - - void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { - typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; - std::size_t maxWidth = 0; - for( it = itBegin; it != itEnd; ++it ) - maxWidth = (std::max)( maxWidth, it->commands().size() ); - - for( it = itBegin; it != itEnd; ++it ) { - Detail::Text usage( it->commands(), Detail::TextAttributes() - .setWidth( maxWidth+indent ) - .setIndent( indent ) ); - // !TBD handle longer usage strings - Detail::Text desc( it->description, Detail::TextAttributes() - .setWidth( width - maxWidth -3 ) ); - - for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { - std::string usageCol = i < usage.size() ? usage[i] : ""; - os << usageCol; - - if( i < desc.size() && !desc[i].empty() ) - os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) - << desc[i]; - os << "\n"; - } - } - } - std::string optUsage() const { - std::ostringstream oss; - optUsage( oss ); - return oss.str(); - } - - void argSynopsis( std::ostream& os ) const { - for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { - if( i > 1 ) - os << " "; - typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i ); - if( it != m_positionalArgs.end() ) - os << "<" << it->second.hint << ">"; - else if( m_arg.get() ) - os << "<" << m_arg->hint << ">"; - else - throw std::logic_error( "non consecutive positional arguments with no floating args" ); - } - // !TBD No indication of mandatory args - if( m_arg.get() ) { - if( m_highestSpecifiedArgPosition > 1 ) - os << " "; - os << "[<" << m_arg->hint << "> ...]"; - } - } - std::string argSynopsis() const { - std::ostringstream oss; - argSynopsis( oss ); - return oss.str(); - } - - void usage( std::ostream& os, std::string const& procName ) const { - os << "usage:\n " << procName << " "; - argSynopsis( os ); - if( !m_options.empty() ) { - os << " [options]\n\nwhere options are: \n"; - optUsage( os, 2 ); - } - os << "\n"; - } - std::string usage( std::string const& procName ) const { - std::ostringstream oss; - usage( oss, procName ); - return oss.str(); - } - - ConfigT parseInto( int argc, char const * const * argv ) const { - ConfigT config; - parseInto( argc, argv, config ); - return config; - } - - std::vector<Parser::Token> parseInto( int argc, char const * const * argv, ConfigT& config ) const { - std::string processName = argv[0]; - std::size_t lastSlash = processName.find_last_of( "/\\" ); - if( lastSlash != std::string::npos ) - processName = processName.substr( lastSlash+1 ); - m_boundProcessName.set( config, processName ); - std::vector<Parser::Token> tokens; - Parser parser; - parser.parseIntoTokens( argc, argv, tokens ); - return populate( tokens, config ); - } - - std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { - if( m_options.empty() && m_positionalArgs.empty() ) - throw std::logic_error( "No options or arguments specified" ); - - std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config ); - unusedTokens = populateFixedArgs( unusedTokens, config ); - unusedTokens = populateFloatingArgs( unusedTokens, config ); - return unusedTokens; - } - - std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { - std::vector<Parser::Token> unusedTokens; - std::vector<std::string> errors; - for( std::size_t i = 0; i < tokens.size(); ++i ) { - Parser::Token const& token = tokens[i]; - typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end(); - for(; it != itEnd; ++it ) { - Arg const& arg = *it; - - try { - if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || - ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { - if( arg.takesArg() ) { - if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) - errors.push_back( "Expected argument to option: " + token.data ); - else - arg.boundField.set( config, tokens[++i].data ); - } - else { - arg.boundField.setFlag( config ); - } - break; - } - } - catch( std::exception& ex ) { - errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); - } - } - if( it == itEnd ) { - if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) - unusedTokens.push_back( token ); - else if( m_throwOnUnrecognisedTokens ) - errors.push_back( "unrecognised option: " + token.data ); - } - } - if( !errors.empty() ) { - std::ostringstream oss; - for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end(); - it != itEnd; - ++it ) { - if( it != errors.begin() ) - oss << "\n"; - oss << *it; - } - throw std::runtime_error( oss.str() ); - } - return unusedTokens; - } - std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { - std::vector<Parser::Token> unusedTokens; - int position = 1; - for( std::size_t i = 0; i < tokens.size(); ++i ) { - Parser::Token const& token = tokens[i]; - typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position ); - if( it != m_positionalArgs.end() ) - it->second.boundField.set( config, token.data ); - else - unusedTokens.push_back( token ); - if( token.type == Parser::Token::Positional ) - position++; - } - return unusedTokens; - } - std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { - if( !m_arg.get() ) - return tokens; - std::vector<Parser::Token> unusedTokens; - for( std::size_t i = 0; i < tokens.size(); ++i ) { - Parser::Token const& token = tokens[i]; - if( token.type == Parser::Token::Positional ) - m_arg->boundField.set( config, token.data ); - else - unusedTokens.push_back( token ); - } - return unusedTokens; - } - - private: - Detail::BoundArgFunction<ConfigT> m_boundProcessName; - std::vector<Arg> m_options; - std::map<int, Arg> m_positionalArgs; - ArgAutoPtr m_arg; - int m_highestSpecifiedArgPosition; - bool m_throwOnUnrecognisedTokens; - }; - -} // end namespace Clara - -#ifdef STITCH_CLARA_OUTER_NAMESPACE -} // end outer namespace -#endif - -#endif // TWOBLUECUBES_CLARA_H_INCLUDED -#undef STITCH_CLARA_OUTER_NAMESPACE - -#include <fstream> - -namespace Catch { - - inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } - inline void abortAfterX( ConfigData& config, int x ) { - if( x < 1 ) - throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); - config.abortAfter = x; - } - inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } - - inline void addWarning( ConfigData& config, std::string const& _warning ) { - if( _warning == "NoAssertions" ) - config.warnings = (WarnAbout::What)( config.warnings | WarnAbout::NoAssertions ); - else - throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" ); - - } - inline void setVerbosity( ConfigData& config, int level ) { - // !TBD: accept strings? - config.verbosity = (Verbosity::Level)level; - } - inline void setShowDurations( ConfigData& config, bool _showDurations ) { - config.showDurations = _showDurations - ? ShowDurations::Always - : ShowDurations::Never; - } - inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { - std::ifstream f( _filename.c_str() ); - if( !f.is_open() ) - throw std::domain_error( "Unable to load input file: " + _filename ); - - std::string line; - while( std::getline( f, line ) ) { - line = trim(line); - if( !line.empty() && !startsWith( line, "#" ) ) - addTestOrTags( config, line ); - } - } - - inline Clara::CommandLine<ConfigData> makeCommandLineParser() { - - Clara::CommandLine<ConfigData> cli; - - cli.bindProcessName( &ConfigData::processName ); - - cli.bind( &ConfigData::showHelp ) - .describe( "display usage information" ) - .shortOpt( "?") - .shortOpt( "h") - .longOpt( "help" ); - - cli.bind( &ConfigData::listTests ) - .describe( "list all/matching test cases" ) - .shortOpt( "l") - .longOpt( "list-tests" ); - - cli.bind( &ConfigData::listTags ) - .describe( "list all/matching tags" ) - .shortOpt( "t") - .longOpt( "list-tags" ); - - cli.bind( &ConfigData::showSuccessfulTests ) - .describe( "include successful tests in output" ) - .shortOpt( "s") - .longOpt( "success" ); - - cli.bind( &ConfigData::shouldDebugBreak ) - .describe( "break into debugger on failure" ) - .shortOpt( "b") - .longOpt( "break" ); - - cli.bind( &ConfigData::noThrow ) - .describe( "skip exception tests" ) - .shortOpt( "e") - .longOpt( "nothrow" ); - - cli.bind( &ConfigData::outputFilename ) - .describe( "output filename" ) - .shortOpt( "o") - .longOpt( "out" ) - .hint( "filename" ); - - cli.bind( &ConfigData::reporterName ) - .describe( "reporter to use (defaults to console)" ) - .shortOpt( "r") - .longOpt( "reporter" ) -// .hint( "name[:filename]" ); - .hint( "name" ); - - cli.bind( &ConfigData::name ) - .describe( "suite name" ) - .shortOpt( "n") - .longOpt( "name" ) - .hint( "name" ); - - cli.bind( &abortAfterFirst ) - .describe( "abort at first failure" ) - .shortOpt( "a") - .longOpt( "abort" ); - - cli.bind( &abortAfterX ) - .describe( "abort after x failures" ) - .shortOpt( "x") - .longOpt( "abortx" ) - .hint( "number of failures" ); - - cli.bind( &addWarning ) - .describe( "enable warnings" ) - .shortOpt( "w") - .longOpt( "warn" ) - .hint( "warning name" ); - -// cli.bind( &setVerbosity ) -// .describe( "level of verbosity (0=no output)" ) -// .shortOpt( "v") -// .longOpt( "verbosity" ) -// .hint( "level" ); - - cli.bind( &addTestOrTags ) - .describe( "which test or tests to use" ) - .hint( "test name, pattern or tags" ); - - cli.bind( &setShowDurations ) - .describe( "show test durations" ) - .shortOpt( "d") - .longOpt( "durations" ) - .hint( "yes/no" ); - - cli.bind( &loadTestNamesFromFile ) - .describe( "load test names to run from a file" ) - .shortOpt( "f") - .longOpt( "input-file" ) - .hint( "filename" ); - - // Less common commands which don't have a short form - cli.bind( &ConfigData::listTestNamesOnly ) - .describe( "list all/matching test cases names only" ) - .longOpt( "list-test-names-only" ); - - cli.bind( &ConfigData::listReporters ) - .describe( "list all reporters" ) - .longOpt( "list-reporters" ); - - return cli; - } - -} // end namespace Catch - -// #included from: internal/catch_list.hpp -#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED - -// #included from: catch_text.h -#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED - -#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH - -#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch -// #included from: tbc_text_format.h -// Only use header guard if we are not using an outer namespace -#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED -# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -# endif -# else -# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED -# endif -#endif -#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -#include <string> -#include <vector> -#include <sstream> - -// Use optional outer namespace -#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { -#endif - -namespace Tbc { - -#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH - const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; -#else - const unsigned int consoleWidth = 80; -#endif - - struct TextAttributes { - TextAttributes() - : initialIndent( std::string::npos ), - indent( 0 ), - width( consoleWidth-1 ), - tabChar( '\t' ) - {} - - TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } - TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } - TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } - TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } - - std::size_t initialIndent; // indent of first line, or npos - std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos - std::size_t width; // maximum width of text, including indent. Longer text will wrap - char tabChar; // If this char is seen the indent is changed to current pos - }; - - class Text { - public: - Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) - : attr( _attr ) - { - std::string wrappableChars = " [({.,/|\\-"; - std::size_t indent = _attr.initialIndent != std::string::npos - ? _attr.initialIndent - : _attr.indent; - std::string remainder = _str; - - while( !remainder.empty() ) { - if( lines.size() >= 1000 ) { - lines.push_back( "... message truncated due to excessive size" ); - return; - } - std::size_t tabPos = std::string::npos; - std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); - std::size_t pos = remainder.find_first_of( '\n' ); - if( pos <= width ) { - width = pos; - } - pos = remainder.find_last_of( _attr.tabChar, width ); - if( pos != std::string::npos ) { - tabPos = pos; - if( remainder[width] == '\n' ) - width--; - remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); - } - - if( width == remainder.size() ) { - spliceLine( indent, remainder, width ); - } - else if( remainder[width] == '\n' ) { - spliceLine( indent, remainder, width ); - if( width <= 1 || remainder.size() != 1 ) - remainder = remainder.substr( 1 ); - indent = _attr.indent; - } - else { - pos = remainder.find_last_of( wrappableChars, width ); - if( pos != std::string::npos && pos > 0 ) { - spliceLine( indent, remainder, pos ); - if( remainder[0] == ' ' ) - remainder = remainder.substr( 1 ); - } - else { - spliceLine( indent, remainder, width-1 ); - lines.back() += "-"; - } - if( lines.size() == 1 ) - indent = _attr.indent; - if( tabPos != std::string::npos ) - indent += tabPos; - } - } - } - - void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { - lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); - _remainder = _remainder.substr( _pos ); - } - - typedef std::vector<std::string>::const_iterator const_iterator; - - const_iterator begin() const { return lines.begin(); } - const_iterator end() const { return lines.end(); } - std::string const& last() const { return lines.back(); } - std::size_t size() const { return lines.size(); } - std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } - std::string toString() const { - std::ostringstream oss; - oss << *this; - return oss.str(); - } - - inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { - for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); - it != itEnd; ++it ) { - if( it != _text.begin() ) - _stream << "\n"; - _stream << *it; - } - return _stream; - } - - private: - std::string str; - TextAttributes attr; - std::vector<std::string> lines; - }; - -} // end namespace Tbc - -#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -} // end outer namespace -#endif - -#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE - -namespace Catch { - using Tbc::Text; - using Tbc::TextAttributes; -} - -// #included from: catch_console_colour.hpp -#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED - -namespace Catch { - - namespace Detail { - struct IColourImpl; - } - - struct Colour { - enum Code { - None = 0, - - White, - Red, - Green, - Blue, - Cyan, - Yellow, - Grey, - - Bright = 0x10, - - BrightRed = Bright | Red, - BrightGreen = Bright | Green, - LightGrey = Bright | Grey, - BrightWhite = Bright | White, - - // By intention - FileName = LightGrey, - ResultError = BrightRed, - ResultSuccess = BrightGreen, - - Error = BrightRed, - Success = Green, - - OriginalExpression = Cyan, - ReconstructedExpression = Yellow, - - SecondaryText = LightGrey, - Headers = White - }; - - // Use constructed object for RAII guard - Colour( Code _colourCode ); - ~Colour(); - - // Use static method for one-shot changes - static void use( Code _colourCode ); - - private: - static Detail::IColourImpl* impl; - }; - -} // end namespace Catch - -// #included from: catch_interfaces_reporter.h -#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED - -// #included from: catch_option.hpp -#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED - -namespace Catch { - - // An optional type - template<typename T> - class Option { - public: - Option() : nullableValue( NULL ) {} - Option( T const& _value ) - : nullableValue( new( storage ) T( _value ) ) - {} - Option( Option const& _other ) - : nullableValue( _other ? new( storage ) T( *_other ) : NULL ) - {} - - ~Option() { - reset(); - } - - Option& operator= ( Option const& _other ) { - if( &_other != this ) { - reset(); - if( _other ) - nullableValue = new( storage ) T( *_other ); - } - return *this; - } - Option& operator = ( T const& _value ) { - reset(); - nullableValue = new( storage ) T( _value ); - return *this; - } - - void reset() { - if( nullableValue ) - nullableValue->~T(); - nullableValue = NULL; - } - - T& operator*() { return *nullableValue; } - T const& operator*() const { return *nullableValue; } - T* operator->() { return nullableValue; } - const T* operator->() const { return nullableValue; } - - T valueOr( T const& defaultValue ) const { - return nullableValue ? *nullableValue : defaultValue; - } - - bool some() const { return nullableValue != NULL; } - bool none() const { return nullableValue == NULL; } - - bool operator !() const { return nullableValue == NULL; } - operator SafeBool::type() const { - return SafeBool::makeSafe( some() ); - } - - private: - T* nullableValue; - char storage[sizeof(T)]; - }; - -} // end namespace Catch - -#include <string> -#include <ostream> -#include <map> -#include <assert.h> - -namespace Catch -{ - struct ReporterConfig { - explicit ReporterConfig( Ptr<IConfig> const& _fullConfig ) - : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} - - ReporterConfig( Ptr<IConfig> const& _fullConfig, std::ostream& _stream ) - : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} - - std::ostream& stream() const { return *m_stream; } - Ptr<IConfig> fullConfig() const { return m_fullConfig; } - - private: - std::ostream* m_stream; - Ptr<IConfig> m_fullConfig; - }; - - struct ReporterPreferences { - ReporterPreferences() - : shouldRedirectStdOut( false ) - {} - - bool shouldRedirectStdOut; - }; - - template<typename T> - struct LazyStat : Option<T> { - LazyStat() : used( false ) {} - LazyStat& operator=( T const& _value ) { - Option<T>::operator=( _value ); - used = false; - return *this; - } - void reset() { - Option<T>::reset(); - used = false; - } - bool used; - }; - - struct TestRunInfo { - TestRunInfo( std::string const& _name ) : name( _name ) {} - std::string name; - }; - struct GroupInfo { - GroupInfo( std::string const& _name, - std::size_t _groupIndex, - std::size_t _groupsCount ) - : name( _name ), - groupIndex( _groupIndex ), - groupsCounts( _groupsCount ) - {} - - std::string name; - std::size_t groupIndex; - std::size_t groupsCounts; - }; - - struct AssertionStats { - AssertionStats( AssertionResult const& _assertionResult, - std::vector<MessageInfo> const& _infoMessages, - Totals const& _totals ) - : assertionResult( _assertionResult ), - infoMessages( _infoMessages ), - totals( _totals ) - { - if( assertionResult.hasMessage() ) { - // Copy message into messages list. - // !TBD This should have been done earlier, somewhere - MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); - builder << assertionResult.getMessage(); - builder.m_info.message = builder.m_stream.str(); - - infoMessages.push_back( builder.m_info ); - } - } - virtual ~AssertionStats(); - - AssertionResult assertionResult; - std::vector<MessageInfo> infoMessages; - Totals totals; - }; - - struct SectionStats { - SectionStats( SectionInfo const& _sectionInfo, - Counts const& _assertions, - double _durationInSeconds, - bool _missingAssertions ) - : sectionInfo( _sectionInfo ), - assertions( _assertions ), - durationInSeconds( _durationInSeconds ), - missingAssertions( _missingAssertions ) - {} - virtual ~SectionStats(); - - SectionInfo sectionInfo; - Counts assertions; - double durationInSeconds; - bool missingAssertions; - }; - - struct TestCaseStats { - TestCaseStats( TestCaseInfo const& _testInfo, - Totals const& _totals, - std::string const& _stdOut, - std::string const& _stdErr, - bool _aborting ) - : testInfo( _testInfo ), - totals( _totals ), - stdOut( _stdOut ), - stdErr( _stdErr ), - aborting( _aborting ) - {} - virtual ~TestCaseStats(); - - TestCaseInfo testInfo; - Totals totals; - std::string stdOut; - std::string stdErr; - bool aborting; - }; - - struct TestGroupStats { - TestGroupStats( GroupInfo const& _groupInfo, - Totals const& _totals, - bool _aborting ) - : groupInfo( _groupInfo ), - totals( _totals ), - aborting( _aborting ) - {} - TestGroupStats( GroupInfo const& _groupInfo ) - : groupInfo( _groupInfo ), - aborting( false ) - {} - virtual ~TestGroupStats(); - - GroupInfo groupInfo; - Totals totals; - bool aborting; - }; - - struct TestRunStats { - TestRunStats( TestRunInfo const& _runInfo, - Totals const& _totals, - bool _aborting ) - : runInfo( _runInfo ), - totals( _totals ), - aborting( _aborting ) - {} - TestRunStats( TestRunStats const& _other ) - : runInfo( _other.runInfo ), - totals( _other.totals ), - aborting( _other.aborting ) - {} - virtual ~TestRunStats(); - - TestRunInfo runInfo; - Totals totals; - bool aborting; - }; - - struct IStreamingReporter : IShared { - virtual ~IStreamingReporter(); - - // Implementing class must also provide the following static method: - // static std::string getDescription(); - - virtual ReporterPreferences getPreferences() const = 0; - - virtual void noMatchingTestCases( std::string const& spec ) = 0; - - virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; - virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; - - virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; - virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; - - virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; - - virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; - virtual void sectionEnded( SectionStats const& sectionStats ) = 0; - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; - virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; - }; - - struct IReporterFactory { - virtual ~IReporterFactory(); - virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; - virtual std::string getDescription() const = 0; - }; - - struct IReporterRegistry { - typedef std::map<std::string, IReporterFactory*> FactoryMap; - - virtual ~IReporterRegistry(); - virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const = 0; - virtual FactoryMap const& getFactories() const = 0; - }; - -} - -#include <limits> -#include <algorithm> - -namespace Catch { - inline bool matchesFilters( std::vector<TestCaseFilters> const& filters, TestCase const& testCase ) { - std::vector<TestCaseFilters>::const_iterator it = filters.begin(); - std::vector<TestCaseFilters>::const_iterator itEnd = filters.end(); - for(; it != itEnd; ++it ) - if( !it->shouldInclude( testCase ) ) - return false; - return true; - } - - inline std::size_t listTests( Config const& config ) { - if( config.filters().empty() ) - std::cout << "All available test cases:\n"; - else - std::cout << "Matching test cases:\n"; - - std::size_t matchedTests = 0; - TextAttributes nameAttr, tagsAttr; - nameAttr.setInitialIndent( 2 ).setIndent( 4 ); - tagsAttr.setIndent( 6 ); - - std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests(); - for( std::vector<TestCase>::const_iterator it = allTests.begin(), itEnd = allTests.end(); - it != itEnd; - ++it ) - if( matchesFilters( config.filters(), *it ) ) { - matchedTests++; - TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); - Colour::Code colour = testCaseInfo.isHidden - ? Colour::SecondaryText - : Colour::None; - Colour colourGuard( colour ); - - std::cout << Text( testCaseInfo.name, nameAttr ) << std::endl; - if( !testCaseInfo.tags.empty() ) - std::cout << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; - } - - if( config.filters().empty() ) - std::cout << pluralise( matchedTests, "test case" ) << "\n" << std::endl; - else - std::cout << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl; - return matchedTests; - } - - inline std::size_t listTestsNamesOnly( Config const& config ) { - std::size_t matchedTests = 0; - std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests(); - for( std::vector<TestCase>::const_iterator it = allTests.begin(), itEnd = allTests.end(); - it != itEnd; - ++it ) - if( matchesFilters( config.filters(), *it ) ) { - matchedTests++; - TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); - std::cout << testCaseInfo.name << std::endl; - } - return matchedTests; - } - - inline std::size_t listTags( Config const& config ) { - if( config.filters().empty() ) - std::cout << "All available tags:\n"; - else - std::cout << "Matching tags:\n"; - - std::map<std::string, int> tagCounts; - - std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests(); - for( std::vector<TestCase>::const_iterator it = allTests.begin(), - itEnd = allTests.end(); - it != itEnd; - ++it ) { - if( matchesFilters( config.filters(), *it ) ) { - for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), - tagItEnd = it->getTestCaseInfo().tags.end(); - tagIt != tagItEnd; - ++tagIt ) { - std::string tagName = *tagIt; - std::map<std::string, int>::iterator countIt = tagCounts.find( tagName ); - if( countIt == tagCounts.end() ) - tagCounts.insert( std::make_pair( tagName, 1 ) ); - else - countIt->second++; - } - } - } - - for( std::map<std::string, int>::const_iterator countIt = tagCounts.begin(), - countItEnd = tagCounts.end(); - countIt != countItEnd; - ++countIt ) { - std::ostringstream oss; - oss << " " << countIt->second << " "; - Text wrapper( "[" + countIt->first + "]", TextAttributes() - .setInitialIndent( 0 ) - .setIndent( oss.str().size() ) - .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); - std::cout << oss.str() << wrapper << "\n"; - } - std::cout << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl; - return tagCounts.size(); - } - - inline std::size_t listReporters( Config const& /*config*/ ) { - std::cout << "Available reports:\n"; - IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); - IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; - std::size_t maxNameLen = 0; - for(it = itBegin; it != itEnd; ++it ) - maxNameLen = (std::max)( maxNameLen, it->first.size() ); - - for(it = itBegin; it != itEnd; ++it ) { - Text wrapper( it->second->getDescription(), TextAttributes() - .setInitialIndent( 0 ) - .setIndent( 7+maxNameLen ) - .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); - std::cout << " " - << it->first - << ":" - << std::string( maxNameLen - it->first.size() + 2, ' ' ) - << wrapper << "\n"; - } - std::cout << std::endl; - return factories.size(); - } - - inline Option<std::size_t> list( Config const& config ) { - Option<std::size_t> listedCount; - if( config.listTests() ) - listedCount = listedCount.valueOr(0) + listTests( config ); - if( config.listTestNamesOnly() ) - listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); - if( config.listTags() ) - listedCount = listedCount.valueOr(0) + listTags( config ); - if( config.listReporters() ) - listedCount = listedCount.valueOr(0) + listReporters( config ); - return listedCount; - } - -} // end namespace Catch - -// #included from: internal/catch_runner_impl.hpp -#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED - -// #included from: catch_test_case_tracker.hpp -#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED - -#include <map> -#include <string> -#include <assert.h> - -namespace Catch { -namespace SectionTracking { - - class TrackedSection { - - typedef std::map<std::string, TrackedSection> TrackedSections; - - public: - enum RunState { - NotStarted, - Executing, - ExecutingChildren, - Completed - }; - - TrackedSection( std::string const& name, TrackedSection* parent ) - : m_name( name ), m_runState( NotStarted ), m_parent( parent ) - {} - - RunState runState() const { return m_runState; } - - void addChild( std::string const& childName ) { - m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) ); - } - TrackedSection* getChild( std::string const& childName ) { - return &m_children.find( childName )->second; - } - - void enter() { - if( m_runState == NotStarted ) - m_runState = Executing; - } - void leave() { - for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end(); - it != itEnd; - ++it ) - if( it->second.runState() != Completed ) { - m_runState = ExecutingChildren; - return; - } - m_runState = Completed; - } - TrackedSection* getParent() { - return m_parent; - } - bool hasChildren() const { - return !m_children.empty(); - } - - private: - std::string m_name; - RunState m_runState; - TrackedSections m_children; - TrackedSection* m_parent; - - }; - - class TestCaseTracker { - public: - TestCaseTracker( std::string const& testCaseName ) - : m_testCase( testCaseName, NULL ), - m_currentSection( &m_testCase ), - m_completedASectionThisRun( false ) - {} - - bool enterSection( std::string const& name ) { - if( m_completedASectionThisRun ) - return false; - if( m_currentSection->runState() == TrackedSection::Executing ) { - m_currentSection->addChild( name ); - return false; - } - else { - TrackedSection* child = m_currentSection->getChild( name ); - if( child->runState() != TrackedSection::Completed ) { - m_currentSection = child; - m_currentSection->enter(); - return true; - } - return false; - } - } - void leaveSection() { - m_currentSection->leave(); - m_currentSection = m_currentSection->getParent(); - assert( m_currentSection != NULL ); - m_completedASectionThisRun = true; - } - - bool currentSectionHasChildren() const { - return m_currentSection->hasChildren(); - } - bool isCompleted() const { - return m_testCase.runState() == TrackedSection::Completed; - } - - class Guard { - public: - Guard( TestCaseTracker& tracker ) - : m_tracker( tracker ) - { - m_tracker.enterTestCase(); - } - ~Guard() { - m_tracker.leaveTestCase(); - } - private: - Guard( Guard const& ); - void operator = ( Guard const& ); - TestCaseTracker& m_tracker; - }; - - private: - void enterTestCase() { - m_currentSection = &m_testCase; - m_completedASectionThisRun = false; - m_testCase.enter(); - } - void leaveTestCase() { - m_testCase.leave(); - } - - TrackedSection m_testCase; - TrackedSection* m_currentSection; - bool m_completedASectionThisRun; - }; - -} // namespace SectionTracking - -using SectionTracking::TestCaseTracker; - -} // namespace Catch - -#include <set> -#include <string> - -namespace Catch { - - class StreamRedirect { - - public: - StreamRedirect( std::ostream& stream, std::string& targetString ) - : m_stream( stream ), - m_prevBuf( stream.rdbuf() ), - m_targetString( targetString ) - { - stream.rdbuf( m_oss.rdbuf() ); - } - - ~StreamRedirect() { - m_targetString += m_oss.str(); - m_stream.rdbuf( m_prevBuf ); - } - - private: - std::ostream& m_stream; - std::streambuf* m_prevBuf; - std::ostringstream m_oss; - std::string& m_targetString; - }; - - /////////////////////////////////////////////////////////////////////////// - - class RunContext : public IResultCapture, public IRunner { - - RunContext( RunContext const& ); - void operator =( RunContext const& ); - - public: - - explicit RunContext( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> const& reporter ) - : m_runInfo( config->name() ), - m_context( getCurrentMutableContext() ), - m_activeTestCase( NULL ), - m_config( config ), - m_reporter( reporter ), - m_prevRunner( &m_context.getRunner() ), - m_prevResultCapture( &m_context.getResultCapture() ), - m_prevConfig( m_context.getConfig() ) - { - m_context.setRunner( this ); - m_context.setConfig( m_config ); - m_context.setResultCapture( this ); - m_reporter->testRunStarting( m_runInfo ); - } - - virtual ~RunContext() { - m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); - m_context.setRunner( m_prevRunner ); - m_context.setConfig( NULL ); - m_context.setResultCapture( m_prevResultCapture ); - m_context.setConfig( m_prevConfig ); - } - - void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { - m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); - } - void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { - m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); - } - - Totals runMatching( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { - - std::vector<TestCase> matchingTests = getRegistryHub().getTestCaseRegistry().getMatchingTestCases( testSpec ); - - Totals totals; - - testGroupStarting( testSpec, groupIndex, groupsCount ); - - std::vector<TestCase>::const_iterator it = matchingTests.begin(); - std::vector<TestCase>::const_iterator itEnd = matchingTests.end(); - for(; it != itEnd; ++it ) - totals += runTest( *it ); - - testGroupEnded( testSpec, totals, groupIndex, groupsCount ); - return totals; - } - - Totals runTest( TestCase const& testCase ) { - Totals prevTotals = m_totals; - - std::string redirectedCout; - std::string redirectedCerr; - - TestCaseInfo testInfo = testCase.getTestCaseInfo(); - - m_reporter->testCaseStarting( testInfo ); - - m_activeTestCase = &testCase; - m_testCaseTracker = TestCaseTracker( testInfo.name ); - - do { - do { - runCurrentTest( redirectedCout, redirectedCerr ); - } - while( !m_testCaseTracker->isCompleted() && !aborting() ); - } - while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); - - Totals deltaTotals = m_totals.delta( prevTotals ); - m_totals.testCases += deltaTotals.testCases; - m_reporter->testCaseEnded( TestCaseStats( testInfo, - deltaTotals, - redirectedCout, - redirectedCerr, - aborting() ) ); - - m_activeTestCase = NULL; - m_testCaseTracker.reset(); - - return deltaTotals; - } - - Ptr<IConfig const> config() const { - return m_config; - } - - private: // IResultCapture - - virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& assertionResult, AssertionInfo const& assertionInfo ) { - m_lastAssertionInfo = assertionInfo; - return actOnCurrentResult( assertionResult.buildResult( assertionInfo ) ); - } - - virtual void assertionEnded( AssertionResult const& result ) { - if( result.getResultType() == ResultWas::Ok ) { - m_totals.assertions.passed++; - } - else if( !result.isOk() ) { - m_totals.assertions.failed++; - } - - if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) ) - m_messages.clear(); - - // Reset working state - m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); - } - - virtual bool sectionStarted ( - SectionInfo const& sectionInfo, - Counts& assertions - ) - { - std::ostringstream oss; - oss << sectionInfo.name << "@" << sectionInfo.lineInfo; - - if( !m_testCaseTracker->enterSection( oss.str() ) ) - return false; - - m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; - - m_reporter->sectionStarting( sectionInfo ); - - assertions = m_totals.assertions; - - return true; - } - bool testForMissingAssertions( Counts& assertions ) { - if( assertions.total() != 0 || - !m_config->warnAboutMissingAssertions() || - m_testCaseTracker->currentSectionHasChildren() ) - return false; - m_totals.assertions.failed++; - assertions.failed++; - return true; - } - - virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) { - if( std::uncaught_exception() ) { - m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) ); - return; - } - - Counts assertions = m_totals.assertions - prevAssertions; - bool missingAssertions = testForMissingAssertions( assertions ); - - m_testCaseTracker->leaveSection(); - - m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) ); - m_messages.clear(); - } - - virtual void pushScopedMessage( MessageInfo const& message ) { - m_messages.push_back( message ); - } - - virtual void popScopedMessage( MessageInfo const& message ) { - m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); - } - - virtual bool shouldDebugBreak() const { - return m_config->shouldDebugBreak(); - } - - virtual std::string getCurrentTestName() const { - return m_activeTestCase - ? m_activeTestCase->getTestCaseInfo().name - : ""; - } - - virtual const AssertionResult* getLastResult() const { - return &m_lastResult; - } - - public: - // !TBD We need to do this another way! - bool aborting() const { - return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() ); - } - - private: - - ResultAction::Value actOnCurrentResult( AssertionResult const& result ) { - m_lastResult = result; - assertionEnded( m_lastResult ); - - ResultAction::Value action = ResultAction::None; - - if( !m_lastResult.isOk() ) { - action = ResultAction::Failed; - if( shouldDebugBreak() ) - action = (ResultAction::Value)( action | ResultAction::Debug ); - if( aborting() ) - action = (ResultAction::Value)( action | ResultAction::Abort ); - } - return action; - } - - void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { - TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); - SectionInfo testCaseSection( testCaseInfo.name, testCaseInfo.description, testCaseInfo.lineInfo ); - m_reporter->sectionStarting( testCaseSection ); - Counts prevAssertions = m_totals.assertions; - double duration = 0; - try { - m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); - TestCaseTracker::Guard guard( *m_testCaseTracker ); - - Timer timer; - timer.start(); - if( m_reporter->getPreferences().shouldRedirectStdOut ) { - StreamRedirect coutRedir( std::cout, redirectedCout ); - StreamRedirect cerrRedir( std::cerr, redirectedCerr ); - m_activeTestCase->invoke(); - } - else { - m_activeTestCase->invoke(); - } - duration = timer.getElapsedSeconds(); - } - catch( TestFailureException& ) { - // This just means the test was aborted due to failure - } - catch(...) { - ExpressionResultBuilder exResult( ResultWas::ThrewException ); - exResult << translateActiveException(); - actOnCurrentResult( exResult.buildResult( m_lastAssertionInfo ) ); - } - // If sections ended prematurely due to an exception we stored their - // infos here so we can tear them down outside the unwind process. - for( std::vector<UnfinishedSections>::const_iterator it = m_unfinishedSections.begin(), - itEnd = m_unfinishedSections.end(); - it != itEnd; - ++it ) - sectionEnded( it->info, it->prevAssertions, it->durationInSeconds ); - m_unfinishedSections.clear(); - m_messages.clear(); - - Counts assertions = m_totals.assertions - prevAssertions; - bool missingAssertions = testForMissingAssertions( assertions ); - - SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); - m_reporter->sectionEnded( testCaseSectionStats ); - } - - private: - struct UnfinishedSections { - UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds ) - : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) - {} - - SectionInfo info; - Counts prevAssertions; - double durationInSeconds; - }; - - TestRunInfo m_runInfo; - IMutableContext& m_context; - TestCase const* m_activeTestCase; - Option<TestCaseTracker> m_testCaseTracker; - AssertionResult m_lastResult; - - Ptr<IConfig const> m_config; - Totals m_totals; - Ptr<IStreamingReporter> m_reporter; - std::vector<MessageInfo> m_messages; - IRunner* m_prevRunner; - IResultCapture* m_prevResultCapture; - Ptr<IConfig const> m_prevConfig; - AssertionInfo m_lastAssertionInfo; - std::vector<UnfinishedSections> m_unfinishedSections; - }; - -} // end namespace Catch - -// #included from: internal/catch_version.h -#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED - -namespace Catch { - - // Versioning information - struct Version { - Version( unsigned int _majorVersion, - unsigned int _minorVersion, - unsigned int _buildNumber, - std::string const& _branchName ) - : majorVersion( _majorVersion ), - minorVersion( _minorVersion ), - buildNumber( _buildNumber ), - branchName( _branchName ) - {} - - const unsigned int majorVersion; - const unsigned int minorVersion; - const unsigned int buildNumber; - const std::string branchName; - - private: - void operator=( Version const& ); - }; - - extern Version libraryVersion; -} - -#include <fstream> -#include <stdlib.h> -#include <limits> - -namespace Catch { - - class Runner { - - public: - Runner( Ptr<Config> const& config ) - : m_config( config ) - { - openStream(); - makeReporter(); - } - - Totals runTests() { - - std::vector<TestCaseFilters> filterGroups = m_config->filters(); - if( filterGroups.empty() ) { - TestCaseFilters filterGroup( "" ); - filterGroups.push_back( filterGroup ); - } - - RunContext context( m_config.get(), m_reporter ); - - Totals totals; - - for( std::size_t i=0; i < filterGroups.size() && !context.aborting(); ++i ) { - context.testGroupStarting( filterGroups[i].getName(), i, filterGroups.size() ); - totals += runTestsForGroup( context, filterGroups[i] ); - context.testGroupEnded( filterGroups[i].getName(), totals, i, filterGroups.size() ); - } - return totals; - } - - Totals runTestsForGroup( RunContext& context, const TestCaseFilters& filterGroup ) { - Totals totals; - std::vector<TestCase>::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin(); - std::vector<TestCase>::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end(); - int testsRunForGroup = 0; - for(; it != itEnd; ++it ) { - if( filterGroup.shouldInclude( *it ) ) { - testsRunForGroup++; - if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) { - - if( context.aborting() ) - break; - - totals += context.runTest( *it ); - m_testsAlreadyRun.insert( *it ); - } - } - } - if( testsRunForGroup == 0 && !filterGroup.getName().empty() ) - m_reporter->noMatchingTestCases( filterGroup.getName() ); - return totals; - - } - - private: - void openStream() { - // Open output file, if specified - if( !m_config->getFilename().empty() ) { - m_ofs.open( m_config->getFilename().c_str() ); - if( m_ofs.fail() ) { - std::ostringstream oss; - oss << "Unable to open file: '" << m_config->getFilename() << "'"; - throw std::domain_error( oss.str() ); - } - m_config->setStreamBuf( m_ofs.rdbuf() ); - } - } - void makeReporter() { - std::string reporterName = m_config->getReporterName().empty() - ? "console" - : m_config->getReporterName(); - - m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, m_config.get() ); - if( !m_reporter ) { - std::ostringstream oss; - oss << "No reporter registered with name: '" << reporterName << "'"; - throw std::domain_error( oss.str() ); - } - } - - private: - Ptr<Config> m_config; - std::ofstream m_ofs; - Ptr<IStreamingReporter> m_reporter; - std::set<TestCase> m_testsAlreadyRun; - }; - - class Session { - static bool alreadyInstantiated; - - public: - - struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; - - Session() - : m_cli( makeCommandLineParser() ) { - if( alreadyInstantiated ) { - std::string msg = "Only one instance of Catch::Session can ever be used"; - std::cerr << msg << std::endl; - throw std::logic_error( msg ); - } - alreadyInstantiated = true; - } - ~Session() { - Catch::cleanUp(); - } - - void showHelp( std::string const& processName ) { - std::cout << "\nCatch v" << libraryVersion.majorVersion << "." - << libraryVersion.minorVersion << " build " - << libraryVersion.buildNumber; - if( libraryVersion.branchName != "master" ) - std::cout << " (" << libraryVersion.branchName << " branch)"; - std::cout << "\n"; - - m_cli.usage( std::cout, processName ); - std::cout << "For more detail usage please see the project docs\n" << std::endl; - } - - int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { - try { - m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); - m_unusedTokens = m_cli.parseInto( argc, argv, m_configData ); - if( m_configData.showHelp ) - showHelp( m_configData.processName ); - m_config.reset(); - } - catch( std::exception& ex ) { - { - Colour colourGuard( Colour::Red ); - std::cerr << "\nError(s) in input:\n" - << Text( ex.what(), TextAttributes().setIndent(2) ) - << "\n\n"; - } - m_cli.usage( std::cout, m_configData.processName ); - return (std::numeric_limits<int>::max)(); - } - return 0; - } - - void useConfigData( ConfigData const& _configData ) { - m_configData = _configData; - m_config.reset(); - } - - int run( int argc, char* const argv[] ) { - - int returnCode = applyCommandLine( argc, argv ); - if( returnCode == 0 ) - returnCode = run(); - return returnCode; - } - - int run() { - if( m_configData.showHelp ) - return 0; - - try - { - config(); // Force config to be constructed - Runner runner( m_config ); - - // Handle list request - if( Option<std::size_t> listed = list( config() ) ) - return static_cast<int>( *listed ); - - return static_cast<int>( runner.runTests().assertions.failed ); - } - catch( std::exception& ex ) { - std::cerr << ex.what() << std::endl; - return (std::numeric_limits<int>::max)(); - } - } - - Clara::CommandLine<ConfigData> const& cli() const { - return m_cli; - } - std::vector<Clara::Parser::Token> const& unusedTokens() const { - return m_unusedTokens; - } - ConfigData& configData() { - return m_configData; - } - Config& config() { - if( !m_config ) - m_config = new Config( m_configData ); - return *m_config; - } - - private: - Clara::CommandLine<ConfigData> m_cli; - std::vector<Clara::Parser::Token> m_unusedTokens; - ConfigData m_configData; - Ptr<Config> m_config; - }; - - bool Session::alreadyInstantiated = false; - -} // end namespace Catch - -// #included from: catch_registry_hub.hpp -#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED - -// #included from: catch_test_case_registry_impl.hpp -#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED - -#include <vector> -#include <set> -#include <sstream> -#include <iostream> - -namespace Catch { - - class TestRegistry : public ITestCaseRegistry { - public: - TestRegistry() : m_unnamedCount( 0 ) {} - virtual ~TestRegistry(); - - virtual void registerTest( TestCase const& testCase ) { - std::string name = testCase.getTestCaseInfo().name; - if( name == "" ) { - std::ostringstream oss; - oss << "Anonymous test case " << ++m_unnamedCount; - return registerTest( testCase.withName( oss.str() ) ); - } - - if( m_functions.find( testCase ) == m_functions.end() ) { - m_functions.insert( testCase ); - m_functionsInOrder.push_back( testCase ); - if( !testCase.isHidden() ) - m_nonHiddenFunctions.push_back( testCase ); - } - else { - TestCase const& prev = *m_functions.find( testCase ); - std::cerr << "error: TEST_CASE( \"" << name << "\" ) already defined.\n" - << "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n" - << "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl; - exit(1); - } - } - - virtual std::vector<TestCase> const& getAllTests() const { - return m_functionsInOrder; - } - - virtual std::vector<TestCase> const& getAllNonHiddenTests() const { - return m_nonHiddenFunctions; - } - - // !TBD deprecated - virtual std::vector<TestCase> getMatchingTestCases( std::string const& rawTestSpec ) const { - std::vector<TestCase> matchingTests; - getMatchingTestCases( rawTestSpec, matchingTests ); - return matchingTests; - } - - // !TBD deprecated - virtual void getMatchingTestCases( std::string const& rawTestSpec, std::vector<TestCase>& matchingTestsOut ) const { - TestCaseFilter filter( rawTestSpec ); - - std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin(); - std::vector<TestCase>::const_iterator itEnd = m_functionsInOrder.end(); - for(; it != itEnd; ++it ) { - if( filter.shouldInclude( *it ) ) { - matchingTestsOut.push_back( *it ); - } - } - } - virtual void getMatchingTestCases( TestCaseFilters const& filters, std::vector<TestCase>& matchingTestsOut ) const { - std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin(); - std::vector<TestCase>::const_iterator itEnd = m_functionsInOrder.end(); - // !TBD: replace with algorithm - for(; it != itEnd; ++it ) - if( filters.shouldInclude( *it ) ) - matchingTestsOut.push_back( *it ); - } - - private: - - std::set<TestCase> m_functions; - std::vector<TestCase> m_functionsInOrder; - std::vector<TestCase> m_nonHiddenFunctions; - size_t m_unnamedCount; - }; - - /////////////////////////////////////////////////////////////////////////// - - class FreeFunctionTestCase : public SharedImpl<ITestCase> { - public: - - FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} - - virtual void invoke() const { - m_fun(); - } - - private: - virtual ~FreeFunctionTestCase(); - - TestFunction m_fun; - }; - - inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { - std::string className = classOrQualifiedMethodName; - if( startsWith( className, "&" ) ) - { - std::size_t lastColons = className.rfind( "::" ); - std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); - if( penultimateColons == std::string::npos ) - penultimateColons = 1; - className = className.substr( penultimateColons, lastColons-penultimateColons ); - } - return className; - } - - /////////////////////////////////////////////////////////////////////////// - - AutoReg::AutoReg( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ) { - registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); - } - - AutoReg::~AutoReg() {} - - void AutoReg::registerTestCase( ITestCase* testCase, - char const* classOrQualifiedMethodName, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ) { - - getMutableRegistryHub().registerTest - ( makeTestCase( testCase, - extractClassName( classOrQualifiedMethodName ), - nameAndDesc.name, - nameAndDesc.description, - lineInfo ) ); - } - -} // end namespace Catch - -// #included from: catch_reporter_registry.hpp -#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED - -#include <map> - -namespace Catch { - - class ReporterRegistry : public IReporterRegistry { - - public: - - virtual ~ReporterRegistry() { - deleteAllValues( m_factories ); - } - - virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const { - FactoryMap::const_iterator it = m_factories.find( name ); - if( it == m_factories.end() ) - return NULL; - return it->second->create( ReporterConfig( config ) ); - } - - void registerReporter( std::string const& name, IReporterFactory* factory ) { - m_factories.insert( std::make_pair( name, factory ) ); - } - - FactoryMap const& getFactories() const { - return m_factories; - } - - private: - FactoryMap m_factories; - }; -} - -// #included from: catch_exception_translator_registry.hpp -#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED - -#ifdef __OBJC__ -#import "Foundation/Foundation.h" -#endif - -namespace Catch { - - class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { - public: - ~ExceptionTranslatorRegistry() { - deleteAll( m_translators ); - } - - virtual void registerTranslator( const IExceptionTranslator* translator ) { - m_translators.push_back( translator ); - } - - virtual std::string translateActiveException() const { - try { -#ifdef __OBJC__ - // In Objective-C try objective-c exceptions first - @try { - throw; - } - @catch (NSException *exception) { - return toString( [exception description] ); - } -#else - throw; -#endif - } - catch( std::exception& ex ) { - return ex.what(); - } - catch( std::string& msg ) { - return msg; - } - catch( const char* msg ) { - return msg; - } - catch(...) { - return tryTranslators( m_translators.begin() ); - } - } - - std::string tryTranslators( std::vector<const IExceptionTranslator*>::const_iterator it ) const { - if( it == m_translators.end() ) - return "Unknown exception"; - - try { - return (*it)->translate(); - } - catch(...) { - return tryTranslators( it+1 ); - } - } - - private: - std::vector<const IExceptionTranslator*> m_translators; - }; -} - -namespace Catch { - - namespace { - - class RegistryHub : public IRegistryHub, public IMutableRegistryHub { - - RegistryHub( RegistryHub const& ); - void operator=( RegistryHub const& ); - - public: // IRegistryHub - RegistryHub() { - } - virtual IReporterRegistry const& getReporterRegistry() const { - return m_reporterRegistry; - } - virtual ITestCaseRegistry const& getTestCaseRegistry() const { - return m_testCaseRegistry; - } - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() { - return m_exceptionTranslatorRegistry; - } - - public: // IMutableRegistryHub - virtual void registerReporter( std::string const& name, IReporterFactory* factory ) { - m_reporterRegistry.registerReporter( name, factory ); - } - virtual void registerTest( TestCase const& testInfo ) { - m_testCaseRegistry.registerTest( testInfo ); - } - virtual void registerTranslator( const IExceptionTranslator* translator ) { - m_exceptionTranslatorRegistry.registerTranslator( translator ); - } - - private: - TestRegistry m_testCaseRegistry; - ReporterRegistry m_reporterRegistry; - ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; - }; - - // Single, global, instance - inline RegistryHub*& getTheRegistryHub() { - static RegistryHub* theRegistryHub = NULL; - if( !theRegistryHub ) - theRegistryHub = new RegistryHub(); - return theRegistryHub; - } - } - - IRegistryHub& getRegistryHub() { - return *getTheRegistryHub(); - } - IMutableRegistryHub& getMutableRegistryHub() { - return *getTheRegistryHub(); - } - void cleanUp() { - delete getTheRegistryHub(); - getTheRegistryHub() = NULL; - cleanUpContext(); - } - std::string translateActiveException() { - return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); - } - -} // end namespace Catch - -// #included from: catch_notimplemented_exception.hpp -#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED - -#include <ostream> - -namespace Catch { - - NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) - : m_lineInfo( lineInfo ) { - std::ostringstream oss; - oss << lineInfo << ": function "; - oss << "not implemented"; - m_what = oss.str(); - } - - const char* NotImplementedException::what() const throw() { - return m_what.c_str(); - } - -} // end namespace Catch - -// #included from: catch_context_impl.hpp -#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED - -// #included from: catch_stream.hpp -#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED - -// #included from: catch_streambuf.h -#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED - -#include <streambuf> - -namespace Catch { - - class StreamBufBase : public std::streambuf { - public: - virtual ~StreamBufBase() throw(); - }; -} - -#include <stdexcept> -#include <cstdio> - -namespace Catch { - - template<typename WriterF, size_t bufferSize=256> - class StreamBufImpl : public StreamBufBase { - char data[bufferSize]; - WriterF m_writer; - - public: - StreamBufImpl() { - setp( data, data + sizeof(data) ); - } - - ~StreamBufImpl() throw() { - sync(); - } - - private: - int overflow( int c ) { - sync(); - - if( c != EOF ) { - if( pbase() == epptr() ) - m_writer( std::string( 1, static_cast<char>( c ) ) ); - else - sputc( static_cast<char>( c ) ); - } - return 0; - } - - int sync() { - if( pbase() != pptr() ) { - m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) ); - setp( pbase(), epptr() ); - } - return 0; - } - }; - - /////////////////////////////////////////////////////////////////////////// - - struct OutputDebugWriter { - - void operator()( std::string const&str ) { - writeToDebugConsole( str ); - } - }; - - Stream::Stream() - : streamBuf( NULL ), isOwned( false ) - {} - - Stream::Stream( std::streambuf* _streamBuf, bool _isOwned ) - : streamBuf( _streamBuf ), isOwned( _isOwned ) - {} - - void Stream::release() { - if( isOwned ) { - delete streamBuf; - streamBuf = NULL; - isOwned = false; - } - } -} - -namespace Catch { - - class Context : public IMutableContext { - - Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {} - Context( Context const& ); - void operator=( Context const& ); - - public: // IContext - virtual IResultCapture& getResultCapture() { - return *m_resultCapture; - } - virtual IRunner& getRunner() { - return *m_runner; - } - virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { - return getGeneratorsForCurrentTest() - .getGeneratorInfo( fileInfo, totalSize ) - .getCurrentIndex(); - } - virtual bool advanceGeneratorsForCurrentTest() { - IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); - return generators && generators->moveNext(); - } - - virtual Ptr<IConfig const> getConfig() const { - return m_config; - } - - public: // IMutableContext - virtual void setResultCapture( IResultCapture* resultCapture ) { - m_resultCapture = resultCapture; - } - virtual void setRunner( IRunner* runner ) { - m_runner = runner; - } - virtual void setConfig( Ptr<IConfig const> const& config ) { - m_config = config; - } - - friend IMutableContext& getCurrentMutableContext(); - - private: - IGeneratorsForTest* findGeneratorsForCurrentTest() { - std::string testName = getResultCapture().getCurrentTestName(); - - std::map<std::string, IGeneratorsForTest*>::const_iterator it = - m_generatorsByTestName.find( testName ); - return it != m_generatorsByTestName.end() - ? it->second - : NULL; - } - - IGeneratorsForTest& getGeneratorsForCurrentTest() { - IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); - if( !generators ) { - std::string testName = getResultCapture().getCurrentTestName(); - generators = createGeneratorsForTest(); - m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); - } - return *generators; - } - - private: - Ptr<IConfig const> m_config; - IRunner* m_runner; - IResultCapture* m_resultCapture; - std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName; - }; - - namespace { - Context* currentContext = NULL; - } - IMutableContext& getCurrentMutableContext() { - if( !currentContext ) - currentContext = new Context(); - return *currentContext; - } - IContext& getCurrentContext() { - return getCurrentMutableContext(); - } - - Stream createStream( std::string const& streamName ) { - if( streamName == "stdout" ) return Stream( std::cout.rdbuf(), false ); - if( streamName == "stderr" ) return Stream( std::cerr.rdbuf(), false ); - if( streamName == "debug" ) return Stream( new StreamBufImpl<OutputDebugWriter>, true ); - - throw std::domain_error( "Unknown stream: " + streamName ); - } - - void cleanUpContext() { - delete currentContext; - currentContext = NULL; - } -} - -// #included from: catch_console_colour_impl.hpp -#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED - -namespace Catch { namespace Detail { - struct IColourImpl { - virtual ~IColourImpl() {} - virtual void use( Colour::Code _colourCode ) = 0; - }; -}} - -#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// - -#ifndef NOMINMAX -#define NOMINMAX -#endif - -#ifdef __AFXDLL -#include <AfxWin.h> -#else -#include <windows.h> -#endif - -namespace Catch { -namespace { - - class Win32ColourImpl : public Detail::IColourImpl { - public: - Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) - { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); - originalAttributes = csbiInfo.wAttributes; - } - - virtual void use( Colour::Code _colourCode ) { - switch( _colourCode ) { - case Colour::None: return setTextAttribute( originalAttributes ); - case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); - case Colour::Red: return setTextAttribute( FOREGROUND_RED ); - case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); - case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); - case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); - case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); - case Colour::Grey: return setTextAttribute( 0 ); - - case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); - case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); - case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); - case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); - - case Colour::Bright: throw std::logic_error( "not a colour" ); - } - } - - private: - void setTextAttribute( WORD _textAttribute ) { - SetConsoleTextAttribute( stdoutHandle, _textAttribute ); - } - HANDLE stdoutHandle; - WORD originalAttributes; - }; - - inline bool shouldUseColourForPlatform() { - return true; - } - - Win32ColourImpl platformColourImpl; - -} // end anon namespace -} // end namespace Catch - -#else // Not Windows - assumed to be POSIX compatible ////////////////////////// - -#include <unistd.h> - -namespace Catch { -namespace { - - // use POSIX/ ANSI console terminal codes - // Thanks to Adam Strzelecki for original contribution - // (http://github.com/nanoant) - // https://github.com/philsquared/Catch/pull/131 - class PosixColourImpl : public Detail::IColourImpl { - public: - virtual void use( Colour::Code _colourCode ) { - switch( _colourCode ) { - case Colour::None: - case Colour::White: return setColour( "[0m" ); - case Colour::Red: return setColour( "[0;31m" ); - case Colour::Green: return setColour( "[0;32m" ); - case Colour::Blue: return setColour( "[0:34m" ); - case Colour::Cyan: return setColour( "[0;36m" ); - case Colour::Yellow: return setColour( "[0;33m" ); - case Colour::Grey: return setColour( "[1;30m" ); - - case Colour::LightGrey: return setColour( "[0;37m" ); - case Colour::BrightRed: return setColour( "[1;31m" ); - case Colour::BrightGreen: return setColour( "[1;32m" ); - case Colour::BrightWhite: return setColour( "[1;37m" ); - - case Colour::Bright: throw std::logic_error( "not a colour" ); - } - } - private: - void setColour( const char* _escapeCode ) { - std::cout << '\033' << _escapeCode; - } - }; - - inline bool shouldUseColourForPlatform() { - return isatty(STDOUT_FILENO); - } - - PosixColourImpl platformColourImpl; - -} // end anon namespace -} // end namespace Catch - -#endif // not Windows - -namespace Catch { - - namespace { - struct NoColourImpl : Detail::IColourImpl { - void use( Colour::Code ) {} - }; - NoColourImpl noColourImpl; - static const bool shouldUseColour = shouldUseColourForPlatform() && - !isDebuggerActive(); - } - - Colour::Colour( Code _colourCode ){ use( _colourCode ); } - Colour::~Colour(){ use( None ); } - void Colour::use( Code _colourCode ) { - impl->use( _colourCode ); - } - - Detail::IColourImpl* Colour::impl = shouldUseColour - ? static_cast<Detail::IColourImpl*>( &platformColourImpl ) - : static_cast<Detail::IColourImpl*>( &noColourImpl ); - -} // end namespace Catch - -// #included from: catch_generators_impl.hpp -#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED - -#include <vector> -#include <string> -#include <map> - -namespace Catch { - - struct GeneratorInfo : IGeneratorInfo { - - GeneratorInfo( std::size_t size ) - : m_size( size ), - m_currentIndex( 0 ) - {} - - bool moveNext() { - if( ++m_currentIndex == m_size ) { - m_currentIndex = 0; - return false; - } - return true; - } - - std::size_t getCurrentIndex() const { - return m_currentIndex; - } - - std::size_t m_size; - std::size_t m_currentIndex; - }; - - /////////////////////////////////////////////////////////////////////////// - - class GeneratorsForTest : public IGeneratorsForTest { - - public: - ~GeneratorsForTest() { - deleteAll( m_generatorsInOrder ); - } - - IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { - std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo ); - if( it == m_generatorsByName.end() ) { - IGeneratorInfo* info = new GeneratorInfo( size ); - m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); - m_generatorsInOrder.push_back( info ); - return *info; - } - return *it->second; - } - - bool moveNext() { - std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin(); - std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end(); - for(; it != itEnd; ++it ) { - if( (*it)->moveNext() ) - return true; - } - return false; - } - - private: - std::map<std::string, IGeneratorInfo*> m_generatorsByName; - std::vector<IGeneratorInfo*> m_generatorsInOrder; - }; - - IGeneratorsForTest* createGeneratorsForTest() - { - return new GeneratorsForTest(); - } - -} // end namespace Catch - -// #included from: catch_assertionresult.hpp -#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED - -namespace Catch { - - AssertionInfo::AssertionInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - std::string const& _capturedExpression, - ResultDisposition::Flags _resultDisposition ) - : macroName( _macroName ), - lineInfo( _lineInfo ), - capturedExpression( _capturedExpression ), - resultDisposition( _resultDisposition ) - {} - - AssertionResult::AssertionResult() {} - - AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) - : m_info( info ), - m_resultData( data ) - {} - - AssertionResult::~AssertionResult() {} - - // Result was a success - bool AssertionResult::succeeded() const { - return Catch::isOk( m_resultData.resultType ); - } - - // Result was a success, or failure is suppressed - bool AssertionResult::isOk() const { - return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); - } - - ResultWas::OfType AssertionResult::getResultType() const { - return m_resultData.resultType; - } - - bool AssertionResult::hasExpression() const { - return !m_info.capturedExpression.empty(); - } - - bool AssertionResult::hasMessage() const { - return !m_resultData.message.empty(); - } - - std::string AssertionResult::getExpression() const { - if( shouldNegate( m_info.resultDisposition ) ) - return "!" + m_info.capturedExpression; - else - return m_info.capturedExpression; - } - std::string AssertionResult::getExpressionInMacro() const { - if( m_info.macroName.empty() ) - return m_info.capturedExpression; - else - return m_info.macroName + "( " + m_info.capturedExpression + " )"; - } - - bool AssertionResult::hasExpandedExpression() const { - return hasExpression() && getExpandedExpression() != getExpression(); - } - - std::string AssertionResult::getExpandedExpression() const { - return m_resultData.reconstructedExpression; - } - - std::string AssertionResult::getMessage() const { - return m_resultData.message; - } - SourceLineInfo AssertionResult::getSourceInfo() const { - return m_info.lineInfo; - } - - std::string AssertionResult::getTestMacroName() const { - return m_info.macroName; - } - -} // end namespace Catch - -// #included from: catch_expressionresult_builder.hpp -#define TWOBLUECUBES_CATCH_EXPRESSIONRESULT_BUILDER_HPP_INCLUDED - -#include <assert.h> - -namespace Catch { - - ExpressionResultBuilder::ExpressionResultBuilder( ResultWas::OfType resultType ) { - m_data.resultType = resultType; - } - ExpressionResultBuilder::ExpressionResultBuilder( ExpressionResultBuilder const& other ) - : m_data( other.m_data ), - m_exprComponents( other.m_exprComponents ) - { - m_stream << other.m_stream.str(); - } - ExpressionResultBuilder& ExpressionResultBuilder::operator=(ExpressionResultBuilder const& other ) { - m_data = other.m_data; - m_exprComponents = other.m_exprComponents; - m_stream.str(""); - m_stream << other.m_stream.str(); - return *this; - } - ExpressionResultBuilder& ExpressionResultBuilder::setResultType( ResultWas::OfType result ) { - m_data.resultType = result; - return *this; - } - ExpressionResultBuilder& ExpressionResultBuilder::setResultType( bool result ) { - m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; - return *this; - } - ExpressionResultBuilder& ExpressionResultBuilder::endExpression( ResultDisposition::Flags resultDisposition ) { - m_exprComponents.shouldNegate = shouldNegate( resultDisposition ); - return *this; - } - ExpressionResultBuilder& ExpressionResultBuilder::setLhs( std::string const& lhs ) { - m_exprComponents.lhs = lhs; - return *this; - } - ExpressionResultBuilder& ExpressionResultBuilder::setRhs( std::string const& rhs ) { - m_exprComponents.rhs = rhs; - return *this; - } - ExpressionResultBuilder& ExpressionResultBuilder::setOp( std::string const& op ) { - m_exprComponents.op = op; - return *this; - } - AssertionResult ExpressionResultBuilder::buildResult( AssertionInfo const& info ) const - { - assert( m_data.resultType != ResultWas::Unknown ); - - AssertionResultData data = m_data; - - // Flip bool results if shouldNegate is set - if( m_exprComponents.shouldNegate && data.resultType == ResultWas::Ok ) - data.resultType = ResultWas::ExpressionFailed; - else if( m_exprComponents.shouldNegate && data.resultType == ResultWas::ExpressionFailed ) - data.resultType = ResultWas::Ok; - - data.message = m_stream.str(); - data.reconstructedExpression = reconstructExpression( info ); - if( m_exprComponents.shouldNegate ) { - if( m_exprComponents.op == "" ) - data.reconstructedExpression = "!" + data.reconstructedExpression; - else - data.reconstructedExpression = "!(" + data.reconstructedExpression + ")"; - } - return AssertionResult( info, data ); - } - std::string ExpressionResultBuilder::reconstructExpression( AssertionInfo const& info ) const { - if( m_exprComponents.op == "" ) - return m_exprComponents.lhs.empty() ? info.capturedExpression : m_exprComponents.op + m_exprComponents.lhs; - else if( m_exprComponents.op == "matches" ) - return m_exprComponents.lhs + " " + m_exprComponents.rhs; - else if( m_exprComponents.op != "!" ) { - if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 && - m_exprComponents.lhs.find("\n") == std::string::npos && - m_exprComponents.rhs.find("\n") == std::string::npos ) - return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs; - else - return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs; - } - else - return "{can't expand - use " + info.macroName + "_FALSE( " + info.capturedExpression.substr(1) + " ) instead of " + info.macroName + "( " + info.capturedExpression + " ) for better diagnostics}"; - } - -} // end namespace Catch - -// #included from: catch_test_case_info.hpp -#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED - -namespace Catch { - - TestCase makeTestCase( ITestCase* _testCase, - std::string const& _className, - std::string const& _name, - std::string const& _descOrTags, - SourceLineInfo const& _lineInfo ) - { - std::string desc = _descOrTags; - bool isHidden( startsWith( _name, "./" ) ); // Legacy support - std::set<std::string> tags; - TagExtracter( tags ).parse( desc ); - if( tags.find( "hide" ) != tags.end() || tags.find( "." ) != tags.end() ) - isHidden = true; - - if( isHidden ) { - tags.insert( "hide" ); - tags.insert( "." ); - } - TestCaseInfo info( _name, _className, desc, tags, isHidden, _lineInfo ); - return TestCase( _testCase, info ); - } - - TestCaseInfo::TestCaseInfo( std::string const& _name, - std::string const& _className, - std::string const& _description, - std::set<std::string> const& _tags, - bool _isHidden, - SourceLineInfo const& _lineInfo ) - : name( _name ), - className( _className ), - description( _description ), - tags( _tags ), - lineInfo( _lineInfo ), - isHidden( _isHidden ) - { - std::ostringstream oss; - for( std::set<std::string>::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) - oss << "[" << *it << "]"; - tagsAsString = oss.str(); - } - - TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) - : name( other.name ), - className( other.className ), - description( other.description ), - tags( other.tags ), - tagsAsString( other.tagsAsString ), - lineInfo( other.lineInfo ), - isHidden( other.isHidden ) - {} - - TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} - - TestCase::TestCase( TestCase const& other ) - : TestCaseInfo( other ), - test( other.test ) - {} - - TestCase TestCase::withName( std::string const& _newName ) const { - TestCase other( *this ); - other.name = _newName; - return other; - } - - void TestCase::invoke() const { - test->invoke(); - } - - bool TestCase::isHidden() const { - return TestCaseInfo::isHidden; - } - - bool TestCase::hasTag( std::string const& tag ) const { - return tags.find( toLower( tag ) ) != tags.end(); - } - bool TestCase::matchesTags( std::string const& tagPattern ) const { - TagExpression exp; - TagExpressionParser( exp ).parse( tagPattern ); - return exp.matches( tags ); - } - std::set<std::string> const& TestCase::getTags() const { - return tags; - } - - void TestCase::swap( TestCase& other ) { - test.swap( other.test ); - className.swap( other.className ); - name.swap( other.name ); - description.swap( other.description ); - std::swap( lineInfo, other.lineInfo ); - } - - bool TestCase::operator == ( TestCase const& other ) const { - return test.get() == other.test.get() && - name == other.name && - className == other.className; - } - - bool TestCase::operator < ( TestCase const& other ) const { - return name < other.name; - } - TestCase& TestCase::operator = ( TestCase const& other ) { - TestCase temp( other ); - swap( temp ); - return *this; - } - - TestCaseInfo const& TestCase::getTestCaseInfo() const - { - return *this; - } - -} // end namespace Catch - -// #included from: catch_tags.hpp -#define TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED - -namespace Catch { - TagParser::~TagParser() {} - - void TagParser::parse( std::string const& str ) { - std::size_t pos = 0; - while( pos < str.size() ) { - char c = str[pos]; - if( c == '[' ) { - std::size_t end = str.find_first_of( ']', pos ); - if( end != std::string::npos ) { - acceptTag( str.substr( pos+1, end-pos-1 ) ); - pos = end+1; - } - else { - acceptChar( c ); - pos++; - } - } - else { - acceptChar( c ); - pos++; - } - } - endParse(); - } - - TagExtracter::TagExtracter( std::set<std::string>& tags ) - : m_tags( tags ) - {} - - TagExtracter::~TagExtracter() {} - - void TagExtracter::parse( std::string& description ) { - TagParser::parse( description ); - description = m_remainder; - } - - void TagExtracter::acceptTag( std::string const& tag ) { - m_tags.insert( toLower( tag ) ); - } - void TagExtracter::acceptChar( char c ) { - m_remainder += c; - } - - Tag::Tag() : m_isNegated( false ) {} - Tag::Tag( std::string const& name, bool isNegated ) - : m_name( name ), - m_isNegated( isNegated ) - {} - - std::string Tag::getName() const { - return m_name; - } - bool Tag::isNegated() const { - return m_isNegated; - } - - bool Tag::operator ! () const { - return m_name.empty(); - } - - void TagSet::add( Tag const& tag ) { - m_tags.insert( std::make_pair( toLower( tag.getName() ), tag ) ); - } - - bool TagSet::empty() const { - return m_tags.empty(); - } - - bool TagSet::matches( std::set<std::string> const& tags ) const { - for( TagMap::const_iterator - it = m_tags.begin(), itEnd = m_tags.end(); - it != itEnd; - ++it ) { - bool found = tags.find( it->first ) != tags.end(); - if( found == it->second.isNegated() ) - return false; - } - return true; - } - - bool TagExpression::matches( std::set<std::string> const& tags ) const { - for( std::vector<TagSet>::const_iterator - it = m_tagSets.begin(), itEnd = m_tagSets.end(); - it != itEnd; - ++it ) - if( it->matches( tags ) ) - return true; - return false; - } - - TagExpressionParser::TagExpressionParser( TagExpression& exp ) - : m_isNegated( false ), - m_exp( exp ) - {} - - TagExpressionParser::~TagExpressionParser() {} - - void TagExpressionParser::acceptTag( std::string const& tag ) { - m_currentTagSet.add( Tag( tag, m_isNegated ) ); - m_isNegated = false; - } - - void TagExpressionParser::acceptChar( char c ) { - switch( c ) { - case '~': - m_isNegated = true; - break; - case ',': - m_exp.m_tagSets.push_back( m_currentTagSet ); - m_currentTagSet = TagSet(); - break; - } - } - - void TagExpressionParser::endParse() { - if( !m_currentTagSet.empty() ) - m_exp.m_tagSets.push_back( m_currentTagSet ); - } - -} // end namespace Catch - -// #included from: catch_test_spec.hpp -#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED - -namespace Catch { - - TestCaseFilter::TestCaseFilter( std::string const& testSpec, IfFilterMatches::DoWhat matchBehaviour ) - : m_stringToMatch( toLower( testSpec ) ), - m_filterType( matchBehaviour ), - m_wildcardPosition( NoWildcard ) - { - if( m_filterType == IfFilterMatches::AutoDetectBehaviour ) { - if( startsWith( m_stringToMatch, "exclude:" ) ) { - m_stringToMatch = m_stringToMatch.substr( 8 ); - m_filterType = IfFilterMatches::ExcludeTests; - } - else if( startsWith( m_stringToMatch, "~" ) ) { - m_stringToMatch = m_stringToMatch.substr( 1 ); - m_filterType = IfFilterMatches::ExcludeTests; - } - else { - m_filterType = IfFilterMatches::IncludeTests; - } - } - - if( startsWith( m_stringToMatch, "*" ) ) { - m_stringToMatch = m_stringToMatch.substr( 1 ); - m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtStart ); - } - if( endsWith( m_stringToMatch, "*" ) ) { - m_stringToMatch = m_stringToMatch.substr( 0, m_stringToMatch.size()-1 ); - m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtEnd ); - } - } - - IfFilterMatches::DoWhat TestCaseFilter::getFilterType() const { - return m_filterType; - } - - bool TestCaseFilter::shouldInclude( TestCase const& testCase ) const { - return isMatch( testCase ) == (m_filterType == IfFilterMatches::IncludeTests); - } - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunreachable-code" -#endif - - bool TestCaseFilter::isMatch( TestCase const& testCase ) const { - std::string name = testCase.getTestCaseInfo().name; - toLowerInPlace( name ); - - switch( m_wildcardPosition ) { - case NoWildcard: - return m_stringToMatch == name; - case WildcardAtStart: - return endsWith( name, m_stringToMatch ); - case WildcardAtEnd: - return startsWith( name, m_stringToMatch ); - case WildcardAtBothEnds: - return contains( name, m_stringToMatch ); - } - throw std::logic_error( "Unhandled wildcard type" ); - } - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - - TestCaseFilters::TestCaseFilters( std::string const& name ) : m_name( name ) {} - - std::string TestCaseFilters::getName() const { - return m_name; - } - - void TestCaseFilters::addFilter( TestCaseFilter const& filter ) { - if( filter.getFilterType() == IfFilterMatches::ExcludeTests ) - m_exclusionFilters.push_back( filter ); - else - m_inclusionFilters.push_back( filter ); - } - - void TestCaseFilters::addTags( std::string const& tagPattern ) { - TagExpression exp; - TagExpressionParser( exp ).parse( tagPattern ); - - m_tagExpressions.push_back( exp ); - } - - bool TestCaseFilters::shouldInclude( TestCase const& testCase ) const { - if( !m_tagExpressions.empty() ) { - std::vector<TagExpression>::const_iterator it = m_tagExpressions.begin(); - std::vector<TagExpression>::const_iterator itEnd = m_tagExpressions.end(); - for(; it != itEnd; ++it ) - if( it->matches( testCase.getTags() ) ) - break; - if( it == itEnd ) - return false; - } - - if( !m_inclusionFilters.empty() ) { - std::vector<TestCaseFilter>::const_iterator it = m_inclusionFilters.begin(); - std::vector<TestCaseFilter>::const_iterator itEnd = m_inclusionFilters.end(); - for(; it != itEnd; ++it ) - if( it->shouldInclude( testCase ) ) - break; - if( it == itEnd ) - return false; - } - else if( m_exclusionFilters.empty() && m_tagExpressions.empty() ) { - return !testCase.isHidden(); - } - - std::vector<TestCaseFilter>::const_iterator it = m_exclusionFilters.begin(); - std::vector<TestCaseFilter>::const_iterator itEnd = m_exclusionFilters.end(); - for(; it != itEnd; ++it ) - if( !it->shouldInclude( testCase ) ) - return false; - return true; - } -} - -// #included from: catch_version.hpp -#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED - -namespace Catch { - - // These numbers are maintained by a script - Version libraryVersion( 1, 0, 27, "master" ); -} - -// #included from: catch_message.hpp -#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED - -namespace Catch { - - MessageInfo::MessageInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - ResultWas::OfType _type ) - : macroName( _macroName ), - lineInfo( _lineInfo ), - type( _type ), - sequence( ++globalCount ) - {} - - // This may need protecting if threading support is added - unsigned int MessageInfo::globalCount = 0; - - //////////////////////////////////////////////////////////////////////////// - - ScopedMessage::ScopedMessage( MessageBuilder const& builder ) - : m_info( builder.m_info ) - { - m_info.message = builder.m_stream.str(); - getResultCapture().pushScopedMessage( m_info ); - } - ScopedMessage::~ScopedMessage() { - getResultCapture().popScopedMessage( m_info ); - } - -} // end namespace Catch - -// #included from: catch_legacy_reporter_adapter.hpp -#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED - -// #included from: catch_legacy_reporter_adapter.h -#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED - -namespace Catch -{ - // Deprecated - struct IReporter : IShared { - virtual ~IReporter(); - - virtual bool shouldRedirectStdout() const = 0; - - virtual void StartTesting() = 0; - virtual void EndTesting( Totals const& totals ) = 0; - virtual void StartGroup( std::string const& groupName ) = 0; - virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; - virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; - virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; - virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; - virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; - virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; - virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; - virtual void Aborted() = 0; - virtual void Result( AssertionResult const& result ) = 0; - }; - - class LegacyReporterAdapter : public SharedImpl<IStreamingReporter> - { - public: - LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter ); - virtual ~LegacyReporterAdapter(); - - virtual ReporterPreferences getPreferences() const; - virtual void noMatchingTestCases( std::string const& ); - virtual void testRunStarting( TestRunInfo const& ); - virtual void testGroupStarting( GroupInfo const& groupInfo ); - virtual void testCaseStarting( TestCaseInfo const& testInfo ); - virtual void sectionStarting( SectionInfo const& sectionInfo ); - virtual void assertionStarting( AssertionInfo const& ); - virtual bool assertionEnded( AssertionStats const& assertionStats ); - virtual void sectionEnded( SectionStats const& sectionStats ); - virtual void testCaseEnded( TestCaseStats const& testCaseStats ); - virtual void testGroupEnded( TestGroupStats const& testGroupStats ); - virtual void testRunEnded( TestRunStats const& testRunStats ); - - private: - Ptr<IReporter> m_legacyReporter; - }; -} - -namespace Catch -{ - LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter ) - : m_legacyReporter( legacyReporter ) - {} - LegacyReporterAdapter::~LegacyReporterAdapter() {} - - ReporterPreferences LegacyReporterAdapter::getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); - return prefs; - } - - void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} - void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { - m_legacyReporter->StartTesting(); - } - void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { - m_legacyReporter->StartGroup( groupInfo.name ); - } - void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { - m_legacyReporter->StartTestCase( testInfo ); - } - void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { - m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); - } - void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { - // Not on legacy interface - } - - bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { - if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { - for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); - it != itEnd; - ++it ) { - if( it->type == ResultWas::Info ) { - ExpressionResultBuilder expressionBuilder( it->type ); - expressionBuilder << it->message; - AssertionInfo info( it->macroName, it->lineInfo, "", ResultDisposition::Normal ); - AssertionResult result = expressionBuilder.buildResult( info ); - m_legacyReporter->Result( result ); - } - } - } - m_legacyReporter->Result( assertionStats.assertionResult ); - return true; - } - void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { - if( sectionStats.missingAssertions ) - m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); - m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); - } - void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { - m_legacyReporter->EndTestCase - ( testCaseStats.testInfo, - testCaseStats.totals, - testCaseStats.stdOut, - testCaseStats.stdErr ); - } - void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { - if( testGroupStats.aborting ) - m_legacyReporter->Aborted(); - m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); - } - void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { - m_legacyReporter->EndTesting( testRunStats.totals ); - } -} - -// #included from: catch_timer.hpp - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wc++11-long-long" -#endif - -#ifdef CATCH_PLATFORM_WINDOWS -#include <windows.h> -#else -#include <sys/time.h> -#endif - -namespace Catch { - - namespace { -#ifdef CATCH_PLATFORM_WINDOWS - uint64_t getCurrentTicks() { - static uint64_t hz=0, hzo=0; - if (!hz) { - QueryPerformanceFrequency((LARGE_INTEGER*)&hz); - QueryPerformanceCounter((LARGE_INTEGER*)&hzo); - } - uint64_t t; - QueryPerformanceCounter((LARGE_INTEGER*)&t); - return ((t-hzo)*1000000)/hz; - } -#else - uint64_t getCurrentTicks() { - timeval t; - gettimeofday(&t,NULL); - return (uint64_t)t.tv_sec * 1000000ull + (uint64_t)t.tv_usec; - } -#endif - } - - void Timer::start() { - m_ticks = getCurrentTicks(); - } - unsigned int Timer::getElapsedNanoseconds() const { - return (unsigned int)(getCurrentTicks() - m_ticks); - } - unsigned int Timer::getElapsedMilliseconds() const { - return (unsigned int)((getCurrentTicks() - m_ticks)/1000); - } - double Timer::getElapsedSeconds() const { - return (getCurrentTicks() - m_ticks)/1000000.0; - } - -} // namespace Catch - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif -// #included from: catch_common.hpp -#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED - -namespace Catch { - - bool startsWith( std::string const& s, std::string const& prefix ) { - return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix; - } - bool endsWith( std::string const& s, std::string const& suffix ) { - return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix; - } - bool contains( std::string const& s, std::string const& infix ) { - return s.find( infix ) != std::string::npos; - } - void toLowerInPlace( std::string& s ) { - std::transform( s.begin(), s.end(), s.begin(), ::tolower ); - } - std::string toLower( std::string const& s ) { - std::string lc = s; - toLowerInPlace( lc ); - return lc; - } - std::string trim( std::string const& str ) { - static char const* whitespaceChars = "\n\r\t "; - std::string::size_type start = str.find_first_not_of( whitespaceChars ); - std::string::size_type end = str.find_last_not_of( whitespaceChars ); - - return start != std::string::npos ? str.substr( start, 1+end-start ) : ""; - } - - pluralise::pluralise( std::size_t count, std::string const& label ) - : m_count( count ), - m_label( label ) - {} - - std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { - os << pluraliser.m_count << " " << pluraliser.m_label; - if( pluraliser.m_count != 1 ) - os << "s"; - return os; - } - - SourceLineInfo::SourceLineInfo() : line( 0 ){} - SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) - : file( _file ), - line( _line ) - {} - SourceLineInfo::SourceLineInfo( SourceLineInfo const& other ) - : file( other.file ), - line( other.line ) - {} - bool SourceLineInfo::empty() const { - return file.empty(); - } - bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { - return line == other.line && file == other.file; - } - - std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { -#ifndef __GNUG__ - os << info.file << "(" << info.line << ")"; -#else - os << info.file << ":" << info.line; -#endif - return os; - } - - void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { - std::ostringstream oss; - oss << locationInfo << ": Internal Catch error: '" << message << "'"; - if( isTrue( true )) - throw std::logic_error( oss.str() ); - } -} - -// #included from: catch_section.hpp -#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED - -namespace Catch { - - Section::Section( SourceLineInfo const& lineInfo, - std::string const& name, - std::string const& description ) - : m_info( name, description, lineInfo ), - m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( m_info, m_assertions ) ) - { - m_timer.start(); - } - - Section::~Section() { - if( m_sectionIncluded ) - getCurrentContext().getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() ); - } - - // This indicates whether the section should be executed or not - Section::operator bool() { - return m_sectionIncluded; - } - -} // end namespace Catch - -// #included from: catch_debugger.hpp -#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED - -#include <iostream> - -#ifdef CATCH_PLATFORM_MAC - - #include <assert.h> - #include <stdbool.h> - #include <sys/types.h> - #include <unistd.h> - #include <sys/sysctl.h> - - namespace Catch{ - - // The following function is taken directly from the following technical note: - // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html - - // Returns true if the current process is being debugged (either - // running under the debugger or has a debugger attached post facto). - bool isDebuggerActive(){ - - int mib[4]; - struct kinfo_proc info; - size_t size; - - // Initialize the flags so that, if sysctl fails for some bizarre - // reason, we get a predictable result. - - info.kp_proc.p_flag = 0; - - // Initialize mib, which tells sysctl the info we want, in this case - // we're looking for information about a specific process ID. - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = getpid(); - - // Call sysctl. - - size = sizeof(info); - if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) { - std::cerr << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; - return false; - } - - // We're being debugged if the P_TRACED flag is set. - - return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); - } - } // namespace Catch - -#elif defined(_MSC_VER) - extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); - namespace Catch { - bool isDebuggerActive() { - return IsDebuggerPresent() != 0; - } - } -#elif defined(__MINGW32__) - extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); - namespace Catch { - bool isDebuggerActive() { - return IsDebuggerPresent() != 0; - } - } -#else - namespace Catch { - inline bool isDebuggerActive() { return false; } - } -#endif // Platform - -#ifdef CATCH_PLATFORM_WINDOWS - extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); - namespace Catch { - void writeToDebugConsole( std::string const& text ) { - ::OutputDebugStringA( text.c_str() ); - } - } -#else - namespace Catch { - void writeToDebugConsole( std::string const& text ) { - // !TBD: Need a version for Mac/ XCode and other IDEs - std::cout << text; - } - } -#endif // Platform - -// #included from: ../reporters/catch_reporter_xml.hpp -#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED - -// #included from: catch_reporter_bases.hpp -#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED - -namespace Catch { - - struct StreamingReporterBase : SharedImpl<IStreamingReporter> { - - StreamingReporterBase( ReporterConfig const& _config ) - : m_config( _config.fullConfig() ), - stream( _config.stream() ) - {} - - virtual ~StreamingReporterBase(); - - virtual void noMatchingTestCases( std::string const& ) {} - - virtual void testRunStarting( TestRunInfo const& _testRunInfo ) { - currentTestRunInfo = _testRunInfo; - } - virtual void testGroupStarting( GroupInfo const& _groupInfo ) { - currentGroupInfo = _groupInfo; - } - - virtual void testCaseStarting( TestCaseInfo const& _testInfo ) { - currentTestCaseInfo = _testInfo; - } - virtual void sectionStarting( SectionInfo const& _sectionInfo ) { - m_sectionStack.push_back( _sectionInfo ); - } - - virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) { - m_sectionStack.pop_back(); - } - virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) { - currentTestCaseInfo.reset(); - assert( m_sectionStack.empty() ); - } - virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) { - currentGroupInfo.reset(); - } - virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) { - currentTestCaseInfo.reset(); - currentGroupInfo.reset(); - currentTestRunInfo.reset(); - } - - Ptr<IConfig> m_config; - std::ostream& stream; - - LazyStat<TestRunInfo> currentTestRunInfo; - LazyStat<GroupInfo> currentGroupInfo; - LazyStat<TestCaseInfo> currentTestCaseInfo; - - std::vector<SectionInfo> m_sectionStack; - }; - - struct CumulativeReporterBase : SharedImpl<IStreamingReporter> { - template<typename T, typename ChildNodeT> - struct Node : SharedImpl<> { - explicit Node( T const& _value ) : value( _value ) {} - virtual ~Node() {} - - typedef std::vector<Ptr<ChildNodeT> > ChildNodes; - T value; - ChildNodes children; - }; - struct SectionNode : SharedImpl<> { - explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} - virtual ~SectionNode(); - - bool operator == ( SectionNode const& other ) const { - return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; - } - bool operator == ( Ptr<SectionNode> const& other ) const { - return operator==( *other ); - } - - SectionStats stats; - typedef std::vector<Ptr<SectionNode> > ChildSections; - typedef std::vector<AssertionStats> Assertions; - ChildSections childSections; - Assertions assertions; - std::string stdOut; - std::string stdErr; - }; - - struct BySectionInfo { - BySectionInfo( SectionInfo const& other ) : m_other( other ) {} - bool operator() ( Ptr<SectionNode> const& node ) const { - return node->stats.sectionInfo.lineInfo == m_other.lineInfo; - } - private: - BySectionInfo& operator=( BySectionInfo const& other ); // = delete; - - SectionInfo const& m_other; - }; - - typedef Node<TestCaseStats, SectionNode> TestCaseNode; - typedef Node<TestGroupStats, TestCaseNode> TestGroupNode; - typedef Node<TestRunStats, TestGroupNode> TestRunNode; - - CumulativeReporterBase( ReporterConfig const& _config ) - : m_config( _config.fullConfig() ), - stream( _config.stream() ) - {} - ~CumulativeReporterBase(); - - virtual void testRunStarting( TestRunInfo const& ) {} - virtual void testGroupStarting( GroupInfo const& ) {} - - virtual void testCaseStarting( TestCaseInfo const& ) {} - - virtual void sectionStarting( SectionInfo const& sectionInfo ) { - SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); - Ptr<SectionNode> node; - if( m_sectionStack.empty() ) { - if( !m_rootSection ) - m_rootSection = new SectionNode( incompleteStats ); - node = m_rootSection; - } - else { - SectionNode& parentNode = *m_sectionStack.back(); - SectionNode::ChildSections::const_iterator it = - std::find_if( parentNode.childSections.begin(), - parentNode.childSections.end(), - BySectionInfo( sectionInfo ) ); - if( it == parentNode.childSections.end() ) { - node = new SectionNode( incompleteStats ); - parentNode.childSections.push_back( node ); - } - else - node = *it; - } - m_sectionStack.push_back( node ); - m_deepestSection = node; - } - - virtual void assertionStarting( AssertionInfo const& ) {} - - virtual bool assertionEnded( AssertionStats const& assertionStats ) { - assert( !m_sectionStack.empty() ); - SectionNode& sectionNode = *m_sectionStack.back(); - sectionNode.assertions.push_back( assertionStats ); - return true; - } - virtual void sectionEnded( SectionStats const& sectionStats ) { - assert( !m_sectionStack.empty() ); - SectionNode& node = *m_sectionStack.back(); - node.stats = sectionStats; - m_sectionStack.pop_back(); - } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { - Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats ); - assert( m_sectionStack.size() == 0 ); - node->children.push_back( m_rootSection ); - m_testCases.push_back( node ); - m_rootSection.reset(); - - assert( m_deepestSection ); - m_deepestSection->stdOut = testCaseStats.stdOut; - m_deepestSection->stdErr = testCaseStats.stdErr; - } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { - Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats ); - node->children.swap( m_testCases ); - m_testGroups.push_back( node ); - } - virtual void testRunEnded( TestRunStats const& testRunStats ) { - Ptr<TestRunNode> node = new TestRunNode( testRunStats ); - node->children.swap( m_testGroups ); - m_testRuns.push_back( node ); - testRunEndedCumulative(); - } - virtual void testRunEndedCumulative() = 0; - - Ptr<IConfig> m_config; - std::ostream& stream; - std::vector<AssertionStats> m_assertions; - std::vector<std::vector<Ptr<SectionNode> > > m_sections; - std::vector<Ptr<TestCaseNode> > m_testCases; - std::vector<Ptr<TestGroupNode> > m_testGroups; - - std::vector<Ptr<TestRunNode> > m_testRuns; - - Ptr<SectionNode> m_rootSection; - Ptr<SectionNode> m_deepestSection; - std::vector<Ptr<SectionNode> > m_sectionStack; - - }; - -} // end namespace Catch - -// #included from: ../internal/catch_reporter_registrars.hpp -#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED - -namespace Catch { - - template<typename T> - class LegacyReporterRegistrar { - - class ReporterFactory : public IReporterFactory { - virtual IStreamingReporter* create( ReporterConfig const& config ) const { - return new LegacyReporterAdapter( new T( config ) ); - } - - virtual std::string getDescription() const { - return T::getDescription(); - } - }; - - public: - - LegacyReporterRegistrar( std::string const& name ) { - getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); - } - }; - - template<typename T> - class ReporterRegistrar { - - class ReporterFactory : public IReporterFactory { - - // *** Please Note ***: - // - If you end up here looking at a compiler error because it's trying to register - // your custom reporter class be aware that the native reporter interface has changed - // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via - // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. - // However please consider updating to the new interface as the old one is now - // deprecated and will probably be removed quite soon! - // Please contact me via github if you have any questions at all about this. - // In fact, ideally, please contact me anyway to let me know you've hit this - as I have - // no idea who is actually using custom reporters at all (possibly no-one!). - // The new interface is designed to minimise exposure to interface changes in the future. - virtual IStreamingReporter* create( ReporterConfig const& config ) const { - return new T( config ); - } - - virtual std::string getDescription() const { - return T::getDescription(); - } - }; - - public: - - ReporterRegistrar( std::string const& name ) { - getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); - } - }; -} - -#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ - namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } -#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ - namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } - -// #included from: ../internal/catch_xmlwriter.hpp -#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED - -#include <sstream> -#include <iostream> -#include <string> -#include <vector> - -namespace Catch { - - class XmlWriter { - public: - - class ScopedElement { - public: - ScopedElement( XmlWriter* writer ) - : m_writer( writer ) - {} - - ScopedElement( ScopedElement const& other ) - : m_writer( other.m_writer ){ - other.m_writer = NULL; - } - - ~ScopedElement() { - if( m_writer ) - m_writer->endElement(); - } - - ScopedElement& writeText( std::string const& text, bool indent = true ) { - m_writer->writeText( text, indent ); - return *this; - } - - template<typename T> - ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { - m_writer->writeAttribute( name, attribute ); - return *this; - } - - private: - mutable XmlWriter* m_writer; - }; - - XmlWriter() - : m_tagIsOpen( false ), - m_needsNewline( false ), - m_os( &std::cout ) - {} - - XmlWriter( std::ostream& os ) - : m_tagIsOpen( false ), - m_needsNewline( false ), - m_os( &os ) - {} - - ~XmlWriter() { - while( !m_tags.empty() ) - endElement(); - } - - XmlWriter& operator = ( XmlWriter const& other ) { - XmlWriter temp( other ); - swap( temp ); - return *this; - } - - void swap( XmlWriter& other ) { - std::swap( m_tagIsOpen, other.m_tagIsOpen ); - std::swap( m_needsNewline, other.m_needsNewline ); - std::swap( m_tags, other.m_tags ); - std::swap( m_indent, other.m_indent ); - std::swap( m_os, other.m_os ); - } - - XmlWriter& startElement( std::string const& name ) { - ensureTagClosed(); - newlineIfNecessary(); - stream() << m_indent << "<" << name; - m_tags.push_back( name ); - m_indent += " "; - m_tagIsOpen = true; - return *this; - } - - ScopedElement scopedElement( std::string const& name ) { - ScopedElement scoped( this ); - startElement( name ); - return scoped; - } - - XmlWriter& endElement() { - newlineIfNecessary(); - m_indent = m_indent.substr( 0, m_indent.size()-2 ); - if( m_tagIsOpen ) { - stream() << "/>\n"; - m_tagIsOpen = false; - } - else { - stream() << m_indent << "</" << m_tags.back() << ">\n"; - } - m_tags.pop_back(); - return *this; - } - - XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { - if( !name.empty() && !attribute.empty() ) { - stream() << " " << name << "=\""; - writeEncodedText( attribute ); - stream() << "\""; - } - return *this; - } - - XmlWriter& writeAttribute( std::string const& name, bool attribute ) { - stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\""; - return *this; - } - - template<typename T> - XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { - if( !name.empty() ) - stream() << " " << name << "=\"" << attribute << "\""; - return *this; - } - - XmlWriter& writeText( std::string const& text, bool indent = true ) { - if( !text.empty() ){ - bool tagWasOpen = m_tagIsOpen; - ensureTagClosed(); - if( tagWasOpen && indent ) - stream() << m_indent; - writeEncodedText( text ); - m_needsNewline = true; - } - return *this; - } - - XmlWriter& writeComment( std::string const& text ) { - ensureTagClosed(); - stream() << m_indent << "<!--" << text << "-->"; - m_needsNewline = true; - return *this; - } - - XmlWriter& writeBlankLine() { - ensureTagClosed(); - stream() << "\n"; - return *this; - } - - private: - - std::ostream& stream() { - return *m_os; - } - - void ensureTagClosed() { - if( m_tagIsOpen ) { - stream() << ">\n"; - m_tagIsOpen = false; - } - } - - void newlineIfNecessary() { - if( m_needsNewline ) { - stream() << "\n"; - m_needsNewline = false; - } - } - - void writeEncodedText( std::string const& text ) { - static const char* charsToEncode = "<&\""; - std::string mtext = text; - std::string::size_type pos = mtext.find_first_of( charsToEncode ); - while( pos != std::string::npos ) { - stream() << mtext.substr( 0, pos ); - - switch( mtext[pos] ) { - case '<': - stream() << "<"; - break; - case '&': - stream() << "&"; - break; - case '\"': - stream() << """; - break; - } - mtext = mtext.substr( pos+1 ); - pos = mtext.find_first_of( charsToEncode ); - } - stream() << mtext; - } - - bool m_tagIsOpen; - bool m_needsNewline; - std::vector<std::string> m_tags; - std::string m_indent; - std::ostream* m_os; - }; - -} -namespace Catch { - class XmlReporter : public SharedImpl<IReporter> { - public: - XmlReporter( ReporterConfig const& config ) : m_config( config ), m_sectionDepth( 0 ) {} - - static std::string getDescription() { - return "Reports test results as an XML document"; - } - virtual ~XmlReporter(); - - private: // IReporter - - virtual bool shouldRedirectStdout() const { - return true; - } - - virtual void StartTesting() { - m_xml = XmlWriter( m_config.stream() ); - m_xml.startElement( "Catch" ); - if( !m_config.fullConfig()->name().empty() ) - m_xml.writeAttribute( "name", m_config.fullConfig()->name() ); - } - - virtual void EndTesting( const Totals& totals ) { - m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", totals.assertions.passed ) - .writeAttribute( "failures", totals.assertions.failed ); - m_xml.endElement(); - } - - virtual void StartGroup( const std::string& groupName ) { - m_xml.startElement( "Group" ) - .writeAttribute( "name", groupName ); - } - - virtual void EndGroup( const std::string&, const Totals& totals ) { - m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", totals.assertions.passed ) - .writeAttribute( "failures", totals.assertions.failed ); - m_xml.endElement(); - } - - virtual void StartSection( const std::string& sectionName, const std::string& description ) { - if( m_sectionDepth++ > 0 ) { - m_xml.startElement( "Section" ) - .writeAttribute( "name", trim( sectionName ) ) - .writeAttribute( "description", description ); - } - } - virtual void NoAssertionsInSection( const std::string& ) {} - virtual void NoAssertionsInTestCase( const std::string& ) {} - - virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) { - if( --m_sectionDepth > 0 ) { - m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", assertions.passed ) - .writeAttribute( "failures", assertions.failed ); - m_xml.endElement(); - } - } - - virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) { - m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); - m_currentTestSuccess = true; - } - - virtual void Result( const Catch::AssertionResult& assertionResult ) { - if( !m_config.fullConfig()->includeSuccessfulResults() && assertionResult.getResultType() == ResultWas::Ok ) - return; - - if( assertionResult.hasExpression() ) { - m_xml.startElement( "Expression" ) - .writeAttribute( "success", assertionResult.succeeded() ) - .writeAttribute( "filename", assertionResult.getSourceInfo().file ) - .writeAttribute( "line", assertionResult.getSourceInfo().line ); - - m_xml.scopedElement( "Original" ) - .writeText( assertionResult.getExpression() ); - m_xml.scopedElement( "Expanded" ) - .writeText( assertionResult.getExpandedExpression() ); - m_currentTestSuccess &= assertionResult.succeeded(); - } - - switch( assertionResult.getResultType() ) { - case ResultWas::ThrewException: - m_xml.scopedElement( "Exception" ) - .writeAttribute( "filename", assertionResult.getSourceInfo().file ) - .writeAttribute( "line", assertionResult.getSourceInfo().line ) - .writeText( assertionResult.getMessage() ); - m_currentTestSuccess = false; - break; - case ResultWas::Info: - m_xml.scopedElement( "Info" ) - .writeText( assertionResult.getMessage() ); - break; - case ResultWas::Warning: - m_xml.scopedElement( "Warning" ) - .writeText( assertionResult.getMessage() ); - break; - case ResultWas::ExplicitFailure: - m_xml.scopedElement( "Failure" ) - .writeText( assertionResult.getMessage() ); - m_currentTestSuccess = false; - break; - case ResultWas::Unknown: - case ResultWas::Ok: - case ResultWas::FailureBit: - case ResultWas::ExpressionFailed: - case ResultWas::Exception: - case ResultWas::DidntThrowException: - break; - } - if( assertionResult.hasExpression() ) - m_xml.endElement(); - } - - virtual void Aborted() { - // !TBD - } - - virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, const std::string& ) { - m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess ); - m_xml.endElement(); - } - - private: - ReporterConfig m_config; - bool m_currentTestSuccess; - XmlWriter m_xml; - int m_sectionDepth; - }; - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_junit.hpp -#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED - -#include <assert.h> - -namespace Catch { - - class JunitReporter : public CumulativeReporterBase { - public: - JunitReporter( ReporterConfig const& _config ) - : CumulativeReporterBase( _config ), - xml( _config.stream() ) - {} - - ~JunitReporter(); - - static std::string getDescription() { - return "Reports test results in an XML format that looks like Ant's junitreport target"; - } - - virtual void noMatchingTestCases( std::string const& /*spec*/ ) {} - - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = true; - return prefs; - } - - virtual void testRunStarting( TestRunInfo const& runInfo ) { - CumulativeReporterBase::testRunStarting( runInfo ); - xml.startElement( "testsuites" ); - } - - virtual void testGroupStarting( GroupInfo const& groupInfo ) { - suiteTimer.start(); - stdOutForSuite.str(""); - stdErrForSuite.str(""); - unexpectedExceptions = 0; - CumulativeReporterBase::testGroupStarting( groupInfo ); - } - - virtual bool assertionEnded( AssertionStats const& assertionStats ) { - if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) - unexpectedExceptions++; - return CumulativeReporterBase::assertionEnded( assertionStats ); - } - - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { - stdOutForSuite << testCaseStats.stdOut; - stdErrForSuite << testCaseStats.stdErr; - CumulativeReporterBase::testCaseEnded( testCaseStats ); - } - - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { - double suiteTime = suiteTimer.getElapsedSeconds(); - CumulativeReporterBase::testGroupEnded( testGroupStats ); - writeGroup( *m_testGroups.back(), suiteTime ); - } - - virtual void testRunEndedCumulative() { - xml.endElement(); - } - - void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { - XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); - TestGroupStats const& stats = groupNode.value; - xml.writeAttribute( "name", stats.groupInfo.name ); - xml.writeAttribute( "errors", unexpectedExceptions ); - xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); - xml.writeAttribute( "tests", stats.totals.assertions.total() ); - xml.writeAttribute( "hostname", "tbd" ); // !TBD - if( m_config->showDurations() == ShowDurations::Never ) - xml.writeAttribute( "time", "" ); - else - xml.writeAttribute( "time", suiteTime ); - xml.writeAttribute( "timestamp", "tbd" ); // !TBD - - // Write test cases - for( TestGroupNode::ChildNodes::const_iterator - it = groupNode.children.begin(), itEnd = groupNode.children.end(); - it != itEnd; - ++it ) - writeTestCase( **it ); - - xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); - xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); - } - - void writeTestCase( TestCaseNode const& testCaseNode ) { - TestCaseStats const& stats = testCaseNode.value; - - // All test cases have exactly one section - which represents the - // test case itself. That section may have 0-n nested sections - assert( testCaseNode.children.size() == 1 ); - SectionNode const& rootSection = *testCaseNode.children.front(); - - std::string className = stats.testInfo.className; - - if( className.empty() ) { - if( rootSection.childSections.empty() ) - className = "global"; - } - writeSection( className, "", rootSection ); - } - - void writeSection( std::string const& className, - std::string const& rootName, - SectionNode const& sectionNode ) { - std::string name = trim( sectionNode.stats.sectionInfo.name ); - if( !rootName.empty() ) - name = rootName + "/" + name; - - if( !sectionNode.assertions.empty() || - !sectionNode.stdOut.empty() || - !sectionNode.stdErr.empty() ) { - XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); - if( className.empty() ) { - xml.writeAttribute( "classname", name ); - xml.writeAttribute( "name", "root" ); - } - else { - xml.writeAttribute( "classname", className ); - xml.writeAttribute( "name", name ); - } - xml.writeAttribute( "time", toString( sectionNode.stats.durationInSeconds ) ); - - writeAssertions( sectionNode ); - - if( !sectionNode.stdOut.empty() ) - xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); - if( !sectionNode.stdErr.empty() ) - xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); - } - for( SectionNode::ChildSections::const_iterator - it = sectionNode.childSections.begin(), - itEnd = sectionNode.childSections.end(); - it != itEnd; - ++it ) - if( className.empty() ) - writeSection( name, "", **it ); - else - writeSection( className, name, **it ); - } - - void writeAssertions( SectionNode const& sectionNode ) { - for( SectionNode::Assertions::const_iterator - it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); - it != itEnd; - ++it ) - writeAssertion( *it ); - } - void writeAssertion( AssertionStats const& stats ) { - AssertionResult const& result = stats.assertionResult; - if( !result.isOk() ) { - std::string elementName; - switch( result.getResultType() ) { - case ResultWas::ThrewException: - elementName = "error"; - break; - case ResultWas::ExplicitFailure: - elementName = "failure"; - break; - case ResultWas::ExpressionFailed: - elementName = "failure"; - break; - case ResultWas::DidntThrowException: - elementName = "failure"; - break; - - // We should never see these here: - case ResultWas::Info: - case ResultWas::Warning: - case ResultWas::Ok: - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - elementName = "internalError"; - break; - } - - XmlWriter::ScopedElement e = xml.scopedElement( elementName ); - - xml.writeAttribute( "message", result.getExpandedExpression() ); - xml.writeAttribute( "type", result.getTestMacroName() ); - - std::ostringstream oss; - if( !result.getMessage().empty() ) - oss << result.getMessage() << "\n"; - for( std::vector<MessageInfo>::const_iterator - it = stats.infoMessages.begin(), - itEnd = stats.infoMessages.end(); - it != itEnd; - ++it ) - if( it->type == ResultWas::Info ) - oss << it->message << "\n"; - - oss << "at " << result.getSourceInfo(); - xml.writeText( oss.str(), false ); - } - } - - XmlWriter xml; - Timer suiteTimer; - std::ostringstream stdOutForSuite; - std::ostringstream stdErrForSuite; - unsigned int unexpectedExceptions; - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_console.hpp -#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED - -namespace Catch { - - struct ConsoleReporter : StreamingReporterBase { - ConsoleReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ), - m_headerPrinted( false ), - m_atLeastOneTestCasePrinted( false ) - {} - - virtual ~ConsoleReporter(); - static std::string getDescription() { - return "Reports test results as plain lines of text"; - } - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = false; - return prefs; - } - - virtual void noMatchingTestCases( std::string const& spec ) { - stream << "No test cases matched '" << spec << "'" << std::endl; - } - - virtual void assertionStarting( AssertionInfo const& ) { - } - - virtual bool assertionEnded( AssertionStats const& _assertionStats ) { - AssertionResult const& result = _assertionStats.assertionResult; - - bool printInfoMessages = true; - - // Drop out if result was successful and we're not printing those - if( !m_config->includeSuccessfulResults() && result.isOk() ) { - if( result.getResultType() != ResultWas::Warning ) - return false; - printInfoMessages = false; - } - - lazyPrint(); - - AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); - printer.print(); - stream << std::endl; - return true; - } - - virtual void sectionStarting( SectionInfo const& _sectionInfo ) { - m_headerPrinted = false; - StreamingReporterBase::sectionStarting( _sectionInfo ); - } - virtual void sectionEnded( SectionStats const& _sectionStats ) { - if( _sectionStats.missingAssertions ) { - lazyPrint(); - Colour colour( Colour::ResultError ); - if( m_sectionStack.size() > 1 ) - stream << "\nNo assertions in section"; - else - stream << "\nNo assertions in test case"; - stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; - } - if( m_headerPrinted ) { - if( m_config->showDurations() == ShowDurations::Always ) - stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl; - m_headerPrinted = false; - } - else { - if( m_config->showDurations() == ShowDurations::Always ) - stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl; - } - StreamingReporterBase::sectionEnded( _sectionStats ); - } - - virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) { - StreamingReporterBase::testCaseEnded( _testCaseStats ); - m_headerPrinted = false; - } - virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) { - if( currentGroupInfo.used ) { - printSummaryDivider(); - stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; - printTotals( _testGroupStats.totals ); - stream << "\n" << std::endl; - } - StreamingReporterBase::testGroupEnded( _testGroupStats ); - } - virtual void testRunEnded( TestRunStats const& _testRunStats ) { - if( m_atLeastOneTestCasePrinted ) - printTotalsDivider(); - printTotals( _testRunStats.totals ); - stream << "\n" << std::endl; - StreamingReporterBase::testRunEnded( _testRunStats ); - } - - private: - - class AssertionPrinter { - void operator= ( AssertionPrinter const& ); - public: - AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) - : stream( _stream ), - stats( _stats ), - result( _stats.assertionResult ), - colour( Colour::None ), - message( result.getMessage() ), - messages( _stats.infoMessages ), - printInfoMessages( _printInfoMessages ) - { - switch( result.getResultType() ) { - case ResultWas::Ok: - colour = Colour::Success; - passOrFail = "PASSED"; - //if( result.hasMessage() ) - if( _stats.infoMessages.size() == 1 ) - messageLabel = "with message"; - if( _stats.infoMessages.size() > 1 ) - messageLabel = "with messages"; - break; - case ResultWas::ExpressionFailed: - if( result.isOk() ) { - colour = Colour::Success; - passOrFail = "FAILED - but was ok"; - } - else { - colour = Colour::Error; - passOrFail = "FAILED"; - } - if( _stats.infoMessages.size() == 1 ) - messageLabel = "with message"; - if( _stats.infoMessages.size() > 1 ) - messageLabel = "with messages"; - break; - case ResultWas::ThrewException: - colour = Colour::Error; - passOrFail = "FAILED"; - messageLabel = "due to unexpected exception with message"; - break; - case ResultWas::DidntThrowException: - colour = Colour::Error; - passOrFail = "FAILED"; - messageLabel = "because no exception was thrown where one was expected"; - break; - case ResultWas::Info: - messageLabel = "info"; - break; - case ResultWas::Warning: - messageLabel = "warning"; - break; - case ResultWas::ExplicitFailure: - passOrFail = "FAILED"; - colour = Colour::Error; - if( _stats.infoMessages.size() == 1 ) - messageLabel = "explicitly with message"; - if( _stats.infoMessages.size() > 1 ) - messageLabel = "explicitly with messages"; - break; - // These cases are here to prevent compiler warnings - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - passOrFail = "** internal error **"; - colour = Colour::Error; - break; - } - } - - void print() const { - printSourceInfo(); - if( stats.totals.assertions.total() > 0 ) { - if( result.isOk() ) - stream << "\n"; - printResultType(); - printOriginalExpression(); - printReconstructedExpression(); - } - else { - stream << "\n"; - } - printMessage(); - } - - private: - void printResultType() const { - if( !passOrFail.empty() ) { - Colour colourGuard( colour ); - stream << passOrFail << ":\n"; - } - } - void printOriginalExpression() const { - if( result.hasExpression() ) { - Colour colourGuard( Colour::OriginalExpression ); - stream << " "; - stream << result.getExpressionInMacro(); - stream << "\n"; - } - } - void printReconstructedExpression() const { - if( result.hasExpandedExpression() ) { - stream << "with expansion:\n"; - Colour colourGuard( Colour::ReconstructedExpression ); - stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n"; - } - } - void printMessage() const { - if( !messageLabel.empty() ) - stream << messageLabel << ":" << "\n"; - for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end(); - it != itEnd; - ++it ) { - // If this assertion is a warning ignore any INFO messages - if( printInfoMessages || it->type != ResultWas::Info ) - stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n"; - } - } - void printSourceInfo() const { - Colour colourGuard( Colour::FileName ); - stream << result.getSourceInfo() << ": "; - } - - std::ostream& stream; - AssertionStats const& stats; - AssertionResult const& result; - Colour::Code colour; - std::string passOrFail; - std::string messageLabel; - std::string message; - std::vector<MessageInfo> messages; - bool printInfoMessages; - }; - - void lazyPrint() { - - if( !currentTestRunInfo.used ) - lazyPrintRunInfo(); - if( !currentGroupInfo.used ) - lazyPrintGroupInfo(); - - if( !m_headerPrinted ) { - printTestCaseAndSectionHeader(); - m_headerPrinted = true; - } - m_atLeastOneTestCasePrinted = true; - } - void lazyPrintRunInfo() { - stream << "\n" << getTildes() << "\n"; - Colour colour( Colour::SecondaryText ); - stream << currentTestRunInfo->name - << " is a Catch v" << libraryVersion.majorVersion << "." - << libraryVersion.minorVersion << " b" - << libraryVersion.buildNumber; - if( libraryVersion.branchName != "master" ) - stream << " (" << libraryVersion.branchName << ")"; - stream << " host application.\n" - << "Run with -? for options\n\n"; - - currentTestRunInfo.used = true; - } - void lazyPrintGroupInfo() { - if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { - printClosedHeader( "Group: " + currentGroupInfo->name ); - currentGroupInfo.used = true; - } - } - void printTestCaseAndSectionHeader() { - assert( !m_sectionStack.empty() ); - printOpenHeader( currentTestCaseInfo->name ); - - if( m_sectionStack.size() > 1 ) { - Colour colourGuard( Colour::Headers ); - - std::vector<SectionInfo>::const_iterator - it = m_sectionStack.begin()+1, // Skip first section (test case) - itEnd = m_sectionStack.end(); - for( ; it != itEnd; ++it ) - printHeaderString( it->name, 2 ); - } - - SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; - - if( !lineInfo.empty() ){ - stream << getDashes() << "\n"; - Colour colourGuard( Colour::FileName ); - stream << lineInfo << "\n"; - } - stream << getDots() << "\n" << std::endl; - } - - void printClosedHeader( std::string const& _name ) { - printOpenHeader( _name ); - stream << getDots() << "\n"; - } - void printOpenHeader( std::string const& _name ) { - stream << getDashes() << "\n"; - { - Colour colourGuard( Colour::Headers ); - printHeaderString( _name ); - } - } - - // if string has a : in first line will set indent to follow it on - // subsequent lines - void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { - std::size_t i = _string.find( ": " ); - if( i != std::string::npos ) - i+=2; - else - i = 0; - stream << Text( _string, TextAttributes() - .setIndent( indent+i) - .setInitialIndent( indent ) ) << "\n"; - } - - void printTotals( const Totals& totals ) { - if( totals.testCases.total() == 0 ) { - stream << "No tests ran"; - } - else if( totals.assertions.total() == 0 ) { - Colour colour( Colour::Yellow ); - printCounts( "test case", totals.testCases ); - stream << " (no assertions)"; - } - else if( totals.assertions.failed ) { - Colour colour( Colour::ResultError ); - printCounts( "test case", totals.testCases ); - if( totals.testCases.failed > 0 ) { - stream << " ("; - printCounts( "assertion", totals.assertions ); - stream << ")"; - } - } - else { - Colour colour( Colour::ResultSuccess ); - stream << "All tests passed (" - << pluralise( totals.assertions.passed, "assertion" ) << " in " - << pluralise( totals.testCases.passed, "test case" ) << ")"; - } - } - void printCounts( std::string const& label, Counts const& counts ) { - if( counts.total() == 1 ) { - stream << "1 " << label << " - "; - if( counts.failed ) - stream << "failed"; - else - stream << "passed"; - } - else { - stream << counts.total() << " " << label << "s "; - if( counts.passed ) { - if( counts.failed ) - stream << "- " << counts.failed << " failed"; - else if( counts.passed == 2 ) - stream << "- both passed"; - else - stream << "- all passed"; - } - else { - if( counts.failed == 2 ) - stream << "- both failed"; - else - stream << "- all failed"; - } - } - } - - void printTotalsDivider() { - stream << getDoubleDashes() << "\n"; - } - void printSummaryDivider() { - stream << getDashes() << "\n"; - } - static std::string const& getDashes() { - static const std::string dashes( CATCH_CONFIG_CONSOLE_WIDTH-1, '-' ); - return dashes; - } - static std::string const& getDots() { - static const std::string dots( CATCH_CONFIG_CONSOLE_WIDTH-1, '.' ); - return dots; - } - static std::string const& getDoubleDashes() { - static const std::string doubleDashes( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); - return doubleDashes; - } - static std::string const& getTildes() { - static const std::string dots( CATCH_CONFIG_CONSOLE_WIDTH-1, '~' ); - return dots; - } - - private: - bool m_headerPrinted; - bool m_atLeastOneTestCasePrinted; - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) - -} // end namespace Catch - -namespace Catch { - NonCopyable::~NonCopyable() {} - IShared::~IShared() {} - StreamBufBase::~StreamBufBase() throw() {} - IContext::~IContext() {} - IResultCapture::~IResultCapture() {} - ITestCase::~ITestCase() {} - ITestCaseRegistry::~ITestCaseRegistry() {} - IRegistryHub::~IRegistryHub() {} - IMutableRegistryHub::~IMutableRegistryHub() {} - IExceptionTranslator::~IExceptionTranslator() {} - IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} - IReporter::~IReporter() {} - IReporterFactory::~IReporterFactory() {} - IReporterRegistry::~IReporterRegistry() {} - IStreamingReporter::~IStreamingReporter() {} - AssertionStats::~AssertionStats() {} - SectionStats::~SectionStats() {} - TestCaseStats::~TestCaseStats() {} - TestGroupStats::~TestGroupStats() {} - TestRunStats::~TestRunStats() {} - CumulativeReporterBase::SectionNode::~SectionNode() {} - CumulativeReporterBase::~CumulativeReporterBase() {} - - StreamingReporterBase::~StreamingReporterBase() {} - ConsoleReporter::~ConsoleReporter() {} - IRunner::~IRunner() {} - IMutableContext::~IMutableContext() {} - IConfig::~IConfig() {} - XmlReporter::~XmlReporter() {} - JunitReporter::~JunitReporter() {} - TestRegistry::~TestRegistry() {} - FreeFunctionTestCase::~FreeFunctionTestCase() {} - IGeneratorInfo::~IGeneratorInfo() {} - IGeneratorsForTest::~IGeneratorsForTest() {} - - Matchers::Impl::StdString::Equals::~Equals() {} - Matchers::Impl::StdString::Contains::~Contains() {} - Matchers::Impl::StdString::StartsWith::~StartsWith() {} - Matchers::Impl::StdString::EndsWith::~EndsWith() {} - - void Config::dummy() {} - - INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "xml", XmlReporter ) -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#endif // CATCH_CONFIG_MAIN || CATCH_CONFIG_RUNNER - -#ifdef CATCH_CONFIG_MAIN -// #included from: internal/catch_default_main.hpp -#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED - -#ifndef __OBJC__ - -// Standard C/C++ main entry point -int main (int argc, char * const argv[]) { - return Catch::Session().run( argc, argv ); -} - -#else // __OBJC__ - -// Objective-C entry point -int main (int argc, char * const argv[]) { -#if !CATCH_ARC_ENABLED - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; -#endif - - Catch::registerTestMethods(); - int result = Catch::Session().run( argc, (char* const*)argv ); - -#if !CATCH_ARC_ENABLED - [pool drain]; -#endif - - return result; -} - -#endif // __OBJC__ - -#endif // CATCH_CONFIG_MAIN - -////// - -// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ -#ifdef CATCH_CONFIG_PREFIX_ALL - -#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) -#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::NegateResult, "CATCH_REQUIRE_FALSE" ) - -#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" ) -#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) -#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) - -#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) -#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "CATCH_CHECK_FALSE" ) -#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" ) -#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" ) -#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" ) - -#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) -#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) -#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) - -#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) -#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" ) - -#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) -#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) -#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) -#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) -#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) - -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) - #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) - #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) - #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) - #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) - #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) -#else - #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) - #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) - #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) - #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) - #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) - #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) -#endif -#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) - -#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) -#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) - -#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) - -// "BDD-style" convenience wrappers -#ifdef CATCH_CONFIG_VARIADIC_MACROS -#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) -#else -#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) -#endif -#define CATCH_GIVEN( desc ) CATCH_SECTION( "Given: " desc, "" ) -#define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" ) -#define CATCH_AND_WHEN( desc ) CATCH_SECTION( " And: " desc, "" ) -#define CATCH_THEN( desc ) CATCH_SECTION( " Then: " desc, "" ) -#define CATCH_AND_THEN( desc ) CATCH_SECTION( " And: " desc, "" ) - -// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required -#else - -#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) -#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::NegateResult, "REQUIRE_FALSE" ) - -#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "REQUIRE_THROWS" ) -#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) -#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) - -#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) -#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "CHECK_FALSE" ) -#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" ) -#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) -#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) - -#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" ) -#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) -#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) - -#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) -#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" ) - -#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) -#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) -#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) -#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) -#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) - -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) - #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) - #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) - #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) - #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) - #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) -#else - #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) - #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) - #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) - #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) - #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) - #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) -#endif -#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) - -#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) -#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) - -#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) - -#endif - -#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) - -// "BDD-style" convenience wrappers -#ifdef CATCH_CONFIG_VARIADIC_MACROS -#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) -#else -#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) -#endif -#define GIVEN( desc ) SECTION( " Given: " desc, "" ) -#define WHEN( desc ) SECTION( " When: " desc, "" ) -#define AND_WHEN( desc ) SECTION( "And when: " desc, "" ) -#define THEN( desc ) SECTION( " Then: " desc, "" ) -#define AND_THEN( desc ) SECTION( " And: " desc, "" ) - -using Catch::Detail::Approx; - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED - diff --git a/lib/entityx/entityx/3rdparty/simplesignal.h b/lib/entityx/entityx/3rdparty/simplesignal.h deleted file mode 100644 index 3c60273..0000000 --- a/lib/entityx/entityx/3rdparty/simplesignal.h +++ /dev/null @@ -1,580 +0,0 @@ -// CC0 Public Domain: http://creativecommons.org/publicdomain/zero/1.0/ -#ifndef SIMPLE_SIGNAL_H__ -#define SIMPLE_SIGNAL_H__ - -#include <assert.h> -#include <stdint.h> -#include <vector> -#include <functional> - -namespace Simple { - -namespace Lib { - -/// ProtoSignal is the template implementation for callback list. -template <typename, typename> -class ProtoSignal; // undefined - -/// CollectorInvocation invokes signal handlers differently depending on return -/// type. -template <typename, typename> -struct CollectorInvocation; - -/// CollectorLast returns the result of the last signal handler from a signal -/// emission. -template <typename Result> -struct CollectorLast { - typedef Result CollectorResult; - explicit CollectorLast() : last_() {} - inline bool operator()(Result r) { - last_ = r; - return true; - } - CollectorResult result() { return last_; } - - private: - Result last_; -}; - -/// CollectorDefault implements the default signal handler collection behaviour. -template <typename Result> -struct CollectorDefault : CollectorLast<Result> {}; - -/// CollectorDefault specialisation for signals with void return type. -template <> -struct CollectorDefault<void> { - typedef void CollectorResult; - void result() {} - inline bool operator()(void) { return true; } -}; - -/// CollectorInvocation specialisation for regular signals. -template <class Collector, class R, class... Args> -struct CollectorInvocation<Collector, R(Args...)> { - inline bool invoke(Collector &collector, const std::function<R(Args...)> &cbf, - Args... args) { - return collector(cbf(args...)); - } -}; - -/// CollectorInvocation specialisation for signals with void return type. -template <class Collector, class... Args> -struct CollectorInvocation<Collector, void(Args...)> { - inline bool invoke(Collector &collector, - const std::function<void(Args...)> &cbf, Args... args) { - cbf(args...); - return collector(); - } -}; - -/// ProtoSignal template specialised for the callback signature and collector. -template <class Collector, class R, class... Args> -class ProtoSignal<R(Args...), Collector> : private CollectorInvocation< - Collector, R(Args...)> { - protected: - typedef std::function<R(Args...)> CbFunction; - typedef typename CbFunction::result_type Result; - typedef typename Collector::CollectorResult CollectorResult; - - private: - /// SignalLink implements a doubly-linked ring with ref-counted nodes - /// containing the signal handlers. - struct SignalLink { - SignalLink *next, *prev; - CbFunction function; - int ref_count; - explicit SignalLink(const CbFunction &cbf) - : next(0), prev(0), function(cbf), ref_count(1) {} - /*dtor*/ ~SignalLink() { assert(ref_count == 0); } - void incref() { - ref_count += 1; - assert(ref_count > 0); - } - void decref() { - ref_count -= 1; - if (!ref_count) - delete this; - else - assert(ref_count > 0); - } - void unlink() { - function = nullptr; - if (next) next->prev = prev; - if (prev) prev->next = next; - decref(); - // leave intact ->next, ->prev for stale iterators - } - size_t add_before(const CbFunction &cb) { - SignalLink *link = new SignalLink(cb); - link->prev = prev; // link to last - link->next = this; - prev->next = link; // link from last - prev = link; - static_assert(sizeof(link) == sizeof(size_t), "sizeof size_t"); - return size_t(link); - } - bool deactivate(const CbFunction &cbf) { - if (cbf == function) { - function = 0; // deactivate static head - return true; - } - for (SignalLink *link = this->next ? this->next : this; link != this; - link = link->next) - if (cbf == link->function) { - link->unlink(); // deactivate and unlink sibling - return true; - } - return false; - } - bool remove_sibling(size_t id) { - for (SignalLink *link = this->next ? this->next : this; link != this; - link = link->next) - if (id == size_t(link)) { - link->unlink(); // deactivate and unlink sibling - return true; - } - return false; - } - }; - SignalLink *callback_ring_; // linked ring of callback nodes - /*copy-ctor*/ ProtoSignal(const ProtoSignal &) = delete; - ProtoSignal &operator=(const ProtoSignal &) = delete; - void ensure_ring() { - if (!callback_ring_) { - callback_ring_ = new SignalLink(CbFunction()); // ref_count = 1 - callback_ring_->incref(); // ref_count = 2, head of ring, can be - // deactivated but not removed - callback_ring_->next = callback_ring_; // ring head initialization - callback_ring_->prev = callback_ring_; // ring tail initialization - } - } - - public: - /// ProtoSignal constructor, connects default callback if non-0. - ProtoSignal(const CbFunction &method) : callback_ring_(0) { - if (method != 0) { - ensure_ring(); - callback_ring_->function = method; - } - } - /// ProtoSignal destructor releases all resources associated with this signal. - ~ProtoSignal() { - if (callback_ring_) { - while (callback_ring_->next != callback_ring_) - callback_ring_->next->unlink(); - assert(callback_ring_->ref_count >= 2); - callback_ring_->decref(); - callback_ring_->decref(); - } - } - /// Operator to add a new function or lambda as signal handler, returns a - /// handler connection ID. - size_t connect(const CbFunction &cb) { - ensure_ring(); - return callback_ring_->add_before(cb); - } - /// Operator to remove a signal handler through it connection ID, returns if a - /// handler was removed. - bool disconnect(size_t connection) { - return callback_ring_ ? callback_ring_->remove_sibling(connection) : false; - } - /// Emit a signal, i.e. invoke all its callbacks and collect return types with - /// the Collector. - CollectorResult emit(Args... args) { - Collector collector; - if (!callback_ring_) return collector.result(); - SignalLink *link = callback_ring_; - link->incref(); - do { - if (link->function != 0) { - const bool continue_emission = - this->invoke(collector, link->function, args...); - if (!continue_emission) break; - } - SignalLink *old = link; - link = old->next; - link->incref(); - old->decref(); - } while (link != callback_ring_); - link->decref(); - return collector.result(); - } - // Number of connected slots. - std::size_t size() { - std::size_t size = 0; - SignalLink *link = callback_ring_; - link->incref(); - do { - if (link->function != 0) { - size++; - } - SignalLink *old = link; - link = old->next; - link->incref(); - old->decref(); - } while (link != callback_ring_); - return size; - } -}; - -} // Lib - // namespace Simple - -/** - * Signal is a template type providing an interface for arbitrary callback - * lists. - * A signal type needs to be declared with the function signature of its - * callbacks, - * and optionally a return result collector class type. - * Signal callbacks can be added with operator+= to a signal and removed with - * operator-=, using - * a callback connection ID return by operator+= as argument. - * The callbacks of a signal are invoked with the emit() method and arguments - * according to the signature. - * The result returned by emit() depends on the signal collector class. By - * default, the result of - * the last callback is returned from emit(). Collectors can be implemented to - * accumulate callback - * results or to halt a running emissions in correspondance to callback results. - * The signal implementation is safe against recursion, so callbacks may be - * removed and - * added during a signal emission and recursive emit() calls are also safe. - * The overhead of an unused signal is intentionally kept very low, around the - * size of a single pointer. - * Note that the Signal template types is non-copyable. - */ -template <typename SignalSignature, - class Collector = Lib::CollectorDefault< - typename std::function<SignalSignature>::result_type>> -struct Signal /*final*/ : Lib::ProtoSignal<SignalSignature, Collector> { - typedef Lib::ProtoSignal<SignalSignature, Collector> ProtoSignal; - typedef typename ProtoSignal::CbFunction CbFunction; - /// Signal constructor, supports a default callback as argument. - Signal(const CbFunction &method = CbFunction()) : ProtoSignal(method) {} -}; - -/// This function creates a std::function by binding @a object to the member -/// function pointer @a method. -template <class Instance, class Class, class R, class... Args> -std::function<R(Args...)> slot(Instance &object, R (Class::*method)(Args...)) { - return [&object, method](Args... args) { return (object.*method)(args...); }; -} - -/// This function creates a std::function by binding @a object to the member -/// function pointer @a method. -template <class Class, class R, class... Args> -std::function<R(Args...)> slot(Class *object, R (Class::*method)(Args...)) { - return [object, method](Args... args) { return (object->*method)(args...); }; -} - -/// Keep signal emissions going while all handlers return !0 (true). -template <typename Result> -struct CollectorUntil0 { - typedef Result CollectorResult; - explicit CollectorUntil0() : result_() {} - const CollectorResult &result() { return result_; } - inline bool operator()(Result r) { - result_ = r; - return result_ ? true : false; - } - - private: - CollectorResult result_; -}; - -/// Keep signal emissions going while all handlers return 0 (false). -template <typename Result> -struct CollectorWhile0 { - typedef Result CollectorResult; - explicit CollectorWhile0() : result_() {} - const CollectorResult &result() { return result_; } - inline bool operator()(Result r) { - result_ = r; - return result_ ? false : true; - } - - private: - CollectorResult result_; -}; - -/// CollectorVector returns the result of the all signal handlers from a signal -/// emission in a std::vector. -template <typename Result> -struct CollectorVector { - typedef std::vector<Result> CollectorResult; - const CollectorResult &result() { return result_; } - inline bool operator()(Result r) { - result_.push_back(r); - return true; - } - - private: - CollectorResult result_; -}; - -} // Simple - -#endif // SIMPLE_SIGNAL_H__ - -#ifdef ENABLE_SIMPLE_SIGNAL_TESTS - -#include <string> -#include <stdarg.h> -#include <time.h> -#include <sys/time.h> - -#ifdef __MACH__ -#include <mach/clock.h> -#include <mach/mach.h> -#endif - -static std::string string_printf(const char *format, ...) - __attribute__((__format__(__printf__, 1, 2))); -static std::string string_printf(const char *format, ...) { - std::string result; - char *str = 0; - va_list args; - va_start(args, format); - if (vasprintf(&str, format, args) >= 0) result = str; - va_end(args); - if (str) free(str); - return result; -} - -static uint64_t timestamp_benchmark() { - struct timespec tp = {0, 0}; - -#ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time - clock_serv_t cclock; - mach_timespec_t mts; - host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); - clock_get_time(cclock, &mts); - mach_port_deallocate(mach_task_self(), cclock); - tp.tv_sec = mts.tv_sec; - tp.tv_nsec = mts.tv_nsec; -#else - clock_gettime(CLOCK_REALTIME, &tp); -#endif - uint64_t stamp = tp.tv_sec * 1000000000ULL + tp.tv_nsec; - return stamp; -} - -struct TestCounter { - static uint64_t get(); - static void set(uint64_t); - static void add2(void *, uint64_t); -}; - -namespace { // Anon -void (*test_counter_add2)(void *, uint64_t) = - TestCounter::add2; // external symbol to prevent easy inlining -static uint64_t test_counter_var = 0; -} // Anon - -class BasicSignalTests { - static std::string accu; - struct Foo { - char foo_bool(float f, int i, std::string s) { - accu += string_printf("Foo: %.2f\n", f + i + s.size()); - return true; - } - }; - static char float_callback(float f, int, std::string) { - accu += string_printf("float: %.2f\n", f); - return 0; - } - - public: - static void run() { - accu = ""; - Simple::Signal<char(float, int, std::string)> sig1; - size_t id1 = sig1.connect(float_callback); - size_t id2 = sig1.connect([](float, int i, std::string) { - accu += string_printf("int: %d\n", i); - return 0; - }); - size_t id3 = sig1.connect([](float, int, const std::string &s) { - accu += string_printf("string: %s\n", s.c_str()); - return 0; - }); - sig1.emit(.3, 4, "huhu"); - bool success; - success = sig1.disconnect(id1); - assert(success == true); - success = sig1.disconnect(id1); - assert(success == false); - success = sig1.disconnect(id2); - assert(success == true); - success = sig1.disconnect(id3); - assert(success == true); - success = sig1.disconnect(id3); - assert(success == false); - success = sig1.disconnect(id2); - assert(success == false); - Foo foo; - sig1.connect(Simple::slot(foo, &Foo::foo_bool)); - sig1.connect(Simple::slot(&foo, &Foo::foo_bool)); - sig1.emit(.5, 1, "12"); - - Simple::Signal<void(std::string, int)> sig2; - sig2.connect([](std::string msg, - int) { accu += string_printf("msg: %s", msg.c_str()); }); - sig2.connect([](std::string, - int d) { accu += string_printf(" *%d*\n", d); }); - sig2.emit("in sig2", 17); - - accu += "DONE"; - - const char *expected = - "float: 0.30\n" - "int: 4\n" - "string: huhu\n" - "Foo: 3.50\n" - "Foo: 3.50\n" - "msg: in sig2 *17*\n" - "DONE"; - assert(accu == expected); - } -}; -std::string BasicSignalTests::accu; - -class TestCollectorVector { - static int handler1() { return 1; } - static int handler42() { return 42; } - static int handler777() { return 777; } - - public: - static void run() { - Simple::Signal<int(), Simple::CollectorVector<int>> sig_vector; - sig_vector.connect(handler777); - sig_vector.connect(handler42); - sig_vector.connect(handler1); - sig_vector.connect(handler42); - sig_vector.connect(handler777); - std::vector<int> results = sig_vector.emit(); - const std::vector<int> reference = {777, 42, 1, 42, 777, }; - assert(results == reference); - } -}; - -class TestCollectorUntil0 { - bool check1, check2; - TestCollectorUntil0() : check1(0), check2(0) {} - bool handler_true() { - check1 = true; - return true; - } - bool handler_false() { - check2 = true; - return false; - } - bool handler_abort() { abort(); } - - public: - static void run() { - TestCollectorUntil0 self; - Simple::Signal<bool(), Simple::CollectorUntil0<bool>> sig_until0; - sig_until0.connect(Simple::slot(self, &TestCollectorUntil0::handler_true)); - sig_until0.connect(Simple::slot(self, &TestCollectorUntil0::handler_false)); - sig_until0.connect(Simple::slot(self, &TestCollectorUntil0::handler_abort)); - assert(!self.check1 && !self.check2); - const bool result = sig_until0.emit(); - assert(!result && self.check1 && self.check2); - } -}; - -class TestCollectorWhile0 { - bool check1, check2; - TestCollectorWhile0() : check1(0), check2(0) {} - bool handler_0() { - check1 = true; - return false; - } - bool handler_1() { - check2 = true; - return true; - } - bool handler_abort() { abort(); } - - public: - static void run() { - TestCollectorWhile0 self; - Simple::Signal<bool(), Simple::CollectorWhile0<bool>> sig_while0; - sig_while0.connect(Simple::slot(self, &TestCollectorWhile0::handler_0)); - sig_while0.connect(Simple::slot(self, &TestCollectorWhile0::handler_1)); - sig_while0.connect(Simple::slot(self, &TestCollectorWhile0::handler_abort)); - assert(!self.check1 && !self.check2); - const bool result = sig_while0.emit(); - assert(result == true && self.check1 && self.check2); - } -}; - -static void bench_simple_signal() { - Simple::Signal<void(void *, uint64_t)> sig_increment; - sig_increment.connect(test_counter_add2); - const uint64_t start_counter = TestCounter::get(); - const uint64_t benchstart = timestamp_benchmark(); - uint64_t i; - for (i = 0; i < 999999; i++) { - sig_increment.emit(0, 1); - } - const uint64_t benchdone = timestamp_benchmark(); - const uint64_t end_counter = TestCounter::get(); - assert(end_counter - start_counter == i); - printf("OK\n Benchmark: Simple::Signal: %fns per emission (size=%zu): ", - size_t(benchdone - benchstart) * 1.0 / size_t(i), - sizeof(sig_increment)); -} - -static void bench_callback_loop() { - void (*counter_increment)(void *, uint64_t) = test_counter_add2; - const uint64_t start_counter = TestCounter::get(); - const uint64_t benchstart = timestamp_benchmark(); - uint64_t i; - for (i = 0; i < 999999; i++) { - counter_increment(0, 1); - } - const uint64_t benchdone = timestamp_benchmark(); - const uint64_t end_counter = TestCounter::get(); - assert(end_counter - start_counter == i); - printf("OK\n Benchmark: callback loop: %fns per round: ", - size_t(benchdone - benchstart) * 1.0 / size_t(i)); -} - -uint64_t TestCounter::get() { return test_counter_var; } - -void TestCounter::set(uint64_t v) { test_counter_var = v; } - -void TestCounter::add2(void *, uint64_t v) { test_counter_var += v; } - -int main(int argc, char *argv[]) { - printf("Signal/Basic Tests: "); - BasicSignalTests::run(); - printf("OK\n"); - - printf("Signal/CollectorVector: "); - TestCollectorVector::run(); - printf("OK\n"); - - printf("Signal/CollectorUntil0: "); - TestCollectorUntil0::run(); - printf("OK\n"); - - printf("Signal/CollectorWhile0: "); - TestCollectorWhile0::run(); - printf("OK\n"); - - printf("Signal/Benchmark: Simple::Signal: "); - bench_simple_signal(); - printf("OK\n"); - - printf("Signal/Benchmark: callback loop: "); - bench_callback_loop(); - printf("OK\n"); - - return 0; -} - -#endif // DISABLE_TESTS - -// g++ -Wall -O2 -std=gnu++0x -pthread simplesignal.cc -lrt && ./a.out diff --git a/lib/entityx/entityx/Benchmarks_test.cc b/lib/entityx/entityx/Benchmarks_test.cc deleted file mode 100644 index 2c30e17..0000000 --- a/lib/entityx/entityx/Benchmarks_test.cc +++ /dev/null @@ -1,154 +0,0 @@ -#define CATCH_CONFIG_MAIN - -#include <iostream> -#include <vector> -#include "entityx/3rdparty/catch.hpp" -#include "entityx/help/Timer.h" -#include "entityx/Entity.h" - -using std::uint64_t; -using std::cout; -using std::endl; -using std::vector; - -using entityx::Receiver; -using entityx::Component; -using entityx::ComponentHandle; -using entityx::Entity; -using entityx::EntityCreatedEvent; -using entityx::EntityDestroyedEvent; -using entityx::EventManager; -using entityx::EntityManager; - -struct AutoTimer { - ~AutoTimer() { - cout << timer_.elapsed() << " seconds elapsed" << endl; - } - -private: - entityx::help::Timer timer_; -}; - -struct Listener : public Receiver<Listener> { - void receive(const EntityCreatedEvent &event) { ++created; } - void receive(const EntityDestroyedEvent &event) { ++destroyed; } - - int created = 0; - int destroyed = 0; -}; - -struct Position : public Component<Position> { -}; - - -struct Direction : public Component<Direction> { -}; - - -struct BenchmarkFixture { - BenchmarkFixture() : em(ev) {} - - EventManager ev; - EntityManager em; -}; - - -TEST_CASE_METHOD(BenchmarkFixture, "TestCreateEntities") { - AutoTimer t; - - uint64_t count = 10000000L; - cout << "creating " << count << " entities" << endl; - - for (uint64_t i = 0; i < count; i++) { - em.create(); - } -} - - -TEST_CASE_METHOD(BenchmarkFixture, "TestDestroyEntities") { - uint64_t count = 10000000L; - vector<Entity> entities; - for (uint64_t i = 0; i < count; i++) { - entities.push_back(em.create()); - } - - AutoTimer t; - cout << "destroying " << count << " entities" << endl; - - for (auto e : entities) { - e.destroy(); - } -} - -TEST_CASE_METHOD(BenchmarkFixture, "TestCreateEntitiesWithListener") { - Listener listen; - ev.subscribe<EntityCreatedEvent>(listen); - - int count = 10000000L; - - AutoTimer t; - cout << "creating " << count << " entities while notifying a single EntityCreatedEvent listener" << endl; - - vector<Entity> entities; - for (int i = 0; i < count; i++) { - entities.push_back(em.create()); - } - - REQUIRE(entities.size() == count); - REQUIRE(listen.created == count); -} - -TEST_CASE_METHOD(BenchmarkFixture, "TestDestroyEntitiesWithListener") { - int count = 10000000; - vector<Entity> entities; - for (int i = 0; i < count; i++) { - entities.push_back(em.create()); - } - - Listener listen; - ev.subscribe<EntityDestroyedEvent>(listen); - - AutoTimer t; - cout << "destroying " << count << " entities while notifying a single EntityDestroyedEvent listener" << endl; - - for (auto &e : entities) { - e.destroy(); - } - - REQUIRE(entities.size() == count); - REQUIRE(listen.destroyed == count); -} - -TEST_CASE_METHOD(BenchmarkFixture, "TestEntityIteration") { - int count = 10000000; - for (int i = 0; i < count; i++) { - auto e = em.create(); - e.assign<Position>(); - } - - AutoTimer t; - cout << "iterating over " << count << " entities, unpacking one component" << endl; - - ComponentHandle<Position> position; - for (auto e : em.entities_with_components(position)) { - (void)e; - } -} - -TEST_CASE_METHOD(BenchmarkFixture, "TestEntityIterationUnpackTwo") { - int count = 10000000; - for (int i = 0; i < count; i++) { - auto e = em.create(); - e.assign<Position>(); - e.assign<Direction>(); - } - - AutoTimer t; - cout << "iterating over " << count << " entities, unpacking two components" << endl; - - ComponentHandle<Position> position; - ComponentHandle<Direction> direction; - for (auto e : em.entities_with_components(position, direction)) { - (void)e; - } -} diff --git a/lib/entityx/entityx/Entity.cc b/lib/entityx/entityx/Entity.cc deleted file mode 100644 index ddb8df7..0000000 --- a/lib/entityx/entityx/Entity.cc +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2012 Alec Thomas <alec@swapoff.org> - * All rights reserved. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. - * - * Author: Alec Thomas <alec@swapoff.org> - */ - -#include <algorithm> -#include "entityx/Entity.h" - -namespace entityx { - -const Entity::Id Entity::INVALID; -BaseComponent::Family BaseComponent::family_counter_ = 0; - -void Entity::invalidate() { - id_ = INVALID; - manager_ = nullptr; -} - -void Entity::destroy() { - assert(valid()); - manager_->destroy(id_); - invalidate(); -} - -std::bitset<entityx::MAX_COMPONENTS> Entity::component_mask() const { - return manager_->component_mask(id_); -} - -EntityManager::EntityManager(EventManager &event_manager) : event_manager_(event_manager) { -} - -EntityManager::~EntityManager() { - reset(); -} - -void EntityManager::reset() { - for (Entity entity : entities_for_debugging()) entity.destroy(); - for (BasePool *pool : component_pools_) { - if (pool) delete pool; - } - for (BaseComponentHelper *helper : component_helpers_) { - if (helper) delete helper; - } - component_pools_.clear(); - component_helpers_.clear(); - entity_component_mask_.clear(); - entity_version_.clear(); - free_list_.clear(); - index_counter_ = 0; -} - -EntityCreatedEvent::~EntityCreatedEvent() {} -EntityDestroyedEvent::~EntityDestroyedEvent() {} - - -} // namespace entityx diff --git a/lib/entityx/entityx/Entity.h b/lib/entityx/entityx/Entity.h deleted file mode 100644 index 27a8820..0000000 --- a/lib/entityx/entityx/Entity.h +++ /dev/null @@ -1,1130 +0,0 @@ -/* - * Copyright (C) 2012 Alec Thomas <alec@swapoff.org> - * All rights reserved. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. - * - * Author: Alec Thomas <alec@swapoff.org> - */ - -#pragma once - - -#include <cstdint> -#include <tuple> -#include <new> -#include <cstdlib> -#include <algorithm> -#include <bitset> -#include <cassert> -#include <iostream> -#include <iterator> -#include <list> -#include <memory> -#include <set> -#include <string> -#include <utility> -#include <vector> -#include <type_traits> - #include <functional> - -#include "entityx/help/Pool.h" -#include "entityx/config.h" -#include "entityx/Event.h" -#include "entityx/help/NonCopyable.h" - -namespace entityx { - -typedef std::uint32_t uint32_t; -typedef std::uint64_t uint64_t; - -class EntityManager; - - -template <typename C, typename EM = EntityManager> -class ComponentHandle; - - - -/** A convenience handle around an Entity::Id. - * - * If an entity is destroyed, any copies will be invalidated. Use valid() to - * check for validity before using. - * - * Create entities with `EntityManager`: - * - * Entity entity = entity_manager->create(); - */ -class Entity { -public: - struct Id { - Id() : id_(0) {} - explicit Id(uint64_t id) : id_(id) {} - Id(uint32_t index, uint32_t version) : id_(uint64_t(index) | uint64_t(version) << 32UL) {} - - uint64_t id() const { return id_; } - - bool operator == (const Id &other) const { return id_ == other.id_; } - bool operator != (const Id &other) const { return id_ != other.id_; } - bool operator < (const Id &other) const { return id_ < other.id_; } - - uint32_t index() const { return id_ & 0xffffffffUL; } - uint32_t version() const { return id_ >> 32; } - - private: - friend class EntityManager; - - uint64_t id_; - }; - - - /** - * Id of an invalid Entity. - */ - static const Id INVALID; - - Entity() = default; - Entity(EntityManager *manager, Entity::Id id) : manager_(manager), id_(id) {} - Entity(const Entity &other) = default; - Entity &operator = (const Entity &other) = default; - - /** - * Check if Entity handle is invalid. - */ - operator bool() const { - return valid(); - } - - bool operator == (const Entity &other) const { - return other.manager_ == manager_ && other.id_ == id_; - } - - bool operator != (const Entity &other) const { - return !(other == *this); - } - - bool operator < (const Entity &other) const { - return other.id_ < id_; - } - - /** - * Is this Entity handle valid? - * - * In older versions of EntityX, there were no guarantees around entity - * validity if a previously allocated entity slot was reassigned. That is no - * longer the case: if a slot is reassigned, old Entity::Id's will be - * invalid. - */ - bool valid() const; - - /** - * Invalidate Entity handle, disassociating it from an EntityManager and invalidating its ID. - * - * Note that this does *not* affect the underlying entity and its - * components. Use destroy() to destroy the associated Entity and components. - */ - void invalidate(); - - Id id() const { return id_; } - - template <typename C, typename ... Args> - ComponentHandle<C> assign(Args && ... args); - - template <typename C> - ComponentHandle<C> assign_from_copy(const C &component); - - template <typename C, typename ... Args> - ComponentHandle<C> replace(Args && ... args); - - template <typename C> - void remove(); - - template <typename C, typename = typename std::enable_if<!std::is_const<C>::value>::type> - ComponentHandle<C> component(); - - template <typename C, typename = typename std::enable_if<std::is_const<C>::value>::type> - const ComponentHandle<C, const EntityManager> component() const; - - template <typename ... Components> - std::tuple<ComponentHandle<Components>...> components(); - - template <typename ... Components> - std::tuple<ComponentHandle<const Components, const EntityManager>...> components() const; - - template <typename C> - bool has_component() const; - - template <typename A, typename ... Args> - void unpack(ComponentHandle<A> &a, ComponentHandle<Args> & ... args); - - /** - * Destroy and invalidate this Entity. - */ - void destroy(); - - std::bitset<entityx::MAX_COMPONENTS> component_mask() const; - - private: - EntityManager *manager_ = nullptr; - Entity::Id id_ = INVALID; -}; - - -/** - * A ComponentHandle<C> is a wrapper around an instance of a component. - * - * It provides safe access to components. The handle will be invalidated under - * the following conditions: - * - * - If a component is removed from its host entity. - * - If its host entity is destroyed. - */ -template <typename C, typename EM> -class ComponentHandle { -public: - typedef C ComponentType; - - ComponentHandle() : manager_(nullptr) {} - - bool valid() const; - operator bool() const; - - C *operator -> (); - const C *operator -> () const; - - C &operator * (); - const C &operator * () const; - - C *get(); - const C *get() const; - - /** - * Remove the component from its entity and destroy it. - */ - void remove(); - - /** - * Returns the Entity associated with the component - */ - Entity entity(); - - bool operator == (const ComponentHandle<C> &other) const { - return manager_ == other.manager_ && id_ == other.id_; - } - - bool operator != (const ComponentHandle<C> &other) const { - return !(*this == other); - } - -private: - friend class EntityManager; - - ComponentHandle(EM *manager, Entity::Id id) : - manager_(manager), id_(id) {} - - EM *manager_; - Entity::Id id_; -}; - - -/** - * Base component class, only used for insertion into collections. - * - * Family is used for registration. - */ -struct BaseComponent { - public: - typedef size_t Family; - - // NOTE: Component memory is *always* managed by the EntityManager. - // Use Entity::destroy() instead. - void operator delete([[maybe_unused]] void *p) { fail(); } - void operator delete[]([[maybe_unused]] void *p) { fail(); } - - virtual void internal_serialize(bool save, void *ar) = 0; - virtual std::string serializeName(void) const = 0; - - protected: - static void fail() { -#if defined(_HAS_EXCEPTIONS) || defined(__EXCEPTIONS) - throw std::bad_alloc(); -#else - std::abort(); -#endif - } - - static Family family_counter_; -}; - - -/** - * Component implementations should inherit from this. - * - * Components MUST provide a no-argument constructor. - * Components SHOULD provide convenience constructors for initializing on assignment to an Entity::Id. - * - * This is a struct to imply that components should be data-only. - * - * Usage: - * - * struct Position : public Component<Position> { - * Position(float x = 0.0f, float y = 0.0f) : x(x), y(y) {} - * - * float x, y; - * }; - * - * family() is used for registration. - */ -template <typename Derived> -struct Component : public BaseComponent { - public: - typedef ComponentHandle<Derived> Handle; - typedef ComponentHandle<const Derived, const EntityManager> ConstHandle; - -private: - friend class EntityManager; - /// Used internally for registration. - static Family family(); -}; - - -/** - * Emitted when an entity is added to the system. - */ -struct EntityCreatedEvent : public Event<EntityCreatedEvent> { - explicit EntityCreatedEvent(Entity entity) : entity(entity) {} - virtual ~EntityCreatedEvent(); - - Entity entity; -}; - - -/** - * Called just prior to an entity being destroyed. - */ -struct EntityDestroyedEvent : public Event<EntityDestroyedEvent> { - explicit EntityDestroyedEvent(Entity entity) : entity(entity) {} - virtual ~EntityDestroyedEvent(); - - Entity entity; -}; - - -/** - * Emitted when any component is added to an entity. - */ -template <typename C> -struct ComponentAddedEvent : public Event<ComponentAddedEvent<C>> { - ComponentAddedEvent(Entity entity, ComponentHandle<C> component) : - entity(entity), component(component) {} - - Entity entity; - ComponentHandle<C> component; -}; - -/** - * Emitted when any component is removed from an entity. - */ -template <typename C> -struct ComponentRemovedEvent : public Event<ComponentRemovedEvent<C>> { - ComponentRemovedEvent(Entity entity, ComponentHandle<C> component) : - entity(entity), component(component) {} - - Entity entity; - ComponentHandle<C> component; -}; - -/** - * Helper class to perform component operations in a typed manner. - */ -class BaseComponentHelper { -public: - virtual ~BaseComponentHelper() {} - virtual void remove_component(Entity e) = 0; - virtual void copy_component_to(Entity source, Entity target) = 0; - virtual BaseComponent *get_component(Entity e) = 0; -}; - -template <typename C> -class ComponentHelper : public BaseComponentHelper { -public: - void remove_component(Entity e) override { - e.remove<C>(); - } - void copy_component_to(Entity source, Entity target) override { - target.assign_from_copy<C>(*(source.component<C>().get())); - } - BaseComponent *get_component(Entity e) override { - return e.component<C>().get(); - } -}; - -/** - * Manages Entity::Id creation and component assignment. - */ -class EntityManager : entityx::help::NonCopyable { - public: - typedef std::bitset<entityx::MAX_COMPONENTS> ComponentMask; - - explicit EntityManager(EventManager &event_manager); - virtual ~EntityManager(); - - /// An iterator over a view of the entities in an EntityManager. - /// If All is true it will iterate over all valid entities and will ignore the entity mask. - template <class Delegate, bool All = false> - class ViewIterator : public std::iterator<std::input_iterator_tag, Entity::Id> { - public: - Delegate &operator ++() { - ++i_; - next(); - return *static_cast<Delegate*>(this); - } - bool operator == (const Delegate& rhs) const { return i_ == rhs.i_; } - bool operator != (const Delegate& rhs) const { return i_ != rhs.i_; } - Entity operator * () { return Entity(manager_, manager_->create_id(i_)); } - const Entity operator * () const { return Entity(manager_, manager_->create_id(i_)); } - - protected: - ViewIterator(EntityManager *manager, uint32_t index) - : manager_(manager), i_(index), capacity_(manager_->capacity()), free_cursor_(~0UL) { - if (All) { - std::sort(manager_->free_list_.begin(), manager_->free_list_.end()); - free_cursor_ = 0; - } - } - ViewIterator(EntityManager *manager, const ComponentMask mask, uint32_t index) - : manager_(manager), mask_(mask), i_(index), capacity_(manager_->capacity()), free_cursor_(~0UL) { - if (All) { - std::sort(manager_->free_list_.begin(), manager_->free_list_.end()); - free_cursor_ = 0; - } - } - - void next() { - while (i_ < capacity_ && !predicate()) { - ++i_; - } - - if (i_ < capacity_) { - Entity entity = manager_->get(manager_->create_id(i_)); - static_cast<Delegate*>(this)->next_entity(entity); - } - } - - inline bool predicate() { - return (All && valid_entity()) || (manager_->entity_component_mask_[i_] & mask_) == mask_; - } - - inline bool valid_entity() { - const std::vector<uint32_t> &free_list = manager_->free_list_; - if (free_cursor_ < free_list.size() && free_list[free_cursor_] == i_) { - ++free_cursor_; - return false; - } - return true; - } - - EntityManager *manager_; - ComponentMask mask_; - uint32_t i_; - size_t capacity_; - size_t free_cursor_; - }; - - template <bool All> - class BaseView { - public: - class Iterator : public ViewIterator<Iterator, All> { - public: - Iterator(EntityManager *manager, - const ComponentMask mask, - uint32_t index) : ViewIterator<Iterator, All>(manager, mask, index) { - ViewIterator<Iterator, All>::next(); - } - - void next_entity([[maybe_unused]]Entity &entity) {} - }; - - Iterator begin() { return Iterator(manager_, mask_, 0); } - Iterator end() { return Iterator(manager_, mask_, uint32_t(manager_->capacity())); } - const Iterator begin() const { return Iterator(manager_, mask_, 0); } - const Iterator end() const { return Iterator(manager_, mask_, manager_->capacity()); } - - private: - friend class EntityManager; - - explicit BaseView(EntityManager *manager) : manager_(manager) { mask_.set(); } - BaseView(EntityManager *manager, ComponentMask mask) : - manager_(manager), mask_(mask) {} - - EntityManager *manager_; - ComponentMask mask_; - }; - - template <bool All, typename ... Components> - class TypedView: public BaseView<All> { - public: - template <typename T> struct identity { typedef T type; }; - - void each(typename identity<std::function<void(Entity entity, Components&...)>>::type f) { - for (auto it : *this) - f(it, *(it.template component<Components>().get())...); - } - - private: - friend class EntityManager; - - explicit TypedView(EntityManager *manager) : BaseView<All>(manager) {} - TypedView(EntityManager *manager, ComponentMask mask) : BaseView<All>(manager, mask) {} - }; - - template <typename ... Components> using View = TypedView<false, Components...>; - typedef BaseView<true> DebugView; - - template <typename ... Components> - class UnpackingView { - public: - struct Unpacker { - explicit Unpacker(ComponentHandle<Components> & ... handles) : - handles(std::tuple<ComponentHandle<Components> & ...>(handles...)) {} - - void unpack(entityx::Entity &entity) const { - unpack_<0, Components...>(entity); - } - - - private: - template <int N, typename C> - void unpack_(entityx::Entity &entity) const { - std::get<N>(handles) = entity.component<C>(); - } - - template <int N, typename C0, typename C1, typename ... Cn> - void unpack_(entityx::Entity &entity) const { - std::get<N>(handles) = entity.component<C0>(); - unpack_<N + 1, C1, Cn...>(entity); - } - - std::tuple<ComponentHandle<Components> & ...> handles; - }; - - - class Iterator : public ViewIterator<Iterator> { - public: - Iterator(EntityManager *manager, - const ComponentMask mask, - uint32_t index, - const Unpacker &unpacker) : ViewIterator<Iterator>(manager, mask, index), unpacker_(unpacker) { - ViewIterator<Iterator>::next(); - } - - void next_entity(Entity &entity) { - unpacker_.unpack(entity); - } - - private: - const Unpacker &unpacker_; - }; - - - Iterator begin() { return Iterator(manager_, mask_, 0, unpacker_); } - Iterator end() { return Iterator(manager_, mask_, static_cast<uint32_t>(manager_->capacity()), unpacker_); } - const Iterator begin() const { return Iterator(manager_, mask_, 0, unpacker_); } - const Iterator end() const { return Iterator(manager_, mask_, static_cast<uint32_t>(manager_->capacity()), unpacker_); } - - - private: - friend class EntityManager; - - UnpackingView(EntityManager *manager, ComponentMask mask, ComponentHandle<Components> & ... handles) : - manager_(manager), mask_(mask), unpacker_(handles...) {} - - EntityManager *manager_; - ComponentMask mask_; - Unpacker unpacker_; - }; - - /** - * Number of managed entities. - */ - size_t size() const { return entity_component_mask_.size() - free_list_.size(); } - - /** - * Current entity capacity. - */ - size_t capacity() const { return entity_component_mask_.size(); } - - /** - * Return true if the given entity ID is still valid. - */ - bool valid(Entity::Id id) const { - return id.index() < entity_version_.size() && entity_version_[id.index()] == id.version(); - } - - /** - * Create a new Entity::Id. - * - * Emits EntityCreatedEvent. - */ - Entity create() { - uint32_t index, version; - if (free_list_.empty()) { - index = index_counter_++; - accomodate_entity(index); - version = entity_version_[index] = 1; - } else { - index = free_list_.back(); - free_list_.pop_back(); - version = entity_version_[index]; - } - Entity entity(this, Entity::Id(index, version)); - event_manager_.emit<EntityCreatedEvent>(entity); - return entity; - } - - /** - * Create a new Entity by copying another. Copy-constructs each component. - * - * Emits EntityCreatedEvent. - */ - Entity create_from_copy(Entity original) { - assert(original.valid()); - auto clone = create(); - auto mask = original.component_mask(); - for (size_t i = 0; i < component_helpers_.size(); i++) { - BaseComponentHelper *helper = component_helpers_[i]; - if (helper && mask.test(i)) - helper->copy_component_to(original, clone); - } - return clone; - } - - - /** - * Destroy an existing Entity::Id and its associated Components. - * - * Emits EntityDestroyedEvent. - */ - void destroy(Entity::Id entity) { - assert_valid(entity); - uint32_t index = entity.index(); - auto mask = entity_component_mask_[index]; - for (size_t i = 0; i < component_helpers_.size(); i++) { - BaseComponentHelper *helper = component_helpers_[i]; - if (helper && mask.test(i)) - helper->remove_component(Entity(this, entity)); - } - event_manager_.emit<EntityDestroyedEvent>(Entity(this, entity)); - entity_component_mask_[index].reset(); - entity_version_[index]++; - free_list_.push_back(index); - } - - Entity get(Entity::Id id) { - assert_valid(id); - return Entity(this, id); - } - - /** - * Create an Entity::Id for a slot. - * - * NOTE: Does *not* check for validity, but the Entity::Id constructor will - * fail if the ID is invalid. - */ - Entity::Id create_id(uint32_t index) const { - return Entity::Id(index, entity_version_[index]); - } - - /** - * Assign a Component to an Entity::Id, passing through Component constructor arguments. - * - * Position &position = em.assign<Position>(e, x, y); - * - * @returns Smart pointer to newly created component. - */ - template <typename C, typename ... Args> - ComponentHandle<C> assign(Entity::Id id, Args && ... args) { - assert_valid(id); - const BaseComponent::Family family = component_family<C>(); - assert(!entity_component_mask_[id.index()].test(family)); - - // Placement new into the component pool. - Pool<C> *pool = accomodate_component<C>(); - ::new(pool->get(id.index())) C(std::forward<Args>(args) ...); - - // Set the bit for this component. - entity_component_mask_[id.index()].set(family); - - // Create and return handle. - ComponentHandle<C> component(this, id); - event_manager_.emit<ComponentAddedEvent<C>>(Entity(this, id), component); - return component; - } - - /** - * Remove a Component from an Entity::Id - * - * Emits a ComponentRemovedEvent<C> event. - */ - template <typename C> - void remove(Entity::Id id) { - assert_valid(id); - const BaseComponent::Family family = component_family<C>(); - const uint32_t index = id.index(); - - // Find the pool for this component family. - BasePool *pool = component_pools_[family]; - ComponentHandle<C> component(this, id); - event_manager_.emit<ComponentRemovedEvent<C>>(Entity(this, id), component); - - // Remove component bit. - entity_component_mask_[id.index()].reset(family); - - // Call destructor. - pool->destroy(index); - } - - /** - * Check if an Entity has a component. - */ - template <typename C> - bool has_component(Entity::Id id) const { - assert_valid(id); - size_t family = component_family<C>(); - // We don't bother checking the component mask, as we return a nullptr anyway. - if (family >= component_pools_.size()) - return false; - BasePool *pool = component_pools_[family]; - if (!pool || !entity_component_mask_[id.index()][family]) - return false; - return true; - } - - /** - * Retrieve a Component assigned to an Entity::Id. - * - * @returns Pointer to an instance of C, or nullptr if the Entity::Id does not have that Component. - */ - template <typename C, typename = typename std::enable_if<!std::is_const<C>::value>::type> - ComponentHandle<C> component(Entity::Id id) { - assert_valid(id); - size_t family = component_family<C>(); - // We don't bother checking the component mask, as we return a nullptr anyway. - if (family >= component_pools_.size()) - return ComponentHandle<C>(); - BasePool *pool = component_pools_[family]; - if (!pool || !entity_component_mask_[id.index()][family]) - return ComponentHandle<C>(); - return ComponentHandle<C>(this, id); - } - - /** - * Retrieve a Component assigned to an Entity::Id. - * - * @returns Component instance, or nullptr if the Entity::Id does not have that Component. - */ - template <typename C, typename = typename std::enable_if<std::is_const<C>::value>::type> - const ComponentHandle<C, const EntityManager> component(Entity::Id id) const { - assert_valid(id); - size_t family = component_family<C>(); - // We don't bother checking the component mask, as we return a nullptr anyway. - if (family >= component_pools_.size()) - return ComponentHandle<C, const EntityManager>(); - BasePool *pool = component_pools_[family]; - if (!pool || !entity_component_mask_[id.index()][family]) - return ComponentHandle<C, const EntityManager>(); - return ComponentHandle<C, const EntityManager>(this, id); - } - - template <typename ... Components> - std::tuple<ComponentHandle<Components>...> components(Entity::Id id) { - return std::make_tuple(component<Components>(id)...); - } - - template <typename ... Components> - std::tuple<ComponentHandle<const Components, const EntityManager>...> components(Entity::Id id) const { - return std::make_tuple(component<const Components>(id)...); - } - - /** - * EDIT by tcsullivan - * Iterates through all components of a given Entity. - */ - template<class Archive> - void entity_serialize(Entity entity, bool save, Archive& ar) - { - auto mask = component_mask(entity.id()); - for (size_t i = 0; i < component_helpers_.size(); i++) { - BaseComponentHelper *helper = component_helpers_[i]; - if (helper && mask.test(i)) { - auto* c = helper->get_component(entity); - ar.setNextName(c->serializeName().c_str()); - ar.startNode(); - c->internal_serialize(save, static_cast<void*>(&ar)); - ar.finishNode(); - } - } - } - - /** - * Find Entities that have all of the specified Components. - * - * @code - * for (Entity entity : entity_manager.entities_with_components<Position, Direction>()) { - * ComponentHandle<Position> position = entity.component<Position>(); - * ComponentHandle<Direction> direction = entity.component<Direction>(); - * - * ... - * } - * @endcode - */ - template <typename ... Components> - View<Components...> entities_with_components() { - auto mask = component_mask<Components ...>(); - return View<Components...>(this, mask); - } - - template <typename T> struct identity { typedef T type; }; - - template <typename ... Components> - void each(typename identity<std::function<void(Entity entity, Components&...)>>::type f) { - return entities_with_components<Components...>().each(f); - } - - /** - * Find Entities that have all of the specified Components and assign them - * to the given parameters. - * - * @code - * ComponentHandle<Position> position; - * ComponentHandle<Direction> direction; - * for (Entity entity : entity_manager.entities_with_components(position, direction)) { - * // Use position and component here. - * } - * @endcode - */ - template <typename ... Components> - UnpackingView<Components...> entities_with_components(ComponentHandle<Components> & ... components) { - auto mask = component_mask<Components...>(); - return UnpackingView<Components...>(this, mask, components...); - } - - /** - * Iterate over all *valid* entities (ie. not in the free list). Not fast, - * so should only be used for debugging. - * - * @code - * for (Entity entity : entity_manager.entities_for_debugging()) {} - * - * @return An iterator view over all valid entities. - */ - DebugView entities_for_debugging() { - return DebugView(this); - } - - template <typename C> - void unpack(Entity::Id id, ComponentHandle<C> &a) { - assert_valid(id); - a = component<C>(id); - } - - /** - * Unpack components directly into pointers. - * - * Components missing from the entity will be set to nullptr. - * - * Useful for fast bulk iterations. - * - * ComponentHandle<Position> p; - * ComponentHandle<Direction> d; - * unpack<Position, Direction>(e, p, d); - */ - template <typename A, typename ... Args> - void unpack(Entity::Id id, ComponentHandle<A> &a, ComponentHandle<Args> & ... args) { - assert_valid(id); - a = component<A>(id); - unpack<Args ...>(id, args ...); - } - - /** - * Destroy all entities and reset the EntityManager. - */ - void reset(); - - // Retrieve the component family for a type. - template <typename C> - static BaseComponent::Family component_family() { - return Component<typename std::remove_const<C>::type>::family(); - } - - private: - friend class Entity; - template <typename C, typename EM> - friend class ComponentHandle; - - - inline void assert_valid(Entity::Id id) const { - assert(id.index() < entity_component_mask_.size() && "Entity::Id ID outside entity vector range"); - assert(entity_version_[id.index()] == id.version() && "Attempt to access Entity via a stale Entity::Id"); - } - - template <typename C> - C *get_component_ptr(Entity::Id id) { - assert(valid(id)); - BasePool *pool = component_pools_[component_family<C>()]; - assert(pool); - return static_cast<C*>(pool->get(id.index())); - } - - template <typename C> - const C *get_component_ptr(Entity::Id id) const { - assert_valid(id); - BasePool *pool = component_pools_[component_family<C>()]; - assert(pool); - return static_cast<const C*>(pool->get(id.index())); - } - - ComponentMask component_mask(Entity::Id id) { - assert_valid(id); - return entity_component_mask_.at(id.index()); - } - - template <typename C> - ComponentMask component_mask() { - ComponentMask mask; - mask.set(component_family<C>()); - return mask; - } - - template <typename C1, typename C2, typename ... Components> - ComponentMask component_mask() { - return component_mask<C1>() | component_mask<C2, Components ...>(); - } - - template <typename C> - ComponentMask component_mask(const ComponentHandle<C> &c) { - return component_mask<C>(); - } - - template <typename C1, typename ... Components> - ComponentMask component_mask(const ComponentHandle<C1> &c1, const ComponentHandle<Components> &... args) { - return component_mask<C1, Components ...>(); - } - - inline void accomodate_entity(uint32_t index) { - if (entity_component_mask_.size() <= index) { - entity_component_mask_.resize(index + 1); - entity_version_.resize(index + 1); - for (BasePool *pool : component_pools_) - if (pool) pool->expand(index + 1); - } - } - - template <typename C> - Pool<C> *accomodate_component() { - BaseComponent::Family family = component_family<C>(); - if (component_pools_.size() <= family) { - component_pools_.resize(family + 1, nullptr); - } - if (!component_pools_[family]) { - Pool<C> *pool = new Pool<C>(); - pool->expand(index_counter_); - component_pools_[family] = pool; - } - if (component_helpers_.size() <= family) { - component_helpers_.resize(family + 1, nullptr); - } - if (!component_helpers_[family]) { - ComponentHelper<C> *helper = new ComponentHelper<C>(); - component_helpers_[family] = helper; - } - return static_cast<Pool<C>*>(component_pools_[family]); - } - - - uint32_t index_counter_ = 0; - - EventManager &event_manager_; - // Each element in component_pools_ corresponds to a Pool for a Component. - // The index into the vector is the Component::family(). - std::vector<BasePool*> component_pools_; - // Each element in component_helpers_ corresponds to a ComponentHelper for a Component type. - // The index into the vector is the Component::family(). - std::vector<BaseComponentHelper*> component_helpers_; - // Bitmask of components associated with each entity. Index into the vector is the Entity::Id. - std::vector<ComponentMask> entity_component_mask_; - // Vector of entity version numbers. Incremented each time an entity is destroyed - std::vector<uint32_t> entity_version_; - // List of available entity slots. - std::vector<uint32_t> free_list_; -}; - - -template <typename C> -BaseComponent::Family Component<C>::family() { - static Family family = family_counter_++; - assert(family < entityx::MAX_COMPONENTS); - return family; -} - - -template <typename C, typename ... Args> -ComponentHandle<C> Entity::assign(Args && ... args) { - assert(valid()); - return manager_->assign<C>(id_, std::forward<Args>(args) ...); -} - -template <typename C> -ComponentHandle<C> Entity::assign_from_copy(const C &component) { - assert(valid()); - return manager_->assign<C>(id_, std::forward<const C &>(component)); -} - -template <typename C, typename ... Args> -ComponentHandle<C> Entity::replace(Args && ... args) { - assert(valid()); - auto handle = component<C>(); - if (handle) { - *(handle.get()) = C(std::forward<Args>(args) ...); - } else { - handle = manager_->assign<C>(id_, std::forward<Args>(args) ...); - } - return handle; -} - -template <typename C> -void Entity::remove() { - assert(valid() && has_component<C>()); - manager_->remove<C>(id_); -} - -template <typename C, typename> -ComponentHandle<C> Entity::component() { - assert(valid()); - return manager_->component<C>(id_); -} - - template <typename C, typename> -const ComponentHandle<C, const EntityManager> Entity::component() const { - assert(valid()); - return const_cast<const EntityManager*>(manager_)->component<const C>(id_); -} - -template <typename ... Components> -std::tuple<ComponentHandle<Components>...> Entity::components() { - assert(valid()); - return manager_->components<Components...>(id_); -} - -template <typename ... Components> -std::tuple<ComponentHandle<const Components, const EntityManager>...> Entity::components() const { - assert(valid()); - return const_cast<const EntityManager*>(manager_)->components<const Components...>(id_); -} - - -template <typename C> -bool Entity::has_component() const { - assert(valid()); - return manager_->has_component<C>(id_); -} - -template <typename A, typename ... Args> -void Entity::unpack(ComponentHandle<A> &a, ComponentHandle<Args> & ... args) { - assert(valid()); - manager_->unpack(id_, a, args ...); -} - -inline bool Entity::valid() const { - return manager_ && manager_->valid(id_); -} - -inline std::ostream &operator << (std::ostream &out, const Entity::Id &id) { - out << "Entity::Id(" << id.index() << "." << id.version() << ")"; - return out; -} - - -inline std::ostream &operator << (std::ostream &out, const Entity &entity) { - out << "Entity(" << entity.id() << ")"; - return out; -} - - -template <typename C, typename EM> -inline ComponentHandle<C, EM>::operator bool() const { - return valid(); -} - -template <typename C, typename EM> -inline bool ComponentHandle<C, EM>::valid() const { - return manager_ && manager_->valid(id_) && manager_->template has_component<C>(id_); -} - -template <typename C, typename EM> -inline C *ComponentHandle<C, EM>::operator -> () { - assert(valid()); - return manager_->template get_component_ptr<C>(id_); -} - -template <typename C, typename EM> -inline const C *ComponentHandle<C, EM>::operator -> () const { - assert(valid()); - return manager_->template get_component_ptr<C>(id_); -} - -template <typename C, typename EM> -inline C &ComponentHandle<C, EM>::operator * () { - assert(valid()); - return *manager_->template get_component_ptr<C>(id_); -} - -template <typename C, typename EM> -inline const C &ComponentHandle<C, EM>::operator * () const { - assert(valid()); - return *manager_->template get_component_ptr<C>(id_); -} - -template <typename C, typename EM> -inline C *ComponentHandle<C, EM>::get() { - assert(valid()); - return manager_->template get_component_ptr<C>(id_); -} - -template <typename C, typename EM> -inline const C *ComponentHandle<C, EM>::get() const { - assert(valid()); - return manager_->template get_component_ptr<C>(id_); -} - -template <typename C, typename EM> -inline void ComponentHandle<C, EM>::remove() { - assert(valid()); - manager_->template remove<C>(id_); -} - -template <typename C, typename EM> -inline Entity ComponentHandle<C, EM>::entity() { - assert(valid()); - return manager_->get(id_); -} - - -} // namespace entityx - - -namespace std { -template <> struct hash<entityx::Entity> { - std::size_t operator () (const entityx::Entity &entity) const { - return static_cast<std::size_t>(entity.id().index() ^ entity.id().version()); - } -}; - -template <> struct hash<const entityx::Entity> { - std::size_t operator () (const entityx::Entity &entity) const { - return static_cast<std::size_t>(entity.id().index() ^ entity.id().version()); - } -}; -} - diff --git a/lib/entityx/entityx/Entity_test.cc b/lib/entityx/entityx/Entity_test.cc deleted file mode 100644 index f985794..0000000 --- a/lib/entityx/entityx/Entity_test.cc +++ /dev/null @@ -1,680 +0,0 @@ -/* - * Copyright (C) 2012 Alec Thomas <alec@swapoff.org> - * All rights reserved. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. - * - * Author: Alec Thomas <alec@swapoff.org> - */ - -#define CATCH_CONFIG_MAIN - -#include <algorithm> -#include <iterator> -#include <string> -#include <utility> -#include <vector> -#include <set> -#include <map> -#include "entityx/3rdparty/catch.hpp" -#include "entityx/entityx.h" - -// using namespace std; -using namespace entityx; - -using std::ostream; -using std::vector; -using std::set; -using std::map; -using std::pair; -using std::string; - -template <typename T> -int size(const T &t) { - int n = 0; - for (auto i : t) { - ++n; - (void)i; // Unused on purpose, suppress warning - } - return n; -} - -struct Position { - Position(float x = 0.0f, float y = 0.0f) : x(x), y(y) {} - - bool operator==(const Position &other) const { - return x == other.x && y == other.y; - } - - float x, y; -}; - -ostream &operator<<(ostream &out, const Position &position) { - out << "Position(" << position.x << ", " << position.y << ")"; - return out; -} - -struct Direction { - Direction(float x = 0.0f, float y = 0.0f) : x(x), y(y) {} - - bool operator==(const Direction &other) const { - return x == other.x && y == other.y; - } - - float x, y; -}; - -ostream &operator<<(ostream &out, const Direction &direction) { - out << "Direction(" << direction.x << ", " << direction.y << ")"; - return out; -} - -struct Tag : Component<Tag> { - explicit Tag(string tag) : tag(tag) {} - - bool operator==(const Tag &other) const { return tag == other.tag; } - - string tag; -}; - -ostream &operator<<(ostream &out, const Tag &tag) { - out << "Tag(" << tag.tag << ")"; - return out; -} - - -struct EntityManagerFixture { - EntityManagerFixture() : em(ev) {} - - EventManager ev; - EntityManager em; -}; - - -TEST_CASE_METHOD(EntityManagerFixture, "TestCreateEntity") { - REQUIRE(em.size() == 0UL); - - Entity e2; - REQUIRE(!(e2.valid())); - - Entity e = em.create(); - REQUIRE(e.valid()); - REQUIRE(em.size() == 1UL); - - e2 = e; - REQUIRE(e2.valid()); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestEntityAsBoolean") { - REQUIRE(em.size() == 0UL); - Entity e = em.create(); - REQUIRE(e.valid()); - REQUIRE(em.size() == 1UL); - REQUIRE(!(!e)); - - e.destroy(); - - REQUIRE(em.size() == 0UL); - - REQUIRE(!e); - - Entity e2; // Not initialized - REQUIRE(!e2); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestEntityReuse") { - Entity e1 = em.create(); - Entity e2 = e1; - auto id = e1.id(); - REQUIRE(e1.valid()); - REQUIRE(e2.valid()); - e1.destroy(); - REQUIRE(!e1.valid()); - REQUIRE(!e2.valid()); - Entity e3 = em.create(); - // It is assumed that the allocation will reuse the same entity id, though - // the version will change. - auto new_id = e3.id(); - REQUIRE(new_id != id); - REQUIRE((new_id.id() & 0xffffffffUL) == (id.id() & 0xffffffffUL)); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestComponentConstruction") { - auto e = em.create(); - auto p = e.assign<Position>(1, 2); - auto cp = e.component<Position>(); - REQUIRE(p == cp); - REQUIRE(1.0 == Approx(cp->x)); - REQUIRE(2.0 == Approx(cp->y)); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestDestroyEntity") { - Entity e = em.create(); - Entity f = em.create(); - e.assign<Position>(); - f.assign<Position>(); - e.assign<Direction>(); - f.assign<Direction>(); - - REQUIRE(e.valid()); - REQUIRE(f.valid()); - REQUIRE(static_cast<bool>(e.component<Position>())); - REQUIRE(static_cast<bool>(e.component<Direction>())); - REQUIRE(static_cast<bool>(f.component<Position>())); - REQUIRE(static_cast<bool>(f.component<Direction>())); - - e.destroy(); - - REQUIRE(!(e.valid())); - REQUIRE(f.valid()); - REQUIRE(static_cast<bool>(f.component<Position>())); - REQUIRE(static_cast<bool>(f.component<Direction>())); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestGetEntitiesWithComponent") { - Entity e = em.create(); - Entity f = em.create(); - Entity g = em.create(); - e.assign<Position>(); - e.assign<Direction>(); - f.assign<Position>(); - g.assign<Position>(); - REQUIRE(3 == size(em.entities_with_components<Position>())); - REQUIRE(1 == size(em.entities_with_components<Direction>())); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestGetEntitiesWithIntersectionOfComponents") { - vector<Entity> entities; - for (int i = 0; i < 150; ++i) { - Entity e = em.create(); - entities.push_back(e); - if (i % 2 == 0) e.assign<Position>(); - if (i % 3 == 0) e.assign<Direction>(); - } - REQUIRE(50 == size(em.entities_with_components<Direction>())); - REQUIRE(75 == size(em.entities_with_components<Position>())); - REQUIRE(25 == size(em.entities_with_components<Direction, Position>())); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestGetEntitiesWithComponentAndUnpacking") { - vector<Entity::Id> entities; - Entity e = em.create(); - Entity f = em.create(); - Entity g = em.create(); - std::vector<std::pair<ComponentHandle<Position>, ComponentHandle<Direction>>> position_directions; - position_directions.push_back(std::make_pair( - e.assign<Position>(1.0f, 2.0f), e.assign<Direction>(3.0f, 4.0f))); - position_directions.push_back(std::make_pair( - f.assign<Position>(7.0f, 8.0f), f.assign<Direction>(9.0f, 10.0f))); - auto thetag = f.assign<Tag>("tag"); - g.assign<Position>(5.0f, 6.0f); - int i = 0; - - ComponentHandle<Position> position; - REQUIRE(3 == size(em.entities_with_components(position))); - - ComponentHandle<Direction> direction; - for (auto unused_entity : em.entities_with_components(position, direction)) { - (void)unused_entity; - REQUIRE(position); - REQUIRE(direction); - auto pd = position_directions.at(i); - REQUIRE(position == pd.first); - REQUIRE(direction == pd.second); - ++i; - } - REQUIRE(2 == i); - ComponentHandle<Tag> tag; - i = 0; - for (auto unused_entity : - em.entities_with_components(position, direction, tag)) { - (void)unused_entity; - REQUIRE(static_cast<bool>(position)); - REQUIRE(static_cast<bool>(direction)); - REQUIRE(static_cast<bool>(tag)); - auto pd = position_directions.at(1); - REQUIRE(position == pd.first); - REQUIRE(direction == pd.second); - REQUIRE(tag == thetag); - i++; - } - REQUIRE(1 == i); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestIterateAllEntitiesSkipsDestroyed") { - Entity a = em.create(); - Entity b = em.create(); - Entity c = em.create(); - - b.destroy(); - - auto it = em.entities_for_debugging().begin(); - REQUIRE(a.id() == (*it).id()); - ++it; - REQUIRE(c.id() == (*it).id()); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestUnpack") { - Entity e = em.create(); - auto p = e.assign<Position>(1.0, 2.0); - auto d = e.assign<Direction>(3.0, 4.0); - auto t = e.assign<Tag>("tag"); - - ComponentHandle<Position> up; - ComponentHandle<Direction> ud; - ComponentHandle<Tag> ut; - e.unpack(up); - REQUIRE(p == up); - e.unpack(up, ud); - REQUIRE(p == up); - REQUIRE(d == ud); - e.unpack(up, ud, ut); - REQUIRE(p == up); - REQUIRE(d == ud); - REQUIRE(t == ut); -} - -// gcc 4.7.2 does not allow this struct to be declared locally inside the -// TEST_CASE_METHOD.EntityManagerFixture, " //" TEST_CASE_METHOD(EntityManagerFixture, "TestUnpackNullMissing") { -// Entity e = em.create(); -// auto p = e.assign<Position>(); - -// std::shared_ptr<Position> up(reinterpret_cast<Position*>(0Xdeadbeef), -// NullDeleter()); -// std::shared_ptr<Direction> ud(reinterpret_cast<Direction*>(0Xdeadbeef), -// NullDeleter()); -// e.unpack<Position, Direction>(up, ud); -// REQUIRE(p == up); -// REQUIRE(std::shared_ptr<Direction>() == ud); -// } - -TEST_CASE_METHOD(EntityManagerFixture, "TestComponentIdsDiffer") { - REQUIRE(EntityManager::component_family<Position>() != EntityManager::component_family<Direction>()); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestEntityCreatedEvent") { - struct EntityCreatedEventReceiver - : public Receiver<EntityCreatedEventReceiver> { - void receive(const EntityCreatedEvent &event) { - created.push_back(event.entity); - } - - vector<Entity> created; - }; - - EntityCreatedEventReceiver receiver; - ev.subscribe<EntityCreatedEvent>(receiver); - - REQUIRE(0UL == receiver.created.size()); - for (int i = 0; i < 10; ++i) { - em.create(); - } - REQUIRE(10UL == receiver.created.size()); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestEntityDestroyedEvent") { - struct EntityDestroyedEventReceiver - : public Receiver<EntityDestroyedEventReceiver> { - void receive(const EntityDestroyedEvent &event) { - destroyed.push_back(event.entity); - } - - vector<Entity> destroyed; - }; - - EntityDestroyedEventReceiver receiver; - ev.subscribe<EntityDestroyedEvent>(receiver); - - REQUIRE(0UL == receiver.destroyed.size()); - vector<Entity> entities; - for (int i = 0; i < 10; ++i) { - entities.push_back(em.create()); - } - REQUIRE(0UL == receiver.destroyed.size()); - for (auto e : entities) { - e.destroy(); - } - REQUIRE(10UL == receiver.destroyed.size()); - REQUIRE(entities == receiver.destroyed); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestComponentAddedEvent") { - struct ComponentAddedEventReceiver - : public Receiver<ComponentAddedEventReceiver> { - - ComponentAddedEventReceiver() - : position_events(0), direction_events(0) {} - - void receive(const ComponentAddedEvent<Position> &event) { - auto p = event.component; - float n = static_cast<float>(position_events); - REQUIRE(p->x == n); - REQUIRE(p->y == n); - position_events++; - } - - void receive(const ComponentAddedEvent<Direction> &event) { - auto p = event.component; - float n = static_cast<float>(direction_events); - REQUIRE(p->x == -n); - REQUIRE(p->y == -n); - direction_events++; - } - - int position_events; - int direction_events; - }; - - ComponentAddedEventReceiver receiver; - ev.subscribe<ComponentAddedEvent<Position>>(receiver); - ev.subscribe<ComponentAddedEvent<Direction>>(receiver); - - REQUIRE(ComponentAddedEvent<Position>::family() != - ComponentAddedEvent<Direction>::family()); - - REQUIRE(0 == receiver.position_events); - REQUIRE(0 == receiver.direction_events); - for (int i = 0; i < 10; ++i) { - Entity e = em.create(); - e.assign<Position>(static_cast<float>(i), static_cast<float>(i)); - e.assign<Direction>(static_cast<float>(-i), static_cast<float>(-i)); - } - REQUIRE(10 == receiver.position_events); - REQUIRE(10 == receiver.direction_events); -} - - -TEST_CASE_METHOD(EntityManagerFixture, "TestComponentRemovedEvent") { - struct ComponentRemovedReceiver : public Receiver<ComponentRemovedReceiver> { - void receive(const ComponentRemovedEvent<Direction> &event) { - removed = event.component; - } - - ComponentHandle<Direction> removed; - }; - - ComponentRemovedReceiver receiver; - ev.subscribe<ComponentRemovedEvent<Direction>>(receiver); - - REQUIRE(!(receiver.removed)); - Entity e = em.create(); - ComponentHandle<Direction> p = e.assign<Direction>(1.0, 2.0); - e.remove<Direction>(); - REQUIRE(receiver.removed == p); - REQUIRE(!(e.component<Direction>())); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestComponentRemovedEventOnEntityDestroyed") { - struct ComponentRemovedReceiver : public Receiver<ComponentRemovedReceiver> { - void receive(const ComponentRemovedEvent<Direction> &event) { - removed = true; - } - - bool removed = false; - }; - - ComponentRemovedReceiver receiver; - ev.subscribe<ComponentRemovedEvent<Direction>>(receiver); - - REQUIRE(!(receiver.removed)); - - Entity e = em.create(); - e.assign<Direction>(1.0, 2.0); - e.destroy(); - - REQUIRE(receiver.removed); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestEntityAssignment") { - Entity a, b; - a = em.create(); - REQUIRE(a != b); - b = a; - REQUIRE(a == b); - a.invalidate(); - REQUIRE(a != b); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestEntityDestroyAll") { - Entity a = em.create(), b = em.create(); - em.reset(); - REQUIRE(!(a.valid())); - REQUIRE(!(b.valid())); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestEntityDestroyHole") { - std::vector<Entity> entities; - - auto count = [this]()->int { - auto e = em.entities_with_components<Position>(); - return std::count_if(e.begin(), e.end(), - [](const Entity &) { return true; }); - }; - - for (int i = 0; i < 5000; i++) { - auto e = em.create(); - e.assign<Position>(); - entities.push_back(e); - } - - REQUIRE(count() == 5000); - - entities[2500].destroy(); - - REQUIRE(count() == 4999); -} - -// TODO(alec): Disable this on OSX - it doesn't seem to be possible to catch it?!? -// TEST_CASE_METHOD(EntityManagerFixture, "DeleteComponentThrowsBadAlloc") { -// Position *position = new Position(); -// REQUIRE_THROWS_AS(delete position, std::bad_alloc); -// } - - -TEST_CASE_METHOD(EntityManagerFixture, "TestComponentHandleInvalidatedWhenEntityDestroyed") { - Entity a = em.create(); - ComponentHandle<Position> position = a.assign<Position>(1, 2); - REQUIRE(position); - REQUIRE(position->x == 1); - REQUIRE(position->y == 2); - a.destroy(); - REQUIRE(!position); -} - -struct CopyVerifier : Component<CopyVerifier> { - CopyVerifier() : copied(false) {} - CopyVerifier(const CopyVerifier &other) { - copied = other.copied + 1; - } - - int copied; -}; - -TEST_CASE_METHOD(EntityManagerFixture, "TestComponentAssignmentFromCopy") { - Entity a = em.create(); - CopyVerifier original; - ComponentHandle<CopyVerifier> copy = a.assign_from_copy(original); - REQUIRE(copy); - REQUIRE(copy->copied == 1); - a.destroy(); - REQUIRE(!copy); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestEntityCreateFromCopy") { - Entity a = em.create(); - a.assign<CopyVerifier>(); - ComponentHandle<CopyVerifier> original = a.component<CopyVerifier>(); - ComponentHandle<Position> aPosition = a.assign<Position>(1, 2); - Entity b = em.create_from_copy(a); - ComponentHandle<CopyVerifier> copy = b.component<CopyVerifier>(); - ComponentHandle<Position> bPosition = b.component<Position>(); - REQUIRE(original); - REQUIRE(original->copied == false); - REQUIRE(copy); - REQUIRE(copy->copied == 1); - REQUIRE(aPosition->x == bPosition->x); - REQUIRE(aPosition->y == bPosition->y); - REQUIRE(aPosition.get() != bPosition.get()); - REQUIRE(a.component_mask() == b.component_mask()); - REQUIRE(a != b); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestComponentHandleInvalidatedWhenComponentDestroyed") { - Entity a = em.create(); - ComponentHandle<Position> position = a.assign<Position>(1, 2); - REQUIRE(position); - REQUIRE(position->x == 1); - REQUIRE(position->y == 2); - a.remove<Position>(); - REQUIRE(!position); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestDeleteEntityWithNoComponents") { - Entity a = em.create(); - a.assign<Position>(1, 2); - Entity b = em.create(); - b.destroy(); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestEntityInStdSet") { - Entity a = em.create(); - Entity b = em.create(); - Entity c = em.create(); - set<Entity> entitySet; - REQUIRE(entitySet.insert(a).second); - REQUIRE(entitySet.insert(b).second); - REQUIRE(entitySet.insert(c).second); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestEntityInStdMap") { - Entity a = em.create(); - Entity b = em.create(); - Entity c = em.create(); - map<Entity, int> entityMap; - REQUIRE(entityMap.insert(pair<Entity, int>(a, 1)).second); - REQUIRE(entityMap.insert(pair<Entity, int>(b, 2)).second); - REQUIRE(entityMap.insert(pair<Entity, int>(c, 3)).second); - REQUIRE(entityMap[a] == 1); - REQUIRE(entityMap[b] == 2); - REQUIRE(entityMap[c] == 3); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestEntityComponentsFromTuple") { - Entity e = em.create(); - e.assign<Position>(1, 2); - e.assign<Direction>(3, 4); - - std::tuple<ComponentHandle<Position>, ComponentHandle<Direction>> components = e.components<Position, Direction>(); - - REQUIRE(std::get<0>(components)->x == 1); - REQUIRE(std::get<0>(components)->y == 2); - REQUIRE(std::get<1>(components)->x == 3); - REQUIRE(std::get<1>(components)->y == 4); -} - -TEST_CASE("TestComponentDestructorCalledWhenManagerDestroyed") { - struct Freed { - explicit Freed(bool &yes) : yes(yes) {} - ~Freed() { yes = true; } - - bool &yes; - }; - - struct Test : Component<Test> { - explicit Test(bool &yes) : freed(yes) {} - - Freed freed; - }; - - bool freed = false; - { - EntityX e; - auto test = e.entities.create(); - test.assign<Test>(freed); - } - REQUIRE(freed == true); -} - -TEST_CASE("TestComponentDestructorCalledWhenEntityDestroyed") { - struct Freed { - explicit Freed(bool &yes) : yes(yes) {} - ~Freed() { yes = true; } - - bool &yes; - }; - - struct Test : Component<Test> { - explicit Test(bool &yes) : freed(yes) {} - - Freed freed; - }; - - bool freed = false; - EntityX e; - auto test = e.entities.create(); - test.assign<Test>(freed); - REQUIRE(freed == false); - test.destroy(); - REQUIRE(freed == true); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestComponentsRemovedFromReusedEntities") { - Entity a = em.create(); - Entity::Id aid = a.id(); - a.assign<Position>(1, 2); - a.destroy(); - - Entity b = em.create(); - Entity::Id bid = b.id(); - - REQUIRE(aid.index() == bid.index()); - REQUIRE(!b.has_component<Position>()); - b.assign<Position>(3, 4); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestConstComponentsNotInstantiatedTwice") { - Entity a = em.create(); - a.assign<Position>(1, 2); - - const Entity b = a; - - REQUIRE(a.component<Position>().valid()); - REQUIRE(b.component<const Position>().valid()); - REQUIRE(b.component<const Position>()->x == 1); - REQUIRE(b.component<const Position>()->y == 2); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestEntityManagerEach") { - Entity a = em.create(); - a.assign<Position>(1, 2); - int count = 0; - em.each<Position>([&count](Entity entity, Position &position) { - count++; - REQUIRE(position.x == 1); - REQUIRE(position.y == 2); - }); - REQUIRE(count == 1); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestViewEach") { - Entity a = em.create(); - a.assign<Position>(1, 2); - int count = 0; - em.entities_with_components<Position>().each([&count](Entity entity, Position &position) { - count++; - REQUIRE(position.x == 1); - REQUIRE(position.y == 2); - }); - REQUIRE(count == 1); -} - -TEST_CASE_METHOD(EntityManagerFixture, "TestComponentDereference") { - Entity a = em.create(); - a.assign<Position>(10, 5); - auto& positionRef = *a.component<Position>(); - REQUIRE(positionRef.x == 10); - REQUIRE(positionRef.y == 5); - positionRef.y = 20; - REQUIRE(a.component<Position>()->y == 20); -} diff --git a/lib/entityx/entityx/Event.cc b/lib/entityx/entityx/Event.cc deleted file mode 100644 index b719c5d..0000000 --- a/lib/entityx/entityx/Event.cc +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2012 Alec Thomas <alec@swapoff.org> - * All rights reserved. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. - * - * Author: Alec Thomas <alec@swapoff.org> - */ - -#include "entityx/Event.h" - -namespace entityx { - -BaseEvent::Family BaseEvent::family_counter_ = 0; - -BaseEvent::~BaseEvent() { -} - -EventManager::EventManager() { -} - -EventManager::~EventManager() { -} - -} // namespace entityx diff --git a/lib/entityx/entityx/Event.h b/lib/entityx/entityx/Event.h deleted file mode 100644 index cb7b3ab..0000000 --- a/lib/entityx/entityx/Event.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 2012 Alec Thomas <alec@swapoff.org> - * All rights reserved. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. - * - * Author: Alec Thomas <alec@swapoff.org> - */ - -#pragma once - -#include <cstdint> -#include <cstddef> -#include <vector> -#include <list> -#include <unordered_map> -#include <memory> -#include <utility> -#include "entityx/config.h" -#include "entityx/3rdparty/simplesignal.h" -#include "entityx/help/NonCopyable.h" - - -namespace entityx { - - -/// Used internally by the EventManager. -class BaseEvent { - public: - typedef std::size_t Family; - - virtual ~BaseEvent(); - - protected: - static Family family_counter_; -}; - - -typedef Simple::Signal<void (const void*)> EventSignal; -typedef std::shared_ptr<EventSignal> EventSignalPtr; -typedef std::weak_ptr<EventSignal> EventSignalWeakPtr; - - -/** - * Event types should subclass from this. - * - * struct Explosion : public Event<Explosion> { - * Explosion(int damage) : damage(damage) {} - * int damage; - * }; - */ -template <typename Derived> -class Event : public BaseEvent { - public: - /// Used internally for registration. - static Family family() { - static Family family = family_counter_++; - return family; - } -}; - - -class BaseReceiver { - public: - virtual ~BaseReceiver() { - for (auto connection : connections_) { - auto &ptr = connection.second.first; - if (!ptr.expired()) { - ptr.lock()->disconnect(connection.second.second); - } - } - } - - // Return number of signals connected to this receiver. - std::size_t connected_signals() const { - std::size_t size = 0; - for (auto connection : connections_) { - if (!connection.second.first.expired()) { - size++; - } - } - return size; - } - - private: - friend class EventManager; - std::unordered_map<BaseEvent::Family, std::pair<EventSignalWeakPtr, std::size_t>> connections_; -}; - - -template <typename Derived> -class Receiver : public BaseReceiver { - public: - virtual ~Receiver() {} -}; - - -/** - * Handles event subscription and delivery. - * - * Subscriptions are automatically removed when receivers are destroyed.. - */ -class EventManager : entityx::help::NonCopyable { - public: - EventManager(); - virtual ~EventManager(); - - /** - * Subscribe an object to receive events of type E. - * - * Receivers must be subclasses of Receiver and must implement a receive() method accepting the given event type. - * - * eg. - * - * struct ExplosionReceiver : public Receiver<ExplosionReceiver> { - * void receive(const Explosion &explosion) { - * } - * }; - * - * ExplosionReceiver receiver; - * em.subscribe<Explosion>(receiver); - */ - template <typename E, typename Receiver> - void subscribe(Receiver &receiver) { - void (Receiver::*receive)(const E &) = &Receiver::receive; - auto sig = signal_for(Event<E>::family()); - auto wrapper = EventCallbackWrapper<E>(std::bind(receive, &receiver, std::placeholders::_1)); - auto connection = sig->connect(wrapper); - BaseReceiver &base = receiver; - base.connections_.insert(std::make_pair(Event<E>::family(), std::make_pair(EventSignalWeakPtr(sig), connection))); - } - - /** - * Unsubscribe an object in order to not receive events of type E anymore. - * - * Receivers must have subscribed for event E before unsubscribing from event E. - * - */ - template <typename E, typename Receiver> - void unsubscribe(Receiver &receiver) { - BaseReceiver &base = receiver; - // Assert that it has been subscribed before - assert(base.connections_.find(Event<E>::family()) != base.connections_.end()); - auto pair = base.connections_[Event<E>::family()]; - auto connection = pair.second; - auto &ptr = pair.first; - if (!ptr.expired()) { - ptr.lock()->disconnect(connection); - } - base.connections_.erase(Event<E>::family()); - } - - template <typename E> - void emit(const E &event) { - auto sig = signal_for(Event<E>::family()); - sig->emit(&event); - } - - /** - * Emit an already constructed event. - */ - template <typename E> - void emit(std::unique_ptr<E> event) { - auto sig = signal_for(Event<E>::family()); - sig->emit(event.get()); - } - - /** - * Emit an event to receivers. - * - * This method constructs a new event object of type E with the provided arguments, then delivers it to all receivers. - * - * eg. - * - * std::shared_ptr<EventManager> em = new EventManager(); - * em->emit<Explosion>(10); - * - */ - template <typename E, typename ... Args> - void emit(Args && ... args) { - // Using 'E event(std::forward...)' causes VS to fail with an internal error. Hack around it. - E event = E(std::forward<Args>(args) ...); - auto sig = signal_for(std::size_t(Event<E>::family())); - sig->emit(&event); - } - - std::size_t connected_receivers() const { - std::size_t size = 0; - for (EventSignalPtr handler : handlers_) { - if (handler) size += handler->size(); - } - return size; - } - - private: - EventSignalPtr &signal_for(std::size_t id) { - if (id >= handlers_.size()) - handlers_.resize(id + 1); - if (!handlers_[id]) - handlers_[id] = std::make_shared<EventSignal>(); - return handlers_[id]; - } - - // Functor used as an event signal callback that casts to E. - template <typename E> - struct EventCallbackWrapper { - explicit EventCallbackWrapper(std::function<void(const E &)> callback) : callback(callback) {} - void operator()(const void *event) { callback(*(static_cast<const E*>(event))); } - std::function<void(const E &)> callback; - }; - - std::vector<EventSignalPtr> handlers_; -}; - -} // namespace entityx diff --git a/lib/entityx/entityx/Event_test.cc b/lib/entityx/entityx/Event_test.cc deleted file mode 100644 index c315051..0000000 --- a/lib/entityx/entityx/Event_test.cc +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2012 Alec Thomas <alec@swapoff.org> - * All rights reserved. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. - * - * Author: Alec Thomas <alec@swapoff.org> - */ - -#define CATCH_CONFIG_MAIN - -#include <string> -#include <vector> -#include "entityx/3rdparty/catch.hpp" -#include "entityx/Event.h" - - -using entityx::EventManager; -using entityx::Event; -using entityx::Receiver; - - -struct Explosion { - explicit Explosion(int damage) : damage(damage) {} - int damage; -}; - - -struct Collision { - explicit Collision(int damage) : damage(damage) {} - int damage; -}; - -struct ExplosionSystem : public Receiver<ExplosionSystem> { - void receive(const Explosion &explosion) { - damage_received += explosion.damage; - received_count++; - } - - void receive(const Collision &collision) { - damage_received += collision.damage; - received_count++; - } - - int received_count = 0; - int damage_received = 0; -}; - -TEST_CASE("TestEmitReceive") { - EventManager em; - ExplosionSystem explosion_system; - em.subscribe<Explosion>(explosion_system); - em.subscribe<Collision>(explosion_system); - REQUIRE(0 == explosion_system.damage_received); - em.emit<Explosion>(10); - REQUIRE(1 == explosion_system.received_count); - REQUIRE(10 == explosion_system.damage_received); - em.emit<Collision>(10); - REQUIRE(20 == explosion_system.damage_received); - REQUIRE(2 == explosion_system.received_count); -} - -TEST_CASE("TestUntypedEmitReceive") { - EventManager em; - ExplosionSystem explosion_system; - em.subscribe<Explosion>(explosion_system); - REQUIRE(0 == explosion_system.damage_received); - Explosion explosion(10); - em.emit(explosion); - REQUIRE(1 == explosion_system.received_count); - REQUIRE(10 == explosion_system.damage_received); -} - - -TEST_CASE("TestReceiverExpired") { - EventManager em; - { - ExplosionSystem explosion_system; - em.subscribe<Explosion>(explosion_system); - em.emit<Explosion>(10); - REQUIRE(10 == explosion_system.damage_received); - REQUIRE(1 == explosion_system.connected_signals()); - REQUIRE(1 == em.connected_receivers()); - } - REQUIRE(0 == em.connected_receivers()); -} - - -TEST_CASE("TestSenderExpired") { - ExplosionSystem explosion_system; - { - EventManager em; - em.subscribe<Explosion>(explosion_system); - em.emit<Explosion>(10); - REQUIRE(10 == explosion_system.damage_received); - REQUIRE(1 == explosion_system.connected_signals()); - REQUIRE(1 == em.connected_receivers()); - } - REQUIRE(0 == explosion_system.connected_signals()); -} - -TEST_CASE("TestUnsubscription") { - ExplosionSystem explosion_system; - { - EventManager em; - em.subscribe<Explosion>(explosion_system); - REQUIRE(explosion_system.damage_received == 0); - em.emit<Explosion>(1); - REQUIRE(explosion_system.damage_received == 1); - em.unsubscribe<Explosion>(explosion_system); - em.emit<Explosion>(1); - REQUIRE(explosion_system.damage_received == 1); - } -} diff --git a/lib/entityx/entityx/System.cc b/lib/entityx/entityx/System.cc deleted file mode 100644 index 8e4b5a9..0000000 --- a/lib/entityx/entityx/System.cc +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2012 Alec Thomas <alec@swapoff.org> - * All rights reserved. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. - * - * Author: Alec Thomas <alec@swapoff.org> - */ - -#include "entityx/System.h" - -namespace entityx { - -BaseSystem::Family BaseSystem::family_counter_; - -BaseSystem::~BaseSystem() { -} - -void SystemManager::update_all(TimeDelta dt) { - assert(initialized_ && "SystemManager::configure() not called"); - for (auto &pair : systems_) { - pair.second->update(entity_manager_, event_manager_, dt); - } -} - -void SystemManager::configure() { - for (auto &pair : systems_) { - pair.second->configure(entity_manager_, event_manager_); - } - initialized_ = true; -} - -} // namespace entityx diff --git a/lib/entityx/entityx/System.h b/lib/entityx/entityx/System.h deleted file mode 100644 index c199957..0000000 --- a/lib/entityx/entityx/System.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2012 Alec Thomas <alec@swapoff.org> - * All rights reserved. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. - * - * Author: Alec Thomas <alec@swapoff.org> - */ - -#pragma once - - -#include <cstdint> -#include <unordered_map> -#include <utility> -#include <cassert> -#include "entityx/config.h" -#include "entityx/Entity.h" -#include "entityx/Event.h" -#include "entityx/help/NonCopyable.h" - - -namespace entityx { - - -class SystemManager; - - -/** - * Base System class. Generally should not be directly used, instead see System<Derived>. - */ -class BaseSystem : entityx::help::NonCopyable { - public: - typedef size_t Family; - - virtual ~BaseSystem(); - - /** - * Called once all Systems have been added to the SystemManager. - * - * Typically used to set up event handlers. - */ - virtual void configure([[maybe_unused]] EntityManager &entities, EventManager &events) { - configure(events); - } - - /** - * Legacy configure(). Called by default implementation of configure(EntityManager&, EventManager&). - */ - virtual void configure([[maybe_unused]] EventManager &events) {} - - /** - * Apply System behavior. - * - * Called every game step. - */ - virtual void update(EntityManager &entities, EventManager &events, TimeDelta dt) = 0; - - static Family family_counter_; - - protected: -}; - - -/** - * Use this class when implementing Systems. - * - * struct MovementSystem : public System<MovementSystem> { - * void update(EntityManager &entities, EventManager &events, TimeDelta dt) { - * // Do stuff to/with entities... - * } - * } - */ -template <typename Derived> -class System : public BaseSystem { - public: - virtual ~System() {} - -private: - friend class SystemManager; - - static Family family() { - static Family family = family_counter_++; - return family; - } -}; - - -class SystemManager : entityx::help::NonCopyable { - public: - SystemManager(EntityManager &entity_manager, - EventManager &event_manager) : - entity_manager_(entity_manager), - event_manager_(event_manager) {} - - /** - * Add a System to the SystemManager. - * - * Must be called before Systems can be used. - * - * eg. - * std::shared_ptr<MovementSystem> movement = entityx::make_shared<MovementSystem>(); - * system.add(movement); - */ - template <typename S> - void add(std::shared_ptr<S> system) { - systems_.insert(std::make_pair(S::family(), system)); - } - - /** - * Add a System to the SystemManager. - * - * Must be called before Systems can be used. - * - * eg. - * auto movement = system.add<MovementSystem>(); - */ - template <typename S, typename ... Args> - std::shared_ptr<S> add(Args && ... args) { - std::shared_ptr<S> s(new S(std::forward<Args>(args) ...)); - add(s); - return s; - } - - /** - * Retrieve the registered System instance, if any. - * - * std::shared_ptr<CollisionSystem> collisions = systems.system<CollisionSystem>(); - * - * @return System instance or empty shared_std::shared_ptr<S>. - */ - template <typename S> - std::shared_ptr<S> system() { - auto it = systems_.find(S::family()); - assert(it != systems_.end()); - return it == systems_.end() - ? std::shared_ptr<S>() - : std::shared_ptr<S>(std::static_pointer_cast<S>(it->second)); - } - - /** - * Call the System::update() method for a registered system. - */ - template <typename S> - void update(TimeDelta dt) { - assert(initialized_ && "SystemManager::configure() not called"); - std::shared_ptr<S> s = system<S>(); - s->update(entity_manager_, event_manager_, dt); - } - - /** - * Call System::update() on all registered systems. - * - * The order which the registered systems are updated is arbitrary but consistent, - * meaning the order which they will be updated cannot be specified, but that order - * will stay the same as long no systems are added or removed. - * - * If the order in which systems update is important, use SystemManager::update() - * to manually specify the update order. EntityX does not yet support a way of - * specifying priority for update_all(). - */ - void update_all(TimeDelta dt); - - /** - * Configure the system. Call after adding all Systems. - * - * This is typically used to set up event handlers. - */ - void configure(); - - private: - bool initialized_ = false; - EntityManager &entity_manager_; - EventManager &event_manager_; - std::unordered_map<BaseSystem::Family, std::shared_ptr<BaseSystem>> systems_; -}; - -} // namespace entityx diff --git a/lib/entityx/entityx/System_test.cc b/lib/entityx/entityx/System_test.cc deleted file mode 100644 index 71ef183..0000000 --- a/lib/entityx/entityx/System_test.cc +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2012 Alec Thomas <alec@swapoff.org> - * All rights reserved. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. - * - * Author: Alec Thomas <alec@swapoff.org> - */ - -#define CATCH_CONFIG_MAIN - -#include <string> -#include <vector> -#include "entityx/3rdparty/catch.hpp" -#include "entityx/System.h" -#include "entityx/quick.h" - -// using namespace std; -using namespace entityx; -using std::string; - -struct Position : Component<Position> { - explicit Position(float x = 0.0f, float y = 0.0f) : x(x), y(y) {} - - float x, y; -}; - -struct Direction : Component<Direction> { - explicit Direction(float x = 0.0f, float y = 0.0f) : x(x), y(y) {} - - float x, y; -}; - -struct Counter : Component<Counter> { - explicit Counter(int counter = 0) : counter(counter) {} - - int counter; -}; - -class MovementSystem : public System<MovementSystem> { - public: - explicit MovementSystem(string label = "") : label(label) {} - - void update(EntityManager &es, EventManager &events, TimeDelta) override { - auto entities = es.entities_with_components<Position, Direction>(); - ComponentHandle<Position> position; - ComponentHandle<Direction> direction; - for (auto entity : entities) { - entity.unpack<Position, Direction>(position, direction); - position->x += direction->x; - position->y += direction->y; - } - } - - string label; -}; - -class CounterSystem : public System<CounterSystem> { -public: - void update(EntityManager &es, EventManager &events, TimeDelta) override { - auto entities = es.entities_with_components<Counter>(); - Counter::Handle counter; - for (auto entity : entities) { - entity.unpack<Counter>(counter); - counter->counter++; - } - } -}; - -class EntitiesFixture : public EntityX { - public: - std::vector<Entity> created_entities; - - EntitiesFixture() { - for (int i = 0; i < 150; ++i) { - Entity e = entities.create(); - created_entities.push_back(e); - if (i % 2 == 0) e.assign<Position>(1, 2); - if (i % 3 == 0) e.assign<Direction>(1, 1); - - e.assign<Counter>(0); - } - } -}; - -TEST_CASE_METHOD(EntitiesFixture, "TestConstructSystemWithArgs") { - systems.add<MovementSystem>("movement"); - systems.configure(); - - REQUIRE("movement" == systems.system<MovementSystem>()->label); -} - -TEST_CASE_METHOD(EntitiesFixture, "TestApplySystem") { - systems.add<MovementSystem>(); - systems.configure(); - - systems.update<MovementSystem>(0.0); - ComponentHandle<Position> position; - ComponentHandle<Direction> direction; - for (auto entity : created_entities) { - entity.unpack<Position, Direction>(position, direction); - if (position && direction) { - REQUIRE(2.0 == Approx(position->x)); - REQUIRE(3.0 == Approx(position->y)); - } else if (position) { - REQUIRE(1.0 == Approx(position->x)); - REQUIRE(2.0 == Approx(position->y)); - } - } -} - -TEST_CASE_METHOD(EntitiesFixture, "TestApplyAllSystems") { - systems.add<MovementSystem>(); - systems.add<CounterSystem>(); - systems.configure(); - - systems.update_all(0.0); - Position::Handle position; - Direction::Handle direction; - Counter::Handle counter; - for (auto entity : created_entities) { - entity.unpack<Position, Direction, Counter>(position, direction, counter); - if (position && direction) { - REQUIRE(2.0 == Approx(position->x)); - REQUIRE(3.0 == Approx(position->y)); - } else if (position) { - REQUIRE(1.0 == Approx(position->x)); - REQUIRE(2.0 == Approx(position->y)); - } - REQUIRE(1 == counter->counter); - } -} diff --git a/lib/entityx/entityx/config.h b/lib/entityx/entityx/config.h deleted file mode 100644 index 630f8a8..0000000 --- a/lib/entityx/entityx/config.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include <cstdint> -#include <cstddef> - -namespace entityx { - -static const size_t MAX_COMPONENTS = 64; -typedef double TimeDelta; - -} // namespace entityx diff --git a/lib/entityx/entityx/config.h.in b/lib/entityx/entityx/config.h.in deleted file mode 100644 index a46fc24..0000000 --- a/lib/entityx/entityx/config.h.in +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include <cstdint> -#include <cstddef> - -namespace entityx { - -static const size_t MAX_COMPONENTS = @ENTITYX_MAX_COMPONENTS@; -typedef @ENTITYX_DT_TYPE@ TimeDelta; - -} // namespace entityx diff --git a/lib/entityx/entityx/deps/Dependencies.h b/lib/entityx/entityx/deps/Dependencies.h deleted file mode 100644 index 88c9f79..0000000 --- a/lib/entityx/entityx/deps/Dependencies.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2013 Alec Thomas <alec@swapoff.org> - * All rights reserved. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. - * - * Author: Alec Thomas <alec@swapoff.org> - */ -#pragma once - -#include "entityx/System.h" -#include "entityx/Event.h" -#include "entityx/Entity.h" - -namespace entityx { -namespace deps { - -/** - * An entityx::System for declaring component dependencies. - * - * eg. To declare that a `Physics` component must always be paired with `Position` - * and `Direction` components: - * - * system_manager->add<Dependency<Physics, Position, Direction>>(); - */ -template <typename C, typename ... Deps> -class Dependency : public System<Dependency<C, Deps...>>, public Receiver<Dependency<C, Deps...>> { -public: - void receive(const ComponentAddedEvent<C> &event) { - assign<Deps...>(event.entity); - } - - void configure(EventManager &events) override { - events.subscribe<ComponentAddedEvent<C>>(*this); - } - - void update(EntityManager &entities, EventManager &events, TimeDelta dt) override {} - -private: - template <typename D> - void assign(Entity entity) { - if (!entity.component<D>()) entity.assign<D>(); - } - - template <typename D, typename D1, typename ... Ds> - void assign(Entity entity) { - assign<D>(entity); - assign<D1, Ds...>(entity); - } -}; - -} // namespace deps -} // namespace entityx diff --git a/lib/entityx/entityx/deps/Dependencies_test.cc b/lib/entityx/entityx/deps/Dependencies_test.cc deleted file mode 100644 index fe9844c..0000000 --- a/lib/entityx/entityx/deps/Dependencies_test.cc +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2013 Alec Thomas <alec@swapoff.org> - * All rights reserved. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. - * - * Author: Alec Thomas <alec@swapoff.org> - */ - -#define CATCH_CONFIG_MAIN - -#include "entityx/3rdparty/catch.hpp" -#include "entityx/deps/Dependencies.h" -#include "entityx/quick.h" - - -namespace deps = entityx::deps; - - -struct A : public entityx::Component<A> {}; -struct B : public entityx::Component<B> { - explicit B(bool b = false) : b(b) {} - - bool b; -}; -struct C : public entityx::Component<C> {}; - -TEST_CASE_METHOD(entityx::EntityX, "TestSingleDependency") { - systems.add<deps::Dependency<A, B>>(); - systems.configure(); - - entityx::Entity e = entities.create(); - REQUIRE(!static_cast<bool>(e.component<A>())); - REQUIRE(!static_cast<bool>(e.component<B>())); - e.assign<A>(); - REQUIRE(static_cast<bool>(e.component<A>())); - REQUIRE(static_cast<bool>(e.component<B>())); -} - -TEST_CASE_METHOD(entityx::EntityX, "TestMultipleDependencies") { - systems.add<deps::Dependency<A, B, C>>(); - systems.configure(); - - entityx::Entity e = entities.create(); - REQUIRE(!static_cast<bool>(e.component<A>())); - REQUIRE(!static_cast<bool>(e.component<B>())); - REQUIRE(!static_cast<bool>(e.component<C>())); - e.assign<A>(); - REQUIRE(static_cast<bool>(e.component<A>())); - REQUIRE(static_cast<bool>(e.component<B>())); - REQUIRE(static_cast<bool>(e.component<C>())); -} - -TEST_CASE_METHOD(entityx::EntityX, "TestDependencyDoesNotRecreateComponent") { - systems.add<deps::Dependency<A, B>>(); - systems.configure(); - - entityx::Entity e = entities.create(); - e.assign<B>(true); - REQUIRE(e.component<B>()->b); - e.assign<A>(); - REQUIRE(e.component<B>()->b); -} diff --git a/lib/entityx/entityx/entityx.h b/lib/entityx/entityx/entityx.h deleted file mode 100644 index 0799793..0000000 --- a/lib/entityx/entityx/entityx.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "entityx/config.h" -#include "entityx/Event.h" -#include "entityx/Entity.h" -#include "entityx/System.h" -#include "entityx/quick.h" diff --git a/lib/entityx/entityx/help/NonCopyable.h b/lib/entityx/entityx/help/NonCopyable.h deleted file mode 100644 index 19c0ed1..0000000 --- a/lib/entityx/entityx/help/NonCopyable.h +++ /dev/null @@ -1,20 +0,0 @@ -// Inspired heavily by boost::noncopyable - -#pragma once - -namespace entityx { -namespace help { - -class NonCopyable { -protected: - NonCopyable() = default; - ~NonCopyable() = default; - - - NonCopyable(const NonCopyable&) = delete; - NonCopyable& operator = (const NonCopyable &) = delete; -}; - - -} // namespace help -} // namespace entityx diff --git a/lib/entityx/entityx/help/Pool.cc b/lib/entityx/entityx/help/Pool.cc deleted file mode 100644 index c710887..0000000 --- a/lib/entityx/entityx/help/Pool.cc +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2012-2014 Alec Thomas <alec@swapoff.org> - * All rights reserved. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. - * - * Author: Alec Thomas <alec@swapoff.org> - */ - -#include "entityx/help/Pool.h" - -namespace entityx { - -BasePool::~BasePool() { - for (char *ptr : blocks_) { - delete[] ptr; - } -} - -} // namespace entityx diff --git a/lib/entityx/entityx/help/Pool.h b/lib/entityx/entityx/help/Pool.h deleted file mode 100644 index f217ec2..0000000 --- a/lib/entityx/entityx/help/Pool.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2012-2014 Alec Thomas <alec@swapoff.org> - * All rights reserved. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. - * - * Author: Alec Thomas <alec@swapoff.org> - */ - -#pragma once - -#include <cstddef> -#include <cassert> -#include <vector> - -namespace entityx { - -/** - * Provides a resizable, semi-contiguous pool of memory for constructing - * objects in. Pointers into the pool will be invalided only when the pool is - * destroyed. - * - * The semi-contiguous nature aims to provide cache-friendly iteration. - * - * Lookups are O(1). - * Appends are amortized O(1). - */ -class BasePool { - public: - explicit BasePool(std::size_t element_size, std::size_t chunk_size = 8192) - : element_size_(element_size), chunk_size_(chunk_size), capacity_(0) {} - virtual ~BasePool(); - - std::size_t size() const { return size_; } - std::size_t capacity() const { return capacity_; } - std::size_t chunks() const { return blocks_.size(); } - - /// Ensure at least n elements will fit in the pool. - inline void expand(std::size_t n) { - if (n >= size_) { - if (n >= capacity_) reserve(n); - size_ = n; - } - } - - inline void reserve(std::size_t n) { - while (capacity_ < n) { - char *chunk = new char[element_size_ * chunk_size_]; - blocks_.push_back(chunk); - capacity_ += chunk_size_; - } - } - - inline void *get(std::size_t n) { - assert(n < size_); - return blocks_[n / chunk_size_] + (n % chunk_size_) * element_size_; - } - - inline const void *get(std::size_t n) const { - assert(n < size_); - return blocks_[n / chunk_size_] + (n % chunk_size_) * element_size_; - } - - virtual void destroy(std::size_t n) = 0; - - protected: - std::vector<char *> blocks_; - std::size_t element_size_; - std::size_t chunk_size_; - std::size_t size_ = 0; - std::size_t capacity_; -}; - - -/** - * Implementation of BasePool that provides type-"safe" deconstruction of - * elements in the pool. - */ -template <typename T, std::size_t ChunkSize = 8192> -class Pool : public BasePool { - public: - Pool() : BasePool(sizeof(T), ChunkSize) {} - virtual ~Pool() { - // Component destructors *must* be called by owner. - } - - virtual void destroy(std::size_t n) override { - assert(n < size_); - T *ptr = static_cast<T*>(get(n)); - ptr->~T(); - } -}; - -} // namespace entityx diff --git a/lib/entityx/entityx/help/Pool_test.cc b/lib/entityx/entityx/help/Pool_test.cc deleted file mode 100644 index 56ca85a..0000000 --- a/lib/entityx/entityx/help/Pool_test.cc +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2012-2014 Alec Thomas <alec@swapoff.org> - * All rights reserved. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. - * - * Author: Alec Thomas <alec@swapoff.org> - */ - -#define CATCH_CONFIG_MAIN - -#include <vector> -#include "entityx/3rdparty/catch.hpp" -#include "entityx/help/Pool.h" - -struct Position { - explicit Position(int *ptr = nullptr) : ptr(ptr) { - if (ptr) (*ptr)++; - } - ~Position() { - if (ptr) (*ptr)++; - } - - float x, y; - int *ptr; -}; - - -TEST_CASE("TestPoolReserve") { - entityx::Pool<Position, 8> pool; - REQUIRE(0 == pool.capacity()); - REQUIRE(0 == pool.chunks()); - pool.reserve(8); - REQUIRE(0 == pool.size()); - REQUIRE(8 == pool.capacity()); - REQUIRE(1 == pool.chunks()); - pool.reserve(16); - REQUIRE(0 == pool.size()); - REQUIRE(16 == pool.capacity()); - REQUIRE(2 == pool.chunks()); -} - -TEST_CASE("TestPoolPointers") { - entityx::Pool<Position, 8> pool; - std::vector<char*> ptrs; - for (int i = 0; i < 4; i++) { - pool.expand(i * 8 + 8); - // NOTE: This is an attempt to ensure non-contiguous allocations from - // arena allocators. - ptrs.push_back(new char[8 * sizeof(Position)]); - } - char *p0 = static_cast<char*>(pool.get(0)); - char *p7 = static_cast<char*>(pool.get(7)); - char *p8 = static_cast<char*>(pool.get(8)); - char *p16 = static_cast<char*>(pool.get(16)); - char *p24 = static_cast<char*>(pool.get(24)); - - void *expected_p7 = p0 + 7 * sizeof(Position); - REQUIRE(expected_p7 == static_cast<void*>(p7)); - void *extrapolated_p8 = p0 + 8 * sizeof(Position); - REQUIRE(extrapolated_p8 != static_cast<void*>(p8)); - void *extrapolated_p16 = p8 + 8 * sizeof(Position); - REQUIRE(extrapolated_p16 != static_cast<void*>(p16)); - void *extrapolated_p24 = p16 + 8 * sizeof(Position); - REQUIRE(extrapolated_p24 != static_cast<void*>(p24)); -} - -TEST_CASE("TestDeconstruct") { - entityx::Pool<Position, 8> pool; - pool.expand(8); - - void *p0 = pool.get(0); - - int counter = 0; - new(p0) Position(&counter); - REQUIRE(1 == counter); - pool.destroy(0); - REQUIRE(2 == counter); -} diff --git a/lib/entityx/entityx/help/Timer.cc b/lib/entityx/entityx/help/Timer.cc deleted file mode 100644 index 43960a7..0000000 --- a/lib/entityx/entityx/help/Timer.cc +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2013 Antony Woods <antony@teamwoods.org> - * All rights reserved. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. - * - * Author: Antony Woods <antony@teamwoods.org> - */ - -#include "entityx/help/Timer.h" - -namespace entityx { -namespace help { - -Timer::Timer() { - _start = std::chrono::system_clock::now(); -} - -Timer::~Timer() { -} - -void Timer::restart() { - _start = std::chrono::system_clock::now(); -} - -double Timer::elapsed() { - return std::chrono::duration<double>(std::chrono::system_clock::now() - _start).count(); -} - -} // namespace help -} // namespace entityx diff --git a/lib/entityx/entityx/help/Timer.h b/lib/entityx/entityx/help/Timer.h deleted file mode 100644 index 4d22b08..0000000 --- a/lib/entityx/entityx/help/Timer.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2013 Antony Woods <antony@teamwoods.org> - * All rights reserved. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. - * - * Author: Antony Woods <antony@teamwoods.org> - */ -#pragma once - -#include <chrono> - -namespace entityx { -namespace help { - -class Timer { -public: - Timer(); - ~Timer(); - - void restart(); - double elapsed(); -private: - std::chrono::time_point<std::chrono::system_clock> _start; -}; - -} // namespace help -} // namespace entityx diff --git a/lib/entityx/entityx/quick.h b/lib/entityx/entityx/quick.h deleted file mode 100644 index 3454b58..0000000 --- a/lib/entityx/entityx/quick.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2014 Alec Thomas <alec@swapoff.org> - * All rights reserved. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. - * - * Author: Alec Thomas <alec@swapoff.org> - */ - -#pragma once - -#include "entityx/Entity.h" -#include "entityx/Event.h" -#include "entityx/System.h" -#include "entityx/config.h" - -namespace entityx { - -/** - * A convenience class for instantiating an EventManager, EntityManager and - * SystemManager. - */ -class EntityX { - public: - EntityX() : entities(events), systems(entities, events) {} - - EventManager events; - EntityManager entities; - SystemManager systems; -}; - -} // namespace entityx diff --git a/lib/entityx/entityx/tags/TagsComponent.h b/lib/entityx/entityx/tags/TagsComponent.h deleted file mode 100644 index 6d19734..0000000 --- a/lib/entityx/entityx/tags/TagsComponent.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2012 Alec Thomas <alec@swapoff.org> - * All rights reserved. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. - * - * Author: Alec Thomas <alec@swapoff.org> - */ - -#pragma once - -#include <unordered_set> -#include <string> -#include "entityx/Entity.h" - -namespace entityx { -namespace tags { - -/** - * Allow entities to be tagged with strings. - * - * entity.assign<TagsComponent>("tag1", "tag2"); - * - * ComponentPtr<TagsComponent> tags; - * for (Entity entity : entity_manager.entities_with_components(tags)) - */ -class TagsComponent : public Component<TagsComponent> { - public: - /** - * Construct a new TagsComponent with the given tags. - * - * eg. TagsComponent tags("a", "b", "c"); - */ - template <typename ... Args> - TagsComponent(const std::string &tag, const Args & ... tags) { - set_tags(tag, tags ...); - } - - std::unordered_set<std::string> tags; - - private: - template <typename ... Args> - void set_tags(const std::string &tag1, const std::string &tag2, const Args & ... tags) { - this->tags.insert(tag1); - set_tags(tag2, tags ...); - } - - void set_tags(const std::string &tag) { - tags.insert(tag); - } -}; - -} // namespace tags -} // namespace entityx diff --git a/lib/entityx/entityx/tags/TagsComponent_test.cc b/lib/entityx/entityx/tags/TagsComponent_test.cc deleted file mode 100644 index c1d575e..0000000 --- a/lib/entityx/entityx/tags/TagsComponent_test.cc +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2012 Alec Thomas <alec@swapoff.org> - * All rights reserved. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. - * - * Author: Alec Thomas <alec@swapoff.org> - */ - -#define CATCH_CONFIG_MAIN - -#include <string> -#include "entityx/3rdparty/catch.hpp" -#include "entityx/tags/TagsComponent.h" - -using namespace std; -using namespace entityx; -using namespace entityx::tags; - - -struct Position : public Component<Position> {}; - - -template <typename T> -int size(const T &t) { - int n = 0; - for (auto i : t) { - ++n; - (void)i; // Unused on purpose, suppress warning - } - return n; -} - - -TEST_CASE("TestVariadicConstruction", "TagsComponentTest") { - auto tags = TagsComponent("player", "indestructible"); - unordered_set<string> expected; - expected.insert("player"); - expected.insert("indestructible"); - REQUIRE(expected == tags.tags); -} diff --git a/lib/entityx/examples/LiberationSans-Regular.ttf b/lib/entityx/examples/LiberationSans-Regular.ttf Binary files differdeleted file mode 100644 index 254ace4..0000000 --- a/lib/entityx/examples/LiberationSans-Regular.ttf +++ /dev/null diff --git a/lib/entityx/examples/example.cc b/lib/entityx/examples/example.cc deleted file mode 100644 index a1ec1c1..0000000 --- a/lib/entityx/examples/example.cc +++ /dev/null @@ -1,412 +0,0 @@ -/** - * This is an example of using EntityX. - * - * It is an SFML2 application that spawns 100 random circles on a 2D plane - * moving in random directions. If two circles collide they will explode and - * emit particles. - * - * This illustrates a bunch of EC/EntityX concepts: - * - * - Separation of data via components. - * - Separation of logic via systems. - * - Use of events (colliding bodies trigger a CollisionEvent). - * - * Compile with: - * - * c++ -I.. -O3 -std=c++11 -Wall -lsfml-system -lsfml-window -lsfml-graphics -lentityx example.cc -o example - */ -#include <cmath> -#include <unordered_set> -#include <sstream> -#include <cstdlib> -#include <memory> -#include <string> -#include <vector> -#include <iostream> -#include <SFML/Window.hpp> -#include <SFML/Graphics.hpp> -#include <entityx/entityx.h> - -using std::cerr; -using std::cout; -using std::endl; - -namespace ex = entityx; - - -float r(int a, float b = 0) { - return static_cast<float>(std::rand() % (a * 1000) + b * 1000) / 1000.0; -} - - -struct Body { - Body(const sf::Vector2f &position, const sf::Vector2f &direction, float rotationd = 0.0) - : position(position), direction(direction), rotationd(rotationd), alpha(0.0) {} - - sf::Vector2f position; - sf::Vector2f direction; - float rotation = 0.0, rotationd, alpha; -}; - - -using Renderable = std::shared_ptr<sf::Shape>; - - -struct Particle { - explicit Particle(sf::Color colour, float radius, float duration) - : colour(colour), radius(radius), alpha(colour.a), d(colour.a / duration) {} - - sf::Color colour; - float radius, alpha, d; -}; - - -struct Collideable { - explicit Collideable(float radius) : radius(radius) {} - - float radius; -}; - - -// Emitted when two entities collide. -struct CollisionEvent { - CollisionEvent(ex::Entity left, ex::Entity right) : left(left), right(right) {} - - ex::Entity left, right; -}; - - -class SpawnSystem : public ex::System<SpawnSystem> { -public: - explicit SpawnSystem(sf::RenderTarget &target, int count) : size(target.getSize()), count(count) {} - - void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override { - int c = 0; - ex::ComponentHandle<Collideable> collideable; - es.each<Collideable>([&](ex::Entity entity, Collideable&) { ++c; }); - - for (int i = 0; i < count - c; i++) { - ex::Entity entity = es.create(); - - // Mark as collideable (explosion particles will not be collideable). - collideable = entity.assign<Collideable>(r(10, 5)); - - // "Physical" attributes. - entity.assign<Body>( - sf::Vector2f(r(size.x), r(size.y)), - sf::Vector2f(r(100, -50), r(100, -50))); - - // Shape to apply to entity. - Renderable shape(new sf::CircleShape(collideable->radius)); - shape->setFillColor(sf::Color(r(128, 127), r(128, 127), r(128, 127), 0)); - shape->setOrigin(collideable->radius, collideable->radius); - entity.assign<Renderable>(shape); - } - } - -private: - sf::Vector2u size; - int count; -}; - - -// Updates a body's position and rotation. -struct BodySystem : public ex::System<BodySystem> { - void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override { - const float fdt = static_cast<float>(dt); - es.each<Body>([fdt](ex::Entity entity, Body &body) { - body.position += body.direction * fdt; - body.rotation += body.rotationd * fdt; - body.alpha = std::min(1.0f, body.alpha + fdt); - }); - }; -}; - - -// Bounce bodies off the edge of the screen. -class BounceSystem : public ex::System<BounceSystem> { -public: - explicit BounceSystem(sf::RenderTarget &target) : size(target.getSize()) {} - - void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override { - es.each<Body>([this](ex::Entity entity, Body &body) { - if (body.position.x + body.direction.x < 0 || - body.position.x + body.direction.x >= size.x) - body.direction.x = -body.direction.x; - if (body.position.y + body.direction.y < 0 || - body.position.y + body.direction.y >= size.y) - body.direction.y = -body.direction.y; - }); - } - -private: - sf::Vector2u size; -}; - - -// Determines if two Collideable bodies have collided. If they have it emits a -// CollisionEvent. This is used by ExplosionSystem to create explosion -// particles, but it could be used by a SoundSystem to play an explosion -// sound, etc.. -// -// Uses a fairly rudimentary 2D partition system, but performs reasonably well. -class CollisionSystem : public ex::System<CollisionSystem> { - static const int PARTITIONS = 200; - - struct Candidate { - sf::Vector2f position; - float radius; - ex::Entity entity; - }; - -public: - explicit CollisionSystem(sf::RenderTarget &target) : size(target.getSize()) { - size.x = size.x / PARTITIONS + 1; - size.y = size.y / PARTITIONS + 1; - } - - void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override { - reset(); - collect(es); - collide(events); - }; - -private: - std::vector<std::vector<Candidate>> grid; - sf::Vector2u size; - - void reset() { - grid.clear(); - grid.resize(size.x * size.y); - } - - void collect(ex::EntityManager &entities) { - entities.each<Body, Collideable>([this](ex::Entity entity, Body &body, Collideable &collideable) { - unsigned int - left = static_cast<int>(body.position.x - collideable.radius) / PARTITIONS, - top = static_cast<int>(body.position.y - collideable.radius) / PARTITIONS, - right = static_cast<int>(body.position.x + collideable.radius) / PARTITIONS, - bottom = static_cast<int>(body.position.y + collideable.radius) / PARTITIONS; - Candidate candidate {body.position, collideable.radius, entity}; - unsigned int slots[4] = { - left + top * size.x, - right + top * size.x, - left + bottom * size.x, - right + bottom * size.x, - }; - grid[slots[0]].push_back(candidate); - if (slots[0] != slots[1]) grid[slots[1]].push_back(candidate); - if (slots[1] != slots[2]) grid[slots[2]].push_back(candidate); - if (slots[2] != slots[3]) grid[slots[3]].push_back(candidate); - }); - } - - void collide(ex::EventManager &events) { - for (const std::vector<Candidate> &candidates : grid) { - for (const Candidate &left : candidates) { - for (const Candidate &right : candidates) { - if (left.entity == right.entity) continue; - if (collided(left, right)) - events.emit<CollisionEvent>(left.entity, right.entity); - } - } - } - } - - float length(const sf::Vector2f &v) { - return std::sqrt(v.x * v.x + v.y * v.y); - } - - bool collided(const Candidate &left, const Candidate &right) { - return length(left.position - right.position) < left.radius + right.radius; - } -}; - - -// Fade out and then remove particles. -class ParticleSystem : public ex::System<ParticleSystem> { -public: - void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override { - es.each<Particle>([dt](ex::Entity entity, Particle &particle) { - particle.alpha -= particle.d * dt; - if (particle.alpha <= 0) { - entity.destroy(); - } else { - particle.colour.a = particle.alpha; - } - }); - } -}; - - -// Renders all explosion particles efficiently as a quad vertex array. -class ParticleRenderSystem : public ex::System<ParticleRenderSystem> { -public: - explicit ParticleRenderSystem(sf::RenderTarget &target) : target(target) {} - - void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override { - sf::VertexArray vertices(sf::Quads); - es.each<Particle, Body>([&vertices](ex::Entity entity, Particle &particle, Body &body) { - const float r = particle.radius; - // Spin the particles. - sf::Transform transform; - transform.rotate(body.rotation); - vertices.append(sf::Vertex(body.position + transform.transformPoint(sf::Vector2f(-r, -r)), particle.colour)); - vertices.append(sf::Vertex(body.position + transform.transformPoint(sf::Vector2f(r, -r)), particle.colour)); - vertices.append(sf::Vertex(body.position + transform.transformPoint(sf::Vector2f(r, r)), particle.colour)); - vertices.append(sf::Vertex(body.position + transform.transformPoint(sf::Vector2f(-r, r)), particle.colour)); - }); - target.draw(vertices); - } -private: - sf::RenderTarget ⌖ -}; - - -// For any two colliding bodies, destroys the bodies and emits a bunch of bodgy explosion particles. -class ExplosionSystem : public ex::System<ExplosionSystem>, public ex::Receiver<ExplosionSystem> { -public: - void configure(ex::EventManager &events) override { - events.subscribe<CollisionEvent>(*this); - } - - void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override { - for (ex::Entity entity : collided) { - emit_particles(es, entity); - entity.destroy(); - } - collided.clear(); - } - - void emit_particles(ex::EntityManager &es, ex::Entity entity) { - ex::ComponentHandle<Body> body = entity.component<Body>(); - ex::ComponentHandle<Renderable> renderable = entity.component<Renderable>(); - ex::ComponentHandle<Collideable> collideable = entity.component<Collideable>(); - sf::Color colour = (*renderable)->getFillColor(); - colour.a = 200; - - float area = (M_PI * collideable->radius * collideable->radius) / 3.0; - for (int i = 0; i < area; i++) { - ex::Entity particle = es.create(); - - float rotationd = r(720, 180); - if (std::rand() % 2 == 0) rotationd = -rotationd; - - float offset = r(collideable->radius, 1); - float angle = r(360) * M_PI / 180.0; - particle.assign<Body>( - body->position + sf::Vector2f(offset * cos(angle), offset * sin(angle)), - body->direction + sf::Vector2f(offset * 2 * cos(angle), offset * 2 * sin(angle)), - rotationd); - - float radius = r(3, 1); - particle.assign<Particle>(colour, radius, radius / 2); - } - } - - void receive(const CollisionEvent &collision) { - // Events are immutable, so we can't destroy the entities here. We defer - // the work until the update loop. - collided.insert(collision.left); - collided.insert(collision.right); - } - -private: - std::unordered_set<ex::Entity> collided; -}; - - -// Render all Renderable entities and draw some informational text. -class RenderSystem :public ex::System<RenderSystem> { -public: - explicit RenderSystem(sf::RenderTarget &target, sf::Font &font) : target(target) { - text.setFont(font); - text.setPosition(sf::Vector2f(2, 2)); - text.setCharacterSize(18); - text.setColor(sf::Color::White); - } - - void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override { - es.each<Body, Renderable>([this](ex::Entity entity, Body &body, Renderable &renderable) { - sf::Color fillColor = renderable->getFillColor(); - fillColor.a = sf::Uint8(body.alpha * 255); - renderable->setFillColor(fillColor); - renderable->setPosition(body.position); - renderable->setRotation(body.rotation); - target.draw(*renderable.get()); - }); - last_update += dt; - frame_count++; - if (last_update >= 0.5) { - std::ostringstream out; - const double fps = frame_count / last_update; - out << es.size() << " entities (" << static_cast<int>(fps) << " fps)"; - text.setString(out.str()); - last_update = 0.0; - frame_count = 0.0; - } - target.draw(text); - } - -private: - double last_update = 0.0; - double frame_count = 0.0; - sf::RenderTarget ⌖ - sf::Text text; -}; - - -class Application : public ex::EntityX { -public: - explicit Application(sf::RenderTarget &target, sf::Font &font) { - systems.add<SpawnSystem>(target, 500); - systems.add<BodySystem>(); - systems.add<BounceSystem>(target); - systems.add<CollisionSystem>(target); - systems.add<ExplosionSystem>(); - systems.add<ParticleSystem>(); - systems.add<RenderSystem>(target, font); - systems.add<ParticleRenderSystem>(target); - systems.configure(); - } - - void update(ex::TimeDelta dt) { - systems.update_all(dt); - } -}; - - - -int main() { - std::srand(std::time(nullptr)); - - sf::RenderWindow window(sf::VideoMode::getDesktopMode(), "EntityX Example", sf::Style::Fullscreen); - sf::Font font; - if (!font.loadFromFile("LiberationSans-Regular.ttf")) { - cerr << "error: failed to load LiberationSans-Regular.ttf" << endl; - return 1; - } - - Application app(window, font); - - sf::Clock clock; - while (window.isOpen()) { - sf::Event event; - while (window.pollEvent(event)) { - switch (event.type) { - case sf::Event::Closed: - case sf::Event::KeyPressed: - window.close(); - break; - - default: - break; - } - } - - window.clear(); - sf::Time elapsed = clock.restart(); - app.update(elapsed.asSeconds()); - window.display(); - } -} diff --git a/lib/entityx/scripts/travis.sh b/lib/entityx/scripts/travis.sh deleted file mode 100755 index c8b2a17..0000000 --- a/lib/entityx/scripts/travis.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -e - -cmake -DCMAKE_BUILD_TYPE=Debug -DENTITYX_BUILD_TESTING=1 -make VERBOSE=1 -make test || cat Testing/Temporary/LastTest.log diff --git a/lib/sol2 b/lib/sol2 new file mode 160000 +Subproject 4de99c5b41b64b7e654bf8e48b177e8414a756b |