/** This file is a part of rexy's general purpose library Copyright (C) 2020 rexy712 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef REXY_UTILITY_HPP #define REXY_UTILITY_HPP #include //forward, move #include //size_t #include #include //strlen, strcmp, memcpy #include //wcslen #include //char_traits #include "compat/if_consteval.hpp" #include "rexy.hpp" namespace rexy{ namespace{ template constexpr void swap(T& l, T& r) noexcept(std::is_nothrow_move_assignable::value && std::is_nothrow_move_constructible::value) { T tmp = std::move(l); l = std::move(r); r = std::move(tmp); } template constexpr Iter2 swap_ranges(Iter1 start1, Iter1 end1, Iter2 start2) noexcept(noexcept(swap(*start1, *start2))) { while(start1 != end1){ swap(start1++, start2++); } return start2; } template constexpr void swap(T (&l)[N], T (&r)[N]) noexcept(noexcept(swap(*l, *r))) { swap_ranges(l, l+N, r); } template constexpr T exchange(T& l, U&& r) noexcept(std::is_nothrow_assignable::value && std::is_nothrow_move_assignable::value) { T old = std::move(l); l = std::forward(r); return old; } template constexpr const T& min(const T& l, const T& r)noexcept{ return l < r ? l : r; } template constexpr const T& min(const T& l, const T& r, Compare cmp) noexcept(std::is_nothrow_invocable::value) { return cmp(l, r) ? l : r; } template constexpr const T& max(const T& l, const T& r)noexcept{ return l > r ? l : r; } template constexpr const T& max(const T& l, const T& r, Compare cmp) noexcept(std::is_nothrow_invocable::value) { return cmp(l, r) ? l : r; } template constexpr T abs(const T& val){ return val > 0 ? val : -val; } #ifdef REXY_if_consteval template constexpr std::size_t strlen(const T* c)noexcept{ return std::char_traits::length(c); } template constexpr int strcmp(const T* l, const T* r)noexcept{ REXY_if_not_consteval{ if constexpr(std::is_same_v,char>){ return std::strcmp(l, r); }else if constexpr(std::is_same_v,wchar_t>){ return std::wcscmp(l, r); } } for(;*l == *r && *l;++l, ++r); return *l - *r; } template constexpr int strncmp(const T* l, const T* r, std::size_t max)noexcept{ REXY_if_not_consteval{ if constexpr(std::is_same_v,char>){ return std::strncmp(l, r, max); }else if constexpr (std::is_same_v,wchar_t>){ return std::wcsncmp(l, r, max); } } for(std::size_t i = 1;*l == *r && *l && i < max;++i, ++l, ++r); return *l - *r; } template constexpr int strncmp(const T* l, const T* r, std::size_t max, Compare cmp)noexcept{ REXY_if_not_consteval{ if constexpr(std::is_same_v,char>){ return std::strncmp(l, r, max); }else if constexpr (std::is_same_v,wchar_t>){ return std::wcsncmp(l, r, max); } } for(std::size_t i = 1;cmp(l, r) && *l && i < max;++i, ++l, ++r); return *l - *r; } template constexpr int strcmp(const T* l, const T* r, Compare cmp)noexcept{ for(;cmp(*l, *r) && *l;++l, ++r); return *l - *r; } constexpr void memcpy(void* l, const void* r, std::size_t n){ REXY_if_not_consteval{ std::memcpy(l, r, n); }else{ char* ld = static_cast(l); const char* rd = static_cast(r); for(std::size_t i = 0;i < n;++i){ ld[i] = rd[i]; } } } } #else // REXY_if_consteval template constexpr std::size_t strlen(const T* c)noexcept{ std::size_t i = 0; for(;c[i];++i); return i; } template constexpr int strcmp(const T* l, const T* r)noexcept{ for(;*l == *r && *l;++l, ++r); return *l - *r; } template constexpr int strcmp(const T* l, const T* r, Compare cmp)noexcept{ for(;cmp(*l, *r) && *l;++l, ++r); return *l - *r; } template constexpr int strncmp(const T* l, const T* r, std::size_t max)noexcept{ for(std::size_t i = 0;*l == *r && *l && i < max;++i, ++l, ++r); return *l - *r; } constexpr void memcpy(void* l, const void* r, std::size_t n){ char* ld = static_cast(l); const char* rd = static_cast(r); for(std::size_t i = 0;i < n;++i){ ld[i] = rd[i]; } } } #endif // REXY_if_consteval } #endif