diff options
Diffstat (limited to 'include/fud_memory.hpp')
-rw-r--r-- | include/fud_memory.hpp | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/include/fud_memory.hpp b/include/fud_memory.hpp new file mode 100644 index 0000000..d6708cd --- /dev/null +++ b/include/fud_memory.hpp @@ -0,0 +1,150 @@ +/* + * libfud + * Copyright 2024 Dominick Allen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FUD_MEMORY_HPP +#define FUD_MEMORY_HPP + +#include "fud_result.hpp" +#include "fud_status.hpp" + +#include <cstddef> +#include <cstdint> +#include <type_traits> + +namespace fud { + +extern void* fudAlloc(size_t size); +extern void* fudRealloc(size_t size); +extern void fudFree(void* ptr); + +// An allocating function which returns null on failure. +using FudAllocOne = void(*)(size_t); + +// An allocating function which returns null on failure. +using FudAllocMany = void(*)(size_t, size_t); + +/** \brief Copies from source to destination count bytes. + * + * \retcode FudStatus::Success + * \retcode FudStatus::NullPointer if destination or source are null + * \retcode FudStatus::InvalidInput if destination_size < count + */ +FudStatus copyMem(void* destination, size_t destination_size, const void* source, size_t count); + +FudStatus compareMem(const void* lhs, size_t destination_size, const void* rhs, size_t count, int* difference); + +Result<int, FudStatus> compareMem(const void* lhs, size_t destination_size, const void* rhs, size_t count); + +FudStatus setMemory(void* data, size_t dataSize, uint8_t pattern, size_t count); + +FudStatus setMemory( + void* data, + size_t collectionCount, + size_t eltOffset, + size_t eltSize, + uint8_t pattern, + size_t eltCount); + +template <template <class, size_t> class Container, typename T, size_t Size> +constexpr void setMemory(Container<T, Size>& container, const T& value) +{ + for (auto& elt : container) { + elt = value; + } +} + +template <size_t Count, typename T, typename U> +void copyMem(T& destination, const U& source) +{ + static_assert(Count <= sizeof(U)); + static_assert(Count <= sizeof(T)); + static_assert(std::is_standard_layout_v<T>); + static_assert(std::is_standard_layout_v<U>); + + for (size_t idx = 0; idx < Count; ++idx) { + // NOLINTBEGIN(cppcoreguidelines-pro-type-reinterpret-cast) + reinterpret_cast<uint8_t*>(&destination)[idx] = reinterpret_cast<const uint8_t*>(&source)[idx]; + // NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast) + } +} + +template <typename T, typename U> +void copyMem(T& destination, const U& source) +{ + static_assert(sizeof(U) <= sizeof(T)); + + copyMem<sizeof(U)>(destination, source); +} + +template <size_t Count, typename T, typename U> +int compareMem(const T& lhs, const U& rhs) +{ + static_assert(Count <= sizeof(T)); + static_assert(Count <= sizeof(U)); + + int difference = 0; + for (size_t idx = 0; idx < Count; ++idx) { + // NOLINTBEGIN(cppcoreguidelines-pro-type-reinterpret-cast) + difference = reinterpret_cast<const uint8_t*>(&lhs)[idx] - reinterpret_cast<const uint8_t*>(&rhs)[idx]; + // NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast) + if (difference != 0) { + break; + } + } + + return difference; +} + +template <size_t Count, typename T, typename U> +int compareMem(const T& lhs, U&& rhs) +{ + static_assert(Count <= sizeof(T)); + static_assert(Count <= sizeof(U)); + + int difference = 0; + for (size_t idx = 0; idx < Count; ++idx) { + // NOLINTBEGIN(cppcoreguidelines-pro-type-reinterpret-cast) + difference = reinterpret_cast<const uint8_t*>(&lhs)[idx] - + reinterpret_cast<const uint8_t*>(&std::forward<U>(rhs))[idx]; + // NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast) + if (difference != 0) { + break; + } + } + + return difference; +} + +template <typename T, typename U> +int compareMem(const T& lhs, const U& rhs) +{ + static_assert(sizeof(U) == sizeof(T)); + + return compareMem<sizeof(U)>(lhs, rhs); +} + +template <typename T, typename U> +int compareMem(const T& lhs, U&& rhs) +{ + static_assert(sizeof(U) == sizeof(T)); + + return compareMem<sizeof(U)>(lhs, std::forward<U>(rhs)); +} + +} // namespace fud + +#endif |