initial commit
diff --git a/cmake/FindASan.cmake b/cmake/FindASan.cmake
new file mode 100644
index 0000000..fcebb43
--- /dev/null
+++ b/cmake/FindASan.cmake
@@ -0,0 +1,59 @@
+# The MIT License (MIT)
+#
+# Copyright (c)
+#   2013 Matthew Arsenault
+#   2015-2016 RWTH Aachen University, Federal Republic of Germany
+#
+# 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.
+
+option(SANITIZE_ADDRESS "Enable AddressSanitizer for sanitized targets." Off)
+
+set(FLAG_CANDIDATES
+    # Clang 3.2+ use this version. The no-omit-frame-pointer option is optional.
+    "-g -fsanitize=address -fno-omit-frame-pointer"
+    "-g -fsanitize=address"
+
+    # Older deprecated flag for ASan
+    "-g -faddress-sanitizer"
+)
+
+
+if (SANITIZE_ADDRESS AND (SANITIZE_THREAD OR SANITIZE_MEMORY))
+    message(FATAL_ERROR "AddressSanitizer is not compatible with "
+        "ThreadSanitizer or MemorySanitizer.")
+endif ()
+
+
+include(sanitize-helpers)
+
+if (SANITIZE_ADDRESS)
+    sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "AddressSanitizer"
+        "ASan")
+
+    find_program(ASan_WRAPPER "asan-wrapper" PATHS ${CMAKE_MODULE_PATH})
+	mark_as_advanced(ASan_WRAPPER)
+endif ()
+
+function (add_sanitize_address TARGET)
+    if (NOT SANITIZE_ADDRESS)
+        return()
+    endif ()
+
+    saitizer_add_flags(${TARGET} "AddressSanitizer" "ASan")
+endfunction ()
diff --git a/cmake/FindMSan.cmake b/cmake/FindMSan.cmake
new file mode 100644
index 0000000..3b0a4ad
--- /dev/null
+++ b/cmake/FindMSan.cmake
@@ -0,0 +1,57 @@
+# The MIT License (MIT)
+#
+# Copyright (c)
+#   2013 Matthew Arsenault
+#   2015-2016 RWTH Aachen University, Federal Republic of Germany
+#
+# 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.
+
+option(SANITIZE_MEMORY "Enable MemorySanitizer for sanitized targets." Off)
+
+set(FLAG_CANDIDATES
+    "-g -fsanitize=memory"
+)
+
+
+include(sanitize-helpers)
+
+if (SANITIZE_MEMORY)
+    if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
+        message(WARNING "MemorySanitizer disabled for target ${TARGET} because "
+            "MemorySanitizer is supported for Linux systems only.")
+        set(SANITIZE_MEMORY Off CACHE BOOL
+            "Enable MemorySanitizer for sanitized targets." FORCE)
+    elseif (NOT ${CMAKE_SIZEOF_VOID_P} EQUAL 8)
+        message(WARNING "MemorySanitizer disabled for target ${TARGET} because "
+            "MemorySanitizer is supported for 64bit systems only.")
+        set(SANITIZE_MEMORY Off CACHE BOOL
+            "Enable MemorySanitizer for sanitized targets." FORCE)
+    else ()
+        sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "MemorySanitizer"
+            "MSan")
+    endif ()
+endif ()
+
+function (add_sanitize_memory TARGET)
+    if (NOT SANITIZE_MEMORY)
+        return()
+    endif ()
+
+    saitizer_add_flags(${TARGET} "MemorySanitizer" "MSan")
+endfunction ()
diff --git a/cmake/FindSanitizers.cmake b/cmake/FindSanitizers.cmake
new file mode 100644
index 0000000..71cda38
--- /dev/null
+++ b/cmake/FindSanitizers.cmake
@@ -0,0 +1,87 @@
+# The MIT License (MIT)
+#
+# Copyright (c)
+#   2013 Matthew Arsenault
+#   2015-2016 RWTH Aachen University, Federal Republic of Germany
+#
+# 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.
+
+# If any of the used compiler is a GNU compiler, add a second option to static
+# link against the sanitizers.
+option(SANITIZE_LINK_STATIC "Try to link static against sanitizers." Off)
+
+
+
+
+set(FIND_QUIETLY_FLAG "")
+if (DEFINED Sanitizers_FIND_QUIETLY)
+    set(FIND_QUIETLY_FLAG "QUIET")
+endif ()
+
+find_package(ASan ${FIND_QUIETLY_FLAG})
+find_package(TSan ${FIND_QUIETLY_FLAG})
+find_package(MSan ${FIND_QUIETLY_FLAG})
+find_package(UBSan ${FIND_QUIETLY_FLAG})
+
+
+
+
+function(sanitizer_add_blacklist_file FILE)
+    if(NOT IS_ABSOLUTE ${FILE})
+        set(FILE "${CMAKE_CURRENT_SOURCE_DIR}/${FILE}")
+    endif()
+    get_filename_component(FILE "${FILE}" REALPATH)
+
+    sanitizer_check_compiler_flags("-fsanitize-blacklist=${FILE}"
+        "SanitizerBlacklist" "SanBlist")
+endfunction()
+
+function(add_sanitizers ...)
+    # If no sanitizer is enabled, return immediately.
+    if (NOT (SANITZE_ADDRESS OR SANITIZE_MEMORY OR SANITIZE_THREAD OR
+        SANITIZE_UNDEFINED))
+        return()
+    endif ()
+
+    foreach (TARGET ${ARGV})
+        # Check if this target will be compiled by exactly one compiler. Other-
+        # wise sanitizers can't be used and a warning should be printed once.
+        sanitizer_target_compilers(${TARGET} TARGET_COMPILER)
+        list(LENGTH TARGET_COMPILER NUM_COMPILERS)
+        if (NUM_COMPILERS GREATER 1)
+            message(WARNING "Can't use any sanitizers for target ${TARGET}, "
+                    "because it will be compiled by incompatible compilers. "
+                    "Target will be compiled without sanitzers.")
+            return()
+
+        # If the target is compiled by no known compiler, ignore it.
+        elseif (NUM_COMPILERS EQUAL 0)
+            message(WARNING "Can't use any sanitizers for target ${TARGET}, "
+                    "because it uses an unknown compiler. Target will be "
+                    "compiled without sanitzers.")
+            return()
+        endif ()
+
+        # Add sanitizers for target.
+        add_sanitize_address(${TARGET})
+        add_sanitize_thread(${TARGET})
+        add_sanitize_memory(${TARGET})
+        add_sanitize_undefined(${TARGET})
+	endforeach ()
+endfunction(add_sanitizers)
diff --git a/cmake/FindTSan.cmake b/cmake/FindTSan.cmake
new file mode 100644
index 0000000..0e80f29
--- /dev/null
+++ b/cmake/FindTSan.cmake
@@ -0,0 +1,64 @@
+# The MIT License (MIT)
+#
+# Copyright (c)
+#   2013 Matthew Arsenault
+#   2015-2016 RWTH Aachen University, Federal Republic of Germany
+#
+# 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.
+
+option(SANITIZE_THREAD "Enable ThreadSanitizer for sanitized targets." Off)
+
+set(FLAG_CANDIDATES
+    "-g -fsanitize=thread"
+)
+
+
+# ThreadSanitizer is not compatible with MemorySanitizer.
+if (SANITIZE_THREAD AND SANITIZE_MEMORY)
+    message(FATAL_ERROR "ThreadSanitizer is not compatible with "
+        "MemorySanitizer.")
+endif ()
+
+
+include(sanitize-helpers)
+
+if (SANITIZE_THREAD)
+    if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
+        message(WARNING "ThreadSanitizer disabled for target ${TARGET} because "
+            "ThreadSanitizer is supported for Linux systems only.")
+        set(SANITIZE_THREAD Off CACHE BOOL
+            "Enable ThreadSanitizer for sanitized targets." FORCE)
+    elseif (NOT ${CMAKE_SIZEOF_VOID_P} EQUAL 8)
+        message(WARNING "ThreadSanitizer disabled for target ${TARGET} because "
+            "ThreadSanitizer is supported for 64bit systems only.")
+        set(SANITIZE_THREAD Off CACHE BOOL
+            "Enable ThreadSanitizer for sanitized targets." FORCE)
+    else ()
+        sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "ThreadSanitizer"
+            "TSan")
+    endif ()
+endif ()
+
+function (add_sanitize_thread TARGET)
+    if (NOT SANITIZE_THREAD)
+        return()
+    endif ()
+
+    saitizer_add_flags(${TARGET} "ThreadSanitizer" "TSan")
+endfunction ()
diff --git a/cmake/FindUBSan.cmake b/cmake/FindUBSan.cmake
new file mode 100644
index 0000000..6948674
--- /dev/null
+++ b/cmake/FindUBSan.cmake
@@ -0,0 +1,46 @@
+# The MIT License (MIT)
+#
+# Copyright (c)
+#   2013 Matthew Arsenault
+#   2015-2016 RWTH Aachen University, Federal Republic of Germany
+#
+# 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.
+
+option(SANITIZE_UNDEFINED
+    "Enable UndefinedBehaviorSanitizer for sanitized targets." Off)
+
+set(FLAG_CANDIDATES
+    "-g -fsanitize=undefined"
+)
+
+
+include(sanitize-helpers)
+
+if (SANITIZE_UNDEFINED)
+    sanitizer_check_compiler_flags("${FLAG_CANDIDATES}"
+        "UndefinedBehaviorSanitizer" "UBSan")
+endif ()
+
+function (add_sanitize_undefined TARGET)
+    if (NOT SANITIZE_UNDEFINED)
+        return()
+    endif ()
+
+    saitizer_add_flags(${TARGET} "UndefinedBehaviorSanitizer" "UBSan")
+endfunction ()
diff --git a/cmake/HunterGate.cmake b/cmake/HunterGate.cmake
new file mode 100644
index 0000000..97f69cc
--- /dev/null
+++ b/cmake/HunterGate.cmake
@@ -0,0 +1,514 @@
+# Copyright (c) 2013-2015, Ruslan Baratov
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice, this
+#   list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright notice,
+#   this list of conditions and the following disclaimer in the documentation
+#   and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# This is a gate file to Hunter package manager.
+# Include this file using `include` command and add package you need, example:
+#
+#     cmake_minimum_required(VERSION 3.0)
+#
+#     include("cmake/HunterGate.cmake")
+#     HunterGate(
+#         URL "https://github.com/path/to/hunter/archive.tar.gz"
+#         SHA1 "798501e983f14b28b10cda16afa4de69eee1da1d"
+#     )
+#
+#     project(MyProject)
+#
+#     hunter_add_package(Foo)
+#     hunter_add_package(Boo COMPONENTS Bar Baz)
+#
+# Projects:
+#     * https://github.com/hunter-packages/gate/
+#     * https://github.com/ruslo/hunter
+
+option(HUNTER_ENABLED "Enable Hunter package manager support" ON)
+if(HUNTER_ENABLED)
+  if(CMAKE_VERSION VERSION_LESS "3.0")
+    message(FATAL_ERROR "At least CMake version 3.0 required for hunter dependency management."
+      " Update CMake or set HUNTER_ENABLED to OFF.")
+  endif()
+endif()
+
+include(CMakeParseArguments) # cmake_parse_arguments
+
+option(HUNTER_STATUS_PRINT "Print working status" ON)
+option(HUNTER_STATUS_DEBUG "Print a lot info" OFF)
+
+set(HUNTER_WIKI "https://github.com/ruslo/hunter/wiki")
+
+function(hunter_gate_status_print)
+  foreach(print_message ${ARGV})
+    if(HUNTER_STATUS_PRINT OR HUNTER_STATUS_DEBUG)
+      message(STATUS "[hunter] ${print_message}")
+    endif()
+  endforeach()
+endfunction()
+
+function(hunter_gate_status_debug)
+  foreach(print_message ${ARGV})
+    if(HUNTER_STATUS_DEBUG)
+      string(TIMESTAMP timestamp)
+      message(STATUS "[hunter *** DEBUG *** ${timestamp}] ${print_message}")
+    endif()
+  endforeach()
+endfunction()
+
+function(hunter_gate_wiki wiki_page)
+  message("------------------------------ WIKI -------------------------------")
+  message("    ${HUNTER_WIKI}/${wiki_page}")
+  message("-------------------------------------------------------------------")
+  message("")
+  message(FATAL_ERROR "")
+endfunction()
+
+function(hunter_gate_internal_error)
+  message("")
+  foreach(print_message ${ARGV})
+    message("[hunter ** INTERNAL **] ${print_message}")
+  endforeach()
+  message("[hunter ** INTERNAL **] [Directory:${CMAKE_CURRENT_LIST_DIR}]")
+  message("")
+  hunter_gate_wiki("error.internal")
+endfunction()
+
+function(hunter_gate_fatal_error)
+  cmake_parse_arguments(hunter "" "WIKI" "" "${ARGV}")
+  string(COMPARE EQUAL "${hunter_WIKI}" "" have_no_wiki)
+  if(have_no_wiki)
+    hunter_gate_internal_error("Expected wiki")
+  endif()
+  message("")
+  foreach(x ${hunter_UNPARSED_ARGUMENTS})
+    message("[hunter ** FATAL ERROR **] ${x}")
+  endforeach()
+  message("[hunter ** FATAL ERROR **] [Directory:${CMAKE_CURRENT_LIST_DIR}]")
+  message("")
+  hunter_gate_wiki("${hunter_WIKI}")
+endfunction()
+
+function(hunter_gate_user_error)
+  hunter_gate_fatal_error(${ARGV} WIKI "error.incorrect.input.data")
+endfunction()
+
+function(hunter_gate_self root version sha1 result)
+  string(COMPARE EQUAL "${root}" "" is_bad)
+  if(is_bad)
+    hunter_gate_internal_error("root is empty")
+  endif()
+
+  string(COMPARE EQUAL "${version}" "" is_bad)
+  if(is_bad)
+    hunter_gate_internal_error("version is empty")
+  endif()
+
+  string(COMPARE EQUAL "${sha1}" "" is_bad)
+  if(is_bad)
+    hunter_gate_internal_error("sha1 is empty")
+  endif()
+
+  string(SUBSTRING "${sha1}" 0 7 archive_id)
+
+  if(EXISTS "${root}/cmake/Hunter")
+    set(hunter_self "${root}")
+  else()
+    set(
+        hunter_self
+        "${root}/_Base/Download/Hunter/${version}/${archive_id}/Unpacked"
+    )
+  endif()
+
+  set("${result}" "${hunter_self}" PARENT_SCOPE)
+endfunction()
+
+# Set HUNTER_GATE_ROOT cmake variable to suitable value.
+function(hunter_gate_detect_root)
+  # Check CMake variable
+  string(COMPARE NOTEQUAL "${HUNTER_ROOT}" "" not_empty)
+  if(not_empty)
+    set(HUNTER_GATE_ROOT "${HUNTER_ROOT}" PARENT_SCOPE)
+    hunter_gate_status_debug("HUNTER_ROOT detected by cmake variable")
+    return()
+  endif()
+
+  # Check environment variable
+  string(COMPARE NOTEQUAL "$ENV{HUNTER_ROOT}" "" not_empty)
+  if(not_empty)
+    set(HUNTER_GATE_ROOT "$ENV{HUNTER_ROOT}" PARENT_SCOPE)
+    hunter_gate_status_debug("HUNTER_ROOT detected by environment variable")
+    return()
+  endif()
+
+  # Check HOME environment variable
+  string(COMPARE NOTEQUAL "$ENV{HOME}" "" result)
+  if(result)
+    set(HUNTER_GATE_ROOT "$ENV{HOME}/.hunter" PARENT_SCOPE)
+    hunter_gate_status_debug("HUNTER_ROOT set using HOME environment variable")
+    return()
+  endif()
+
+  # Check SYSTEMDRIVE and USERPROFILE environment variable (windows only)
+  if(WIN32)
+    string(COMPARE NOTEQUAL "$ENV{SYSTEMDRIVE}" "" result)
+    if(result)
+      set(HUNTER_GATE_ROOT "$ENV{SYSTEMDRIVE}/.hunter" PARENT_SCOPE)
+      hunter_gate_status_debug(
+          "HUNTER_ROOT set using SYSTEMDRIVE environment variable"
+      )
+      return()
+    endif()
+
+    string(COMPARE NOTEQUAL "$ENV{USERPROFILE}" "" result)
+    if(result)
+      set(HUNTER_GATE_ROOT "$ENV{USERPROFILE}/.hunter" PARENT_SCOPE)
+      hunter_gate_status_debug(
+          "HUNTER_ROOT set using USERPROFILE environment variable"
+      )
+      return()
+    endif()
+  endif()
+
+  hunter_gate_fatal_error(
+      "Can't detect HUNTER_ROOT"
+      WIKI "error.detect.hunter.root"
+  )
+endfunction()
+
+macro(hunter_gate_lock dir)
+  if(NOT HUNTER_SKIP_LOCK)
+    if("${CMAKE_VERSION}" VERSION_LESS "3.2")
+      hunter_gate_fatal_error(
+          "Can't lock, upgrade to CMake 3.2 or use HUNTER_SKIP_LOCK"
+          WIKI "error.can.not.lock"
+      )
+    endif()
+    hunter_gate_status_debug("Locking directory: ${dir}")
+    file(LOCK "${dir}" DIRECTORY GUARD FUNCTION)
+    hunter_gate_status_debug("Lock done")
+  endif()
+endmacro()
+
+function(hunter_gate_download dir)
+  string(
+      COMPARE
+      NOTEQUAL
+      "$ENV{HUNTER_DISABLE_AUTOINSTALL}"
+      ""
+      disable_autoinstall
+  )
+  if(disable_autoinstall AND NOT HUNTER_RUN_INSTALL)
+    hunter_gate_fatal_error(
+        "Hunter not found in '${dir}'"
+        "Set HUNTER_RUN_INSTALL=ON to auto-install it from '${HUNTER_GATE_URL}'"
+        "Settings:"
+        "  HUNTER_ROOT: ${HUNTER_GATE_ROOT}"
+        "  HUNTER_SHA1: ${HUNTER_GATE_SHA1}"
+        WIKI "error.run.install"
+    )
+  endif()
+  string(COMPARE EQUAL "${dir}" "" is_bad)
+  if(is_bad)
+    hunter_gate_internal_error("Empty 'dir' argument")
+  endif()
+
+  string(COMPARE EQUAL "${HUNTER_GATE_SHA1}" "" is_bad)
+  if(is_bad)
+    hunter_gate_internal_error("HUNTER_GATE_SHA1 empty")
+  endif()
+
+  string(COMPARE EQUAL "${HUNTER_GATE_URL}" "" is_bad)
+  if(is_bad)
+    hunter_gate_internal_error("HUNTER_GATE_URL empty")
+  endif()
+
+  set(done_location "${dir}/DONE")
+  set(sha1_location "${dir}/SHA1")
+
+  set(build_dir "${dir}/Build")
+  set(cmakelists "${dir}/CMakeLists.txt")
+
+  hunter_gate_lock("${dir}")
+  if(EXISTS "${done_location}")
+    # while waiting for lock other instance can do all the job
+    hunter_gate_status_debug("File '${done_location}' found, skip install")
+    return()
+  endif()
+
+  file(REMOVE_RECURSE "${build_dir}")
+  file(REMOVE_RECURSE "${cmakelists}")
+
+  file(MAKE_DIRECTORY "${build_dir}") # check directory permissions
+
+  # Disabling languages speeds up a little bit, reduces noise in the output
+  # and avoids path too long windows error
+  file(
+      WRITE
+      "${cmakelists}"
+      "cmake_minimum_required(VERSION 3.0)\n"
+      "project(HunterDownload LANGUAGES NONE)\n"
+      "include(ExternalProject)\n"
+      "ExternalProject_Add(\n"
+      "    Hunter\n"
+      "    URL\n"
+      "    \"${HUNTER_GATE_URL}\"\n"
+      "    URL_HASH\n"
+      "    SHA1=${HUNTER_GATE_SHA1}\n"
+      "    DOWNLOAD_DIR\n"
+      "    \"${dir}\"\n"
+      "    SOURCE_DIR\n"
+      "    \"${dir}/Unpacked\"\n"
+      "    CONFIGURE_COMMAND\n"
+      "    \"\"\n"
+      "    BUILD_COMMAND\n"
+      "    \"\"\n"
+      "    INSTALL_COMMAND\n"
+      "    \"\"\n"
+      ")\n"
+  )
+
+  if(HUNTER_STATUS_DEBUG)
+    set(logging_params "")
+  else()
+    set(logging_params OUTPUT_QUIET)
+  endif()
+
+  hunter_gate_status_debug("Run generate")
+
+  # Need to add toolchain file too.
+  # Otherwise on Visual Studio + MDD this will fail with error:
+  # "Could not find an appropriate version of the Windows 10 SDK installed on this machine"
+  if(EXISTS "${CMAKE_TOOLCHAIN_FILE}")
+    set(toolchain_arg "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}")
+  else()
+    # 'toolchain_arg' can't be empty
+    set(toolchain_arg "-DCMAKE_TOOLCHAIN_FILE=")
+  endif()
+
+  execute_process(
+      COMMAND "${CMAKE_COMMAND}" "-H${dir}" "-B${build_dir}" "-G${CMAKE_GENERATOR}" "${toolchain_arg}"
+      WORKING_DIRECTORY "${dir}"
+      RESULT_VARIABLE download_result
+      ${logging_params}
+  )
+
+  if(NOT download_result EQUAL 0)
+    hunter_gate_internal_error("Configure project failed")
+  endif()
+
+  hunter_gate_status_print(
+      "Initializing Hunter workspace (${HUNTER_GATE_SHA1})"
+      "  ${HUNTER_GATE_URL}"
+      "  -> ${dir}"
+  )
+  execute_process(
+      COMMAND "${CMAKE_COMMAND}" --build "${build_dir}"
+      WORKING_DIRECTORY "${dir}"
+      RESULT_VARIABLE download_result
+      ${logging_params}
+  )
+
+  if(NOT download_result EQUAL 0)
+    hunter_gate_internal_error("Build project failed")
+  endif()
+
+  file(REMOVE_RECURSE "${build_dir}")
+  file(REMOVE_RECURSE "${cmakelists}")
+
+  file(WRITE "${sha1_location}" "${HUNTER_GATE_SHA1}")
+  file(WRITE "${done_location}" "DONE")
+
+  hunter_gate_status_debug("Finished")
+endfunction()
+
+# Must be a macro so master file 'cmake/Hunter' can
+# apply all variables easily just by 'include' command
+# (otherwise PARENT_SCOPE magic needed)
+macro(HunterGate)
+  if(HUNTER_GATE_DONE)
+    # variable HUNTER_GATE_DONE set explicitly for external project
+    # (see `hunter_download`)
+    set_property(GLOBAL PROPERTY HUNTER_GATE_DONE YES)
+  endif()
+
+  # First HunterGate command will init Hunter, others will be ignored
+  get_property(_hunter_gate_done GLOBAL PROPERTY HUNTER_GATE_DONE SET)
+
+  if(NOT HUNTER_ENABLED)
+    # Empty function to avoid error "unknown function"
+    function(hunter_add_package)
+    endfunction()
+  elseif(_hunter_gate_done)
+    hunter_gate_status_debug("Secondary HunterGate (use old settings)")
+    hunter_gate_self(
+        "${HUNTER_CACHED_ROOT}"
+        "${HUNTER_VERSION}"
+        "${HUNTER_SHA1}"
+        _hunter_self
+    )
+    include("${_hunter_self}/cmake/Hunter")
+  else()
+    set(HUNTER_GATE_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
+
+    string(COMPARE NOTEQUAL "${PROJECT_NAME}" "" _have_project_name)
+    if(_have_project_name)
+      hunter_gate_fatal_error(
+          "Please set HunterGate *before* 'project' command. "
+          "Detected project: ${PROJECT_NAME}"
+          WIKI "error.huntergate.before.project"
+      )
+    endif()
+
+    cmake_parse_arguments(
+        HUNTER_GATE "LOCAL" "URL;SHA1;GLOBAL;FILEPATH" "" ${ARGV}
+    )
+
+    string(COMPARE EQUAL "${HUNTER_GATE_SHA1}" "" _empty_sha1)
+    string(COMPARE EQUAL "${HUNTER_GATE_URL}" "" _empty_url)
+    string(
+        COMPARE
+        NOTEQUAL
+        "${HUNTER_GATE_UNPARSED_ARGUMENTS}"
+        ""
+        _have_unparsed
+    )
+    string(COMPARE NOTEQUAL "${HUNTER_GATE_GLOBAL}" "" _have_global)
+    string(COMPARE NOTEQUAL "${HUNTER_GATE_FILEPATH}" "" _have_filepath)
+
+    if(_have_unparsed)
+      hunter_gate_user_error(
+          "HunterGate unparsed arguments: ${HUNTER_GATE_UNPARSED_ARGUMENTS}"
+      )
+    endif()
+    if(_empty_sha1)
+      hunter_gate_user_error("SHA1 suboption of HunterGate is mandatory")
+    endif()
+    if(_empty_url)
+      hunter_gate_user_error("URL suboption of HunterGate is mandatory")
+    endif()
+    if(_have_global)
+      if(HUNTER_GATE_LOCAL)
+        hunter_gate_user_error("Unexpected LOCAL (already has GLOBAL)")
+      endif()
+      if(_have_filepath)
+        hunter_gate_user_error("Unexpected FILEPATH (already has GLOBAL)")
+      endif()
+    endif()
+    if(HUNTER_GATE_LOCAL)
+      if(_have_global)
+        hunter_gate_user_error("Unexpected GLOBAL (already has LOCAL)")
+      endif()
+      if(_have_filepath)
+        hunter_gate_user_error("Unexpected FILEPATH (already has LOCAL)")
+      endif()
+    endif()
+    if(_have_filepath)
+      if(_have_global)
+        hunter_gate_user_error("Unexpected GLOBAL (already has FILEPATH)")
+      endif()
+      if(HUNTER_GATE_LOCAL)
+        hunter_gate_user_error("Unexpected LOCAL (already has FILEPATH)")
+      endif()
+    endif()
+
+    hunter_gate_detect_root() # set HUNTER_GATE_ROOT
+
+    # Beautify path, fix probable problems with windows path slashes
+    get_filename_component(
+        HUNTER_GATE_ROOT "${HUNTER_GATE_ROOT}" ABSOLUTE
+    )
+    hunter_gate_status_debug("HUNTER_ROOT: ${HUNTER_GATE_ROOT}")
+    if(NOT HUNTER_ALLOW_SPACES_IN_PATH)
+      string(FIND "${HUNTER_GATE_ROOT}" " " _contain_spaces)
+      if(NOT _contain_spaces EQUAL -1)
+        hunter_gate_fatal_error(
+            "HUNTER_ROOT (${HUNTER_GATE_ROOT}) contains spaces."
+            "Set HUNTER_ALLOW_SPACES_IN_PATH=ON to skip this error"
+            "(Use at your own risk!)"
+            WIKI "error.spaces.in.hunter.root"
+        )
+      endif()
+    endif()
+
+    string(
+        REGEX
+        MATCH
+        "[0-9]+\\.[0-9]+\\.[0-9]+[-_a-z0-9]*"
+        HUNTER_GATE_VERSION
+        "${HUNTER_GATE_URL}"
+    )
+    string(COMPARE EQUAL "${HUNTER_GATE_VERSION}" "" _is_empty)
+    if(_is_empty)
+      set(HUNTER_GATE_VERSION "unknown")
+    endif()
+
+    hunter_gate_self(
+        "${HUNTER_GATE_ROOT}"
+        "${HUNTER_GATE_VERSION}"
+        "${HUNTER_GATE_SHA1}"
+        _hunter_self
+    )
+
+    set(_master_location "${_hunter_self}/cmake/Hunter")
+    if(EXISTS "${HUNTER_GATE_ROOT}/cmake/Hunter")
+      # Hunter downloaded manually (e.g. by 'git clone')
+      set(_unused "xxxxxxxxxx")
+      set(HUNTER_GATE_SHA1 "${_unused}")
+      set(HUNTER_GATE_VERSION "${_unused}")
+    else()
+      get_filename_component(_archive_id_location "${_hunter_self}/.." ABSOLUTE)
+      set(_done_location "${_archive_id_location}/DONE")
+      set(_sha1_location "${_archive_id_location}/SHA1")
+
+      # Check Hunter already downloaded by HunterGate
+      if(NOT EXISTS "${_done_location}")
+        hunter_gate_download("${_archive_id_location}")
+      endif()
+
+      if(NOT EXISTS "${_done_location}")
+        hunter_gate_internal_error("hunter_gate_download failed")
+      endif()
+
+      if(NOT EXISTS "${_sha1_location}")
+        hunter_gate_internal_error("${_sha1_location} not found")
+      endif()
+      file(READ "${_sha1_location}" _sha1_value)
+      string(COMPARE EQUAL "${_sha1_value}" "${HUNTER_GATE_SHA1}" _is_equal)
+      if(NOT _is_equal)
+        hunter_gate_internal_error(
+            "Short SHA1 collision:"
+            "  ${_sha1_value} (from ${_sha1_location})"
+            "  ${HUNTER_GATE_SHA1} (HunterGate)"
+        )
+      endif()
+      if(NOT EXISTS "${_master_location}")
+        hunter_gate_user_error(
+            "Master file not found:"
+            "  ${_master_location}"
+            "try to update Hunter/HunterGate"
+        )
+      endif()
+    endif()
+    include("${_master_location}")
+    set_property(GLOBAL PROPERTY HUNTER_GATE_DONE YES)
+  endif()
+endmacro()
\ No newline at end of file
diff --git a/cmake/sanitize-helpers.cmake b/cmake/sanitize-helpers.cmake
new file mode 100644
index 0000000..6f3decd
--- /dev/null
+++ b/cmake/sanitize-helpers.cmake
@@ -0,0 +1,170 @@
+# The MIT License (MIT)
+#
+# Copyright (c)
+#   2013 Matthew Arsenault
+#   2015-2016 RWTH Aachen University, Federal Republic of Germany
+#
+# 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.
+
+# Helper function to get the language of a source file.
+function (sanitizer_lang_of_source FILE RETURN_VAR)
+    get_filename_component(FILE_EXT "${FILE}" EXT)
+    string(TOLOWER "${FILE_EXT}" FILE_EXT)
+    string(SUBSTRING "${FILE_EXT}" 1 -1 FILE_EXT)
+
+    get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
+    foreach (LANG ${ENABLED_LANGUAGES})
+        list(FIND CMAKE_${LANG}_SOURCE_FILE_EXTENSIONS "${FILE_EXT}" TEMP)
+        if (NOT ${TEMP} EQUAL -1)
+            set(${RETURN_VAR} "${LANG}" PARENT_SCOPE)
+            return()
+        endif ()
+    endforeach()
+
+    set(${RETURN_VAR} "" PARENT_SCOPE)
+endfunction ()
+
+
+# Helper function to get compilers used by a target.
+function (sanitizer_target_compilers TARGET RETURN_VAR)
+    # Check if all sources for target use the same compiler. If a target uses
+    # e.g. C and Fortran mixed and uses different compilers (e.g. clang and
+    # gfortran) this can trigger huge problems, because different compilers may
+    # use different implementations for sanitizers.
+    set(BUFFER "")
+    get_target_property(TSOURCES ${TARGET} SOURCES)
+    foreach (FILE ${TSOURCES})
+        # If expression was found, FILE is a generator-expression for an object
+        # library. Object libraries will be ignored.
+        string(REGEX MATCH "TARGET_OBJECTS:([^ >]+)" _file ${FILE})
+        if ("${_file}" STREQUAL "")
+            sanitizer_lang_of_source(${FILE} LANG)
+            if (LANG)
+                list(APPEND BUFFER ${CMAKE_${LANG}_COMPILER_ID})
+            endif ()
+        endif ()
+    endforeach ()
+
+    list(REMOVE_DUPLICATES BUFFER)
+    set(${RETURN_VAR} "${BUFFER}" PARENT_SCOPE)
+endfunction ()
+
+
+# Helper function to check compiler flags for language compiler.
+function (sanitizer_check_compiler_flag FLAG LANG VARIABLE)
+    if (${LANG} STREQUAL "C")
+        include(CheckCCompilerFlag)
+        check_c_compiler_flag("${FLAG}" ${VARIABLE})
+
+    elseif (${LANG} STREQUAL "CXX")
+        include(CheckCXXCompilerFlag)
+        check_cxx_compiler_flag("${FLAG}" ${VARIABLE})
+
+    elseif (${LANG} STREQUAL "Fortran")
+        # CheckFortranCompilerFlag was introduced in CMake 3.x. To be compatible
+        # with older Cmake versions, we will check if this module is present
+        # before we use it. Otherwise we will define Fortran coverage support as
+        # not available.
+        include(CheckFortranCompilerFlag OPTIONAL RESULT_VARIABLE INCLUDED)
+        if (INCLUDED)
+            check_fortran_compiler_flag("${FLAG}" ${VARIABLE})
+        elseif (NOT CMAKE_REQUIRED_QUIET)
+            message(STATUS "Performing Test ${VARIABLE}")
+            message(STATUS "Performing Test ${VARIABLE}"
+                " - Failed (Check not supported)")
+        endif ()
+    endif()
+endfunction ()
+
+
+# Helper function to test compiler flags.
+function (sanitizer_check_compiler_flags FLAG_CANDIDATES NAME PREFIX)
+    set(CMAKE_REQUIRED_QUIET ${${PREFIX}_FIND_QUIETLY})
+
+    get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
+    foreach (LANG ${ENABLED_LANGUAGES})
+        # Sanitizer flags are not dependend on language, but the used compiler.
+        # So instead of searching flags foreach language, search flags foreach
+        # compiler used.
+        set(COMPILER ${CMAKE_${LANG}_COMPILER_ID})
+        if (NOT DEFINED ${PREFIX}_${COMPILER}_FLAGS)
+            foreach (FLAG ${FLAG_CANDIDATES})
+                if(NOT CMAKE_REQUIRED_QUIET)
+                    message(STATUS "Try ${COMPILER} ${NAME} flag = [${FLAG}]")
+                endif()
+
+                set(CMAKE_REQUIRED_FLAGS "${FLAG}")
+                unset(${PREFIX}_FLAG_DETECTED CACHE)
+                sanitizer_check_compiler_flag("${FLAG}" ${LANG}
+                    ${PREFIX}_FLAG_DETECTED)
+
+                if (${PREFIX}_FLAG_DETECTED)
+                    # If compiler is a GNU compiler, search for static flag, if
+                    # SANITIZE_LINK_STATIC is enabled.
+                    if (SANITIZE_LINK_STATIC AND (${COMPILER} STREQUAL "GNU"))
+                        string(TOLOWER ${PREFIX} PREFIX_lower)
+                        sanitizer_check_compiler_flag(
+                            "-static-lib${PREFIX_lower}" ${LANG}
+                            ${PREFIX}_STATIC_FLAG_DETECTED)
+
+                        if (${PREFIX}_STATIC_FLAG_DETECTED)
+                            set(FLAG "-static-lib${PREFIX_lower} ${FLAG}")
+                        endif ()
+                    endif ()
+
+                    set(${PREFIX}_${COMPILER}_FLAGS "${FLAG}" CACHE STRING
+                        "${NAME} flags for ${COMPILER} compiler.")
+                    mark_as_advanced(${PREFIX}_${COMPILER}_FLAGS)
+                    break()
+                endif ()
+            endforeach ()
+
+            if (NOT ${PREFIX}_FLAG_DETECTED)
+                set(${PREFIX}_${COMPILER}_FLAGS "" CACHE STRING
+                    "${NAME} flags for ${COMPILER} compiler.")
+                mark_as_advanced(${PREFIX}_${COMPILER}_FLAGS)
+
+                message(WARNING "${NAME} is not available for ${COMPILER} "
+                        "compiler. Targets using this compiler will be "
+                        "compiled without ${NAME}.")
+            endif ()
+        endif ()
+    endforeach ()
+endfunction ()
+
+
+# Helper to assign sanitizer flags for TARGET.
+function (saitizer_add_flags TARGET NAME PREFIX)
+    # Get list of compilers used by target and check, if sanitizer is available
+    # for this target. Other compiler checks like check for conflicting
+    # compilers will be done in add_sanitizers function.
+    sanitizer_target_compilers(${TARGET} TARGET_COMPILER)
+    list(LENGTH TARGET_COMPILER NUM_COMPILERS)
+    if ("${${PREFIX}_${TARGET_COMPILER}_FLAGS}" STREQUAL "")
+        return()
+    endif()
+
+    # Set compile- and link-flags for target.
+    set_property(TARGET ${TARGET} APPEND_STRING
+        PROPERTY COMPILE_FLAGS " ${${PREFIX}_${TARGET_COMPILER}_FLAGS}")
+    set_property(TARGET ${TARGET} APPEND_STRING
+        PROPERTY COMPILE_FLAGS " ${SanBlist_${TARGET_COMPILER}_FLAGS}")
+    set_property(TARGET ${TARGET} APPEND_STRING
+        PROPERTY LINK_FLAGS " ${${PREFIX}_${TARGET_COMPILER}_FLAGS}")
+endfunction ()