Fri, 05 Feb 2021 11:36:38 +0200
refactor
/* Copyright 2014 - 2021 Teemu Piippo All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 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. */ #pragma once #include <cassert> #include <cstdlib> #include <type_traits> #if !defined(_MSC_VER) && !defined(__cdecl) # define __cdecl #endif #define MACRO_TO_STRING_2(A) #A #define MACRO_TO_STRING(A) MACRO_TO_STRING_2(A) // The Windows SDK appears to use identifiers that conflicts with the identifiers defined in ZFC, // so they have to be put in a namespace. #define BEGIN_ZFC_NAMESPACE namespace zfc { #define END_ZFC_NAMESPACE } // Goddamnit, MSVC #ifdef _MSC_VER # define and && # define or || # define not ! #endif #define TEXTCOLOR_Escape "\x1C" #define TEXTCOLOR_Black TEXTCOLOR_Escape "M" #define TEXTCOLOR_Gray TEXTCOLOR_Escape "U" #define TEXTCOLOR_Silver TEXTCOLOR_Escape "C" #define TEXTCOLOR_White TEXTCOLOR_Escape "J" #define TEXTCOLOR_Red TEXTCOLOR_Escape "R" #define TEXTCOLOR_BrightRed TEXTCOLOR_Escape "G" #define TEXTCOLOR_Green TEXTCOLOR_Escape "Q" #define TEXTCOLOR_BrightGreen TEXTCOLOR_Escape "D" #define TEXTCOLOR_Yellow TEXTCOLOR_Escape "K" #define TEXTCOLOR_BrightYellow TEXTCOLOR_Escape "F" #define TEXTCOLOR_Blue TEXTCOLOR_Escape "H" #define TEXTCOLOR_BrightBlue TEXTCOLOR_Escape "N" #define TEXTCOLOR_Magenta TEXTCOLOR_Escape "T" #define TEXTCOLOR_BrightCyan TEXTCOLOR_Escape "V" #define TEXTCOLOR_Reset TEXTCOLOR_Escape "-" #undef min #undef max BEGIN_ZFC_NAMESPACE template<typename T, typename TT> constexpr std::common_type_t<T, TT> min(T a, TT b) { return (a < b) ? a : b; } template<typename ContainerType> typename ContainerType::value_type min(const ContainerType& container) { typename ContainerType::value_type result; for (typename ContainerType::value_type element : container) result = min(result, element); return result; } template<typename T, typename TT> constexpr std::common_type_t<T, TT> max(T a, TT b) { return (a > b) ? a : b; } template<typename ContainerType> typename ContainerType::value_type max(const ContainerType& container) { typename ContainerType::value_type result; for (typename ContainerType::value_type element : container) result = max(result, element); return result; } template<typename T, typename TT, typename TTT> constexpr std::common_type_t<T, TT, TTT> clamp(T a, TT b, TTT c) { return (a < b) ? b : (a > c) ? c : a; } inline const char *plural(int value) { return value != 1 ? "s" : ""; } template<typename T, std::size_t N> constexpr std::size_t countof(T(&)[N]) { return N; } #ifdef __GNUC__ # define GNUATTRIBUTE(X) __attribute__(X) #else # define GNUATTRIBUTE(X) #endif END_ZFC_NAMESPACE