summaryrefslogtreecommitdiff
path: root/include/memory.hpp
diff options
context:
space:
mode:
authorDominick Allen <djallen@librehumanitas.org>2024-09-22 10:19:15 -0500
committerDominick Allen <djallen@librehumanitas.org>2024-09-22 10:19:15 -0500
commitbf81e34921e3e30b05313efbcf5c9fa839cb7c05 (patch)
treeb56a343e59164bc347232669e8bb808cf3c4f4ef /include/memory.hpp
Initial commit.
Diffstat (limited to 'include/memory.hpp')
-rw-r--r--include/memory.hpp140
1 files changed, 140 insertions, 0 deletions
diff --git a/include/memory.hpp b/include/memory.hpp
new file mode 100644
index 0000000..1ca6029
--- /dev/null
+++ b/include/memory.hpp
@@ -0,0 +1,140 @@
+/*
+ * 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 MEMORY_HPP
+#define MEMORY_HPP
+
+#include "result.hpp"
+#include "status.hpp"
+
+#include <cstddef>
+#include <cstdint>
+#include <type_traits>
+
+namespace fud {
+
+// 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);
+
+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