// Copyright (C) 2023 RozK // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero 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 Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #ifndef RK_ENGINE_CMP_MEMCPY_H #define RK_ENGINE_CMP_MEMCPY_H #include "types.hpp" template bool _rk_cmp_memcpy_small( void * const __restrict _dst, void const * const __restrict _src, unsigned const size) { unsigned count = (size / sizeof(_type)); _type * dst = reinterpret_cast<_type *>(_dst); _type const * src = reinterpret_cast<_type const *>(_src); _type cmp = 0; do { cmp |= *dst ^ *src; *dst++ = *src++; } while(--count > 0); return (cmp != 0); } template bool _rk_cmp_memcpy_big( void * const __restrict _dst, void const * const __restrict _src, unsigned const size) { unsigned count = size / sizeof(_big); unsigned const remain = size % sizeof(_big); _big * dst = reinterpret_cast<_big *>(_dst); _big const * src = reinterpret_cast<_big const *>(_src); _big cmp = 0; do { cmp |= *dst ^ *src; *dst++ = *src++; } while(--count > 0); bool modified = (cmp != 0); if (remain) { modified |= _rk_cmp_memcpy_small<_small>(dst, src, remain); } return modified; } #ifdef RK_CMP_MEMCPY_UNALIGNED #define _rk_size_and_alignment(_t) (size >= sizeof(_t)) #else #define _rk_size_and_alignment(_t) (size >= sizeof(_t) && !(alignment & (sizeof(_t) - 1))) #endif template bool rk_cmp_memcpy( void * const __restrict _dst, void const * const __restrict _src, unsigned const size); template<> bool rk_cmp_memcpy( void * const __restrict _dst, void const * const __restrict _src, unsigned const size) { #ifndef RK_CMP_MEMCPY_UNALIGNED unsigned const alignment = reinterpret_cast(_dst) | reinterpret_cast(_src); #endif if (_rk_size_and_alignment(rk_ullong)) { return _rk_cmp_memcpy_big(_dst, _src, size); } if (_rk_size_and_alignment(rk_ulong)) { return _rk_cmp_memcpy_big(_dst, _src, size); } if (_rk_size_and_alignment(rk_uint)) { return _rk_cmp_memcpy_big(_dst, _src, size); } if (_rk_size_and_alignment(rk_ushort)) { return _rk_cmp_memcpy_big(_dst, _src, size); } if (size > 0) { return _rk_cmp_memcpy_small(_dst, _src, size); } return false; } template<> bool rk_cmp_memcpy( void * const __restrict _dst, void const * const __restrict _src, unsigned const size) { #ifndef RK_CMP_MEMCPY_UNALIGNED unsigned const alignment = reinterpret_cast(_dst) | reinterpret_cast(_src); #endif if (_rk_size_and_alignment(rk_ullong)) { return _rk_cmp_memcpy_big(_dst, _src, size); } if (_rk_size_and_alignment(rk_ulong)) { return _rk_cmp_memcpy_big(_dst, _src, size); } if (_rk_size_and_alignment(rk_uint)) { return _rk_cmp_memcpy_big(_dst, _src, size); } if (size > 0) { return _rk_cmp_memcpy_small(_dst, _src, size); } return false; } template<> bool rk_cmp_memcpy( void * const __restrict _dst, void const * const __restrict _src, unsigned const size) { #ifndef RK_CMP_MEMCPY_UNALIGNED unsigned const alignment = reinterpret_cast(_dst) | reinterpret_cast(_src); #endif if (_rk_size_and_alignment(rk_ullong)) { return _rk_cmp_memcpy_big(_dst, _src, size); } if (_rk_size_and_alignment(rk_ulong)) { return _rk_cmp_memcpy_big(_dst, _src, size); } if (size > 0) { return _rk_cmp_memcpy_small(_dst, _src, size); } return false; } template<> bool rk_cmp_memcpy( void * const __restrict _dst, void const * const __restrict _src, unsigned const size) { #ifndef RK_CMP_MEMCPY_UNALIGNED unsigned const alignment = reinterpret_cast(_dst) | reinterpret_cast(_src); #endif if (_rk_size_and_alignment(rk_ullong)) { return _rk_cmp_memcpy_big(_dst, _src, size); } if (size > 0) { return _rk_cmp_memcpy_small(_dst, _src, size); } return false; } template<> bool rk_cmp_memcpy( void * const __restrict _dst, void const * const __restrict _src, unsigned const size) { if (size > 0) { return _rk_cmp_memcpy_small(_dst, _src, size); } return false; } #undef _rk_size_and_alignment #endif // RK_ENGINE_CMP_MEMCPY_H