summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorDominick Allen <djallen@librehumanitas.org>2024-10-27 09:04:05 -0500
committerDominick Allen <djallen@librehumanitas.org>2024-10-27 09:04:05 -0500
commitb8345246dcc2121bcb6d1515a9341789de20199f (patch)
tree4a25857512a90ff38e8a40166c54694b74920216 /include
parentf84b8259f6e980fed647d8e1ec0634f89ee59c06 (diff)
First crack at file objects.
Diffstat (limited to 'include')
-rw-r--r--include/fud_c_file.hpp11
-rw-r--r--include/fud_file.hpp168
-rw-r--r--include/fud_memory.hpp26
-rw-r--r--include/fud_status.hpp45
-rw-r--r--include/fud_string.hpp6
-rw-r--r--include/fud_string_view.hpp7
6 files changed, 238 insertions, 25 deletions
diff --git a/include/fud_c_file.hpp b/include/fud_c_file.hpp
index b54b044..197abd3 100644
--- a/include/fud_c_file.hpp
+++ b/include/fud_c_file.hpp
@@ -22,6 +22,7 @@
#include "fud_result.hpp"
#include "fud_status.hpp"
#include "fud_string.hpp"
+#include "fud_file.hpp"
#include <cstdint>
#include <cstdio>
@@ -82,16 +83,6 @@ constexpr const char* CTextFileModeFromFlags(CFileMode mode)
}
}
-struct [[nodiscard]] ReadResult {
- size_t bytesRead{0};
- FudStatus status{FudStatus::Success};
-};
-
-struct [[nodiscard]] WriteResult {
- size_t bytesWritten{0};
- FudStatus status{FudStatus::Success};
-};
-
namespace detail {
template <typename Derived>
diff --git a/include/fud_file.hpp b/include/fud_file.hpp
new file mode 100644
index 0000000..b468b4b
--- /dev/null
+++ b/include/fud_file.hpp
@@ -0,0 +1,168 @@
+/*
+ * 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_FILE_HPP
+#define FUD_FILE_HPP
+
+#include "fud_allocator.hpp"
+#include "fud_option.hpp"
+#include "fud_result.hpp"
+#include "fud_status.hpp"
+#include "fud_string_view.hpp"
+
+#include <fcntl.h>
+
+namespace fud {
+
+/** \brief Access Modes for File */
+enum class FileAccessMode : uint8_t
+{
+ Read = 0x01,
+ Write = 0x02,
+ ReadWrite = Read | Write
+};
+
+enum class OpenFlagEnum : uint32_t
+{
+ Append = O_APPEND,
+ Truncate = O_TRUNC,
+ CloseOnExec = O_CLOEXEC,
+ DataSync = O_DSYNC,
+ Direct = O_DIRECT,
+ NoAtime = O_NOATIME,
+ NonBlock = O_NONBLOCK,
+ FileSync = O_SYNC
+};
+
+class OpenFlags {
+ public:
+ using FlagType = std::underlying_type_t<OpenFlagEnum>;
+
+ constexpr OpenFlags() noexcept = default;
+ constexpr OpenFlags(const OpenFlags& rhs) noexcept = default;
+ constexpr OpenFlags(OpenFlags&& rhs) noexcept = default;
+ constexpr ~OpenFlags() noexcept = default;
+ constexpr OpenFlags& operator=(const OpenFlags& rhs) noexcept = default;
+ constexpr OpenFlags& operator=(OpenFlags&& rhs) noexcept = default;
+
+ constexpr OpenFlags(OpenFlagEnum mode) noexcept : m_mask{static_cast<FlagType>(mode)}
+ {
+ }
+
+ constexpr OpenFlags operator|(OpenFlags rhs) const noexcept
+ {
+ OpenFlags mode{*this};
+ mode.m_mask |= rhs.m_mask;
+ return mode;
+ }
+
+ constexpr OpenFlags& operator|=(OpenFlags rhs) noexcept
+ {
+ m_mask |= rhs.m_mask;
+ return *this;
+ }
+
+ constexpr OpenFlags& operator|=(OpenFlagEnum rhs) noexcept
+ {
+ m_mask |= static_cast<FlagType>(rhs);
+ return *this;
+ }
+
+ constexpr OpenFlags operator|(OpenFlagEnum rhs) const noexcept
+ {
+ OpenFlags mode{*this};
+ mode.m_mask |= static_cast<FlagType>(rhs);
+ return mode;
+ }
+
+ constexpr FlagType flags() const noexcept
+ {
+ return m_mask;
+ }
+
+ constexpr bool hasFlag(OpenFlagEnum flag) noexcept
+ {
+ return (m_mask & static_cast<FlagType>(flag)) != 0;
+ }
+
+ private:
+ FlagType m_mask{0};
+};
+
+constexpr OpenFlags operator|(OpenFlagEnum lhs, OpenFlagEnum rhs)
+{
+ OpenFlags mode{lhs};
+ return mode | rhs;
+}
+
+struct [[nodiscard]] ReadResult {
+ size_t bytesRead{0};
+ FudStatus status{FudStatus::Success};
+};
+
+struct [[nodiscard]] WriteResult {
+ size_t bytesWritten{0};
+ FudStatus status{FudStatus::Success};
+};
+
+class RegularFile;
+using FileResult = Result<RegularFile, FudStatus>;
+
+class RegularFile {
+ public:
+ static FileResult open(
+ StringView filename,
+ FileAccessMode mode,
+ OpenFlags flags,
+ Option<int> dirFdoption,
+ Allocator* allocator = &globalFudAllocator);
+
+ static FileResult create(
+ StringView filename,
+ FileAccessMode mode,
+ OpenFlags flags,
+ bool exclusive,
+ Option<int> dirFdOption,
+ Allocator* allocator = &globalFudAllocator);
+
+ FudStatus close();
+
+ private:
+ RegularFile() = default;
+
+ public:
+ RegularFile(const RegularFile& rhs) = delete;
+
+ RegularFile(RegularFile&& rhs) noexcept;
+
+ ~RegularFile();
+
+ RegularFile& operator=(const RegularFile& rhs) = delete;
+
+ RegularFile& operator=(RegularFile&& rhs) noexcept;
+
+ FudStatus take(RegularFile& rhs);
+
+ private:
+ int m_fd{-1};
+ FileAccessMode m_modeFlags{};
+ OpenFlags m_openFlags{};
+};
+
+} // namespace fud
+
+#endif
diff --git a/include/fud_memory.hpp b/include/fud_memory.hpp
index 6ce6312..6f6816f 100644
--- a/include/fud_memory.hpp
+++ b/include/fud_memory.hpp
@@ -73,6 +73,18 @@ constexpr void setMemory(Container<Size>& container, T&& value)
}
}
+template <typename T>
+constexpr void zeroObject(T& object)
+{
+ static_assert(std::is_standard_layout_v<T>);
+ static_assert(std::is_trivially_copyable_v<T>);
+
+ auto* objPtr = reinterpret_cast<uint8_t*>(&object);
+ for (size_t idx = 0; idx < sizeof(object); ++idx) {
+ objPtr[idx] = 0;
+ }
+}
+
template <size_t Count, typename T, typename U>
void copyMem(T& destination, const U& source)
{
@@ -80,11 +92,16 @@ void copyMem(T& destination, const U& source)
static_assert(Count <= sizeof(T));
static_assert(std::is_standard_layout_v<T>);
static_assert(std::is_standard_layout_v<U>);
+ static_assert(std::is_trivially_copyable_v<T>);
+ static_assert(std::is_trivially_copyable_v<U>);
+
+ // NOLINTBEGIN(cppcoreguidelines-pro-type-reinterpret-cast)
+ auto* destPtr = reinterpret_cast<char*>(&destination);
+ const auto* srcPtr = reinterpret_cast<const char*>(&source);
+ // NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast)
for (size_t idx = 0; idx < Count; ++idx) {
- // NOLINTBEGIN(cppcoreguidelines-pro-type-reinterpret-cast)
- reinterpret_cast<char*>(&destination)[idx] = reinterpret_cast<const char*>(&source)[idx];
- // NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast)
+ destPtr[idx] = srcPtr[idx];
}
}
@@ -126,8 +143,7 @@ int compareMem(const T& lhs, U&& rhs)
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*>(&uRhs)[idx];
+ difference = reinterpret_cast<const uint8_t*>(&lhs)[idx] - reinterpret_cast<const uint8_t*>(&uRhs)[idx];
// NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast)
if (difference != 0) {
break;
diff --git a/include/fud_status.hpp b/include/fud_status.hpp
index d57a9c5..f18c119 100644
--- a/include/fud_status.hpp
+++ b/include/fud_status.hpp
@@ -18,32 +18,59 @@
#ifndef FUD_STATUS_HPP
#define FUD_STATUS_HPP
+#include <cstdint>
+
namespace fud {
-enum class [[nodiscard]] FudStatus
+enum class [[nodiscard]] FudStatus : int32_t
{
+ /** \brief Indisputable success. */
Success = 0,
+ /** \brief Either partially succeeding, or failing in a recoverable way. */
Partial,
+ /** \brief Typically a major failure in an underlying system call. */
Failure,
+ /** \brief An argument passed in was a null pointer and is invalid. */
NullPointer,
+ /** \brief An argument passed in is in an invalid state or mismatches with other arguments. */
ArgumentInvalid,
- VariantInvalid,
+ /** \brief An handle to a managed object is not valid. */
+ HandleInvalid,
+ /** \brief An object is uninitialized or no longer valid. */
ObjectInvalid,
+ /** \brief A utf sequence in a string is invalid. */
Utf8Invalid,
+ /** \brief A string is not terminated or has a length field exceeding its capacity. */
StringInvalid,
+ /** \brief The requested operation on the object is not valid for its current state. */
OperationInvalid,
+ /** \brief An object which is to be initialized has already been initialized. */
AlreadyInitialized,
+ /** \brief A format string is invalid. */
FormatInvalid,
+ /** \brief A string being parsed as a number is out of range for the requested type. */
RangeError,
+ /** \brief The given index is not in range of a randomly accessible container. */
IndexInvalid,
+ /** \brief An object in a container already exists in the requested slot for a new object. */
Exists,
+ /** \brief An object in a container does not exist in the requested slot for an existing object. */
NotFound,
+ /** \brief A container is empty when something was expected to be present. */
Empty,
+ /** \brief A container is full when attempting to add something to it. */
Full,
+ /** \brief An operation requiring elevated permissions failed. */
+ PermissionDenied,
+ /** \brief Two or more objects overlap when they are expected to be distinct. */
Aliased,
+ /** \brief An requested allocation could not be completed. */
AllocFailure,
+ /** \brief An requested deallocation could not be completed. */
DeallocFailure,
+ /** \brief The function is not implemented, but is planned to be implemented. */
NotImplemented,
+ /** \brief The function or desired mode of action for a function is not supported. */
NotSupported
};
@@ -58,20 +85,20 @@ constexpr const char* FudStatusToString(FudStatus status)
return "Failure";
case FudStatus::NullPointer:
return "NullPointer";
- case FudStatus::StringInvalid:
- return "StringInvalid";
+ case FudStatus::ArgumentInvalid:
+ return "ArgumentInvalid";
+ case FudStatus::HandleInvalid:
+ return "HandleInvalid";
case FudStatus::ObjectInvalid:
return "ObjectInvalid";
+ case FudStatus::StringInvalid:
+ return "StringInvalid";
case FudStatus::OperationInvalid:
return "OperationInvalid";
- case FudStatus::ArgumentInvalid:
- return "ArgumentInvalid";
case FudStatus::Utf8Invalid:
return "Utf8Invalid";
case FudStatus::RangeError:
return "RangeError";
- case FudStatus::VariantInvalid:
- return "VariantInvalid";
case FudStatus::FormatInvalid:
return "FormatInvalid";
case FudStatus::AlreadyInitialized:
@@ -86,6 +113,8 @@ constexpr const char* FudStatusToString(FudStatus status)
return "Empty";
case FudStatus::Full:
return "Full";
+ case FudStatus::PermissionDenied:
+ return "PermissionDenied";
case FudStatus::Aliased:
return "Aliased";
case FudStatus::AllocFailure:
diff --git a/include/fud_string.hpp b/include/fud_string.hpp
index 0213524..df03ad9 100644
--- a/include/fud_string.hpp
+++ b/include/fud_string.hpp
@@ -90,7 +90,6 @@ class String {
}
String output{};
- auto* data = output.m_buffer.data();
output.m_length = totalLength;
output.m_allocator = allocator;
if (output.m_length >= output.m_capacity) {
@@ -103,10 +102,11 @@ class String {
output.m_data = static_cast<utf8*>(dataResult.getOkay());
}
+ auto* data = output.data();
size_t cumulativeLength = 0;
for (size_t idx = 0; idx < strPointers.size(); ++idx) {
const auto* cString = strPointers[idx];
- auto copyStatus = copyMem(data, output.m_capacity - cumulativeLength, cString, lengths[idx]);
+ auto copyStatus = copyMem(data + cumulativeLength, output.m_capacity - cumulativeLength, cString, lengths[idx]);
fudAssert(copyStatus == FudStatus::Success);
cumulativeLength += lengths[idx];
}
@@ -131,6 +131,8 @@ class String {
static StringResult from(const String& rhs);
+ static StringResult from(StringView view, Allocator* allocator = &globalFudAllocator);
+
FudStatus copy(const String& rhs);
[[nodiscard]] constexpr size_t length() const
diff --git a/include/fud_string_view.hpp b/include/fud_string_view.hpp
index 718b3d7..972630a 100644
--- a/include/fud_string_view.hpp
+++ b/include/fud_string_view.hpp
@@ -61,6 +61,13 @@ struct StringView {
explicit StringView(const String& fudString) noexcept;
+ template <size_t N>
+ constexpr static StringView cStringView(const char (&input)[N])
+ {
+ static_assert(N > 0);
+ return StringView{N, reinterpret_cast<const utf8*>(input)};
+ }
+
[[nodiscard]] constexpr size_t length() const
{
return m_length;