Move cmp_memcpy into directory utils.
This commit is contained in:
99
cpp/utils/cmp_memcpy.hpp
Normal file
99
cpp/utils/cmp_memcpy.hpp
Normal file
@ -0,0 +1,99 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef RK_ENGINE_CMP_MEMCPY_H
|
||||
#define RK_ENGINE_CMP_MEMCPY_H
|
||||
|
||||
#include "../types.hpp"
|
||||
|
||||
template<typename _small>
|
||||
bool _rk_cmp_memcpy_small(
|
||||
_small * __restrict dst,
|
||||
_small const * __restrict src,
|
||||
unsigned count) {
|
||||
_small cmp = 0;
|
||||
do {
|
||||
cmp |= *dst ^ *src;
|
||||
*dst++ = *src++;
|
||||
} while(--count > 0);
|
||||
return (cmp != 0);
|
||||
}
|
||||
|
||||
template<typename _big, typename _small>
|
||||
bool _rk_cmp_memcpy_big(
|
||||
_small * const __restrict _dst,
|
||||
_small const * const __restrict _src,
|
||||
unsigned const _count) {
|
||||
unsigned const ratio = sizeof(_big) / sizeof(_small);
|
||||
unsigned big_count = _count / ratio;
|
||||
unsigned const small_count = _count % ratio;
|
||||
_big * dst = reinterpret_cast<_big *>(_dst);
|
||||
_big const * src = reinterpret_cast<_big const *>(_src);
|
||||
_big cmp = 0;
|
||||
do {
|
||||
cmp |= *dst ^ *src;
|
||||
*dst++ = *src++;
|
||||
} while(--big_count > 0);
|
||||
bool modified = (cmp != 0);
|
||||
if (small_count) {
|
||||
modified |= _rk_cmp_memcpy_small<_small>(
|
||||
reinterpret_cast<_small *>(dst), reinterpret_cast<_small const *>(src), small_count);
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
#ifdef RK_CMP_MEMCPY_UNALIGNED
|
||||
#define _rk_count_and_alignment(_t) (count >= (sizeof(_t) / sizeof(_small)))
|
||||
#else
|
||||
#define _rk_count_and_alignment(_t) ((count >= (sizeof(_t) / sizeof(_small))) && !(alignment % sizeof(_t)))
|
||||
#endif
|
||||
|
||||
template<typename _small>
|
||||
bool rk_cmp_memcpy(
|
||||
_small * const __restrict _dst,
|
||||
_small const * const __restrict _src,
|
||||
unsigned const count) {
|
||||
#ifndef RK_CMP_MEMCPY_UNALIGNED
|
||||
unsigned const alignment = reinterpret_cast<uintptr_t>(_dst) | reinterpret_cast<uintptr_t const>(_src);
|
||||
#endif
|
||||
if (sizeof(_small) < sizeof(rk_ullong)) {
|
||||
if (_rk_count_and_alignment(rk_ullong)) {
|
||||
return _rk_cmp_memcpy_big<rk_ullong, _small>(_dst, _src, count);
|
||||
}
|
||||
}
|
||||
if (sizeof(_small) < sizeof(rk_ulong)) {
|
||||
if (_rk_count_and_alignment(rk_ulong)) {
|
||||
return _rk_cmp_memcpy_big<rk_ulong, _small>(_dst, _src, count);
|
||||
}
|
||||
}
|
||||
if (sizeof(_small) < sizeof(rk_uint)) {
|
||||
if (_rk_count_and_alignment(rk_uint)) {
|
||||
return _rk_cmp_memcpy_big<rk_uint, _small>(_dst, _src, count);
|
||||
}
|
||||
}
|
||||
if (sizeof(_small) < sizeof(rk_ushort)) {
|
||||
if (_rk_count_and_alignment(rk_ushort)) {
|
||||
return _rk_cmp_memcpy_big<rk_ushort, _small>(_dst, _src, count);
|
||||
}
|
||||
}
|
||||
if (count) {
|
||||
return _rk_cmp_memcpy_small<_small>(_dst, _src, count);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#undef _rk_count_and_alignment
|
||||
|
||||
#endif // RK_ENGINE_CMP_MEMCPY_H
|
Reference in New Issue
Block a user