summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorDominick Allen <djallen@librehumanitas.org>2024-10-16 22:25:08 -0500
committerDominick Allen <djallen@librehumanitas.org>2024-10-16 22:25:08 -0500
commit53c4dcf374c66f1e9190f5a62a52d02fe11a69e6 (patch)
treeee40277c36fdba58fb06aca87b8ffa67ab5f8558 /source
parentf3ac764684c64fbdd2094853a80b23e570cd5d9c (diff)
First crack at allocators.
Diffstat (limited to 'source')
-rw-r--r--source/fud_allocator.cpp48
-rw-r--r--source/fud_c_file.cpp24
-rw-r--r--source/fud_directory.cpp98
-rw-r--r--source/fud_sqlite.cpp5
-rw-r--r--source/fud_string.cpp105
-rw-r--r--source/libfud.cpp2
6 files changed, 182 insertions, 100 deletions
diff --git a/source/fud_allocator.cpp b/source/fud_allocator.cpp
new file mode 100644
index 0000000..b5af593
--- /dev/null
+++ b/source/fud_allocator.cpp
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+#include "fud_allocator.hpp"
+
+namespace fud {
+
+Result<void*, FudStatus> FudAllocator::allocate(size_t bytes, size_t alignment)
+{
+ using RetType = Result<void*, FudStatus>;
+ static_cast<void>(alignment);
+ auto* pointer = static_cast<std::byte*>(fudAlloc(bytes));
+ if (pointer == nullptr) {
+ return RetType::error(FudStatus::AllocFailure);
+ }
+ return RetType::okay(pointer);
+}
+
+void FudAllocator::deallocate(void* pointer, size_t bytes, size_t alignment)
+{
+ static_cast<void>(bytes);
+ static_cast<void>(alignment);
+ fudFree(pointer);
+}
+
+bool FudAllocator::isEqual(const Allocator& rhs) const
+{
+ /* Is this legit? Or is this a bogus check? */
+ return &rhs == static_cast<const Allocator*>(this);
+}
+
+FudAllocator globalFudAllocator{};
+
+} // namespace fud
diff --git a/source/fud_c_file.cpp b/source/fud_c_file.cpp
index a63923a..15c57ab 100644
--- a/source/fud_c_file.cpp
+++ b/source/fud_c_file.cpp
@@ -30,7 +30,10 @@ CBinaryFileResult CBinaryFile::make(const String& filename, CFileMode mode)
}
CBinaryFile binaryFile{};
- binaryFile.m_filename = filename;
+ auto copyStatus = binaryFile.m_filename.copy(filename);
+ if (copyStatus != FudStatus::Success) {
+ return CBinaryFileResult::error(copyStatus);
+ }
binaryFile.m_mode = modeResult.takeOkay();
binaryFile.m_modeFlags = mode;
return CBinaryFileResult::okay(std::move(binaryFile));
@@ -41,13 +44,16 @@ CBinaryFileResult CBinaryFile::make(const String& filename, CFileMode mode, cons
if (!filename.valid()) {
return CBinaryFileResult::error(FudStatus::InvalidInput);
}
- auto modeResult{String::makeFromCString(CBinaryFileModeFromFlags(mode), extraFlags)};
+ auto modeResult{String::makeFromCStrings(CBinaryFileModeFromFlags(mode), extraFlags)};
if (modeResult.isError()) {
return CBinaryFileResult::error(modeResult);
}
CBinaryFile binaryFile{};
- binaryFile.m_filename = filename;
+ auto copyStatus = binaryFile.m_filename.copy(filename);
+ if (copyStatus != FudStatus::Success) {
+ return CBinaryFileResult::error(copyStatus);
+ }
binaryFile.m_mode = modeResult.takeOkay();
binaryFile.m_modeFlags = mode;
return CBinaryFileResult::okay(std::move(binaryFile));
@@ -92,7 +98,10 @@ CTextFileResult CTextFile::make(const String& filename, CFileMode mode)
}
CTextFile textFile{};
- textFile.m_filename = filename;
+ auto copyStatus = textFile.m_filename.copy(filename);
+ if (copyStatus != FudStatus::Success) {
+ return CTextFileResult::error(copyStatus);
+ }
textFile.m_mode = modeResult.takeOkay();
textFile.m_modeFlags = mode;
return CTextFileResult::okay(std::move(textFile));
@@ -103,13 +112,16 @@ CTextFileResult CTextFile::make(const String& filename, CFileMode mode, const ch
if (!filename.valid()) {
return CTextFileResult::error(FudStatus::InvalidInput);
}
- auto modeResult{String::makeFromCString(CTextFileModeFromFlags(mode), extraFlags)};
+ auto modeResult{String::makeFromCStrings(CTextFileModeFromFlags(mode), extraFlags)};
if (modeResult.isError()) {
return CTextFileResult::error(modeResult);
}
CTextFile textFile{};
- textFile.m_filename = filename;
+ auto copyStatus = textFile.m_filename.copy(filename);
+ if (copyStatus != FudStatus::Success) {
+ return CTextFileResult::error(copyStatus);
+ }
textFile.m_mode = modeResult.takeOkay();
textFile.m_modeFlags = mode;
return CTextFileResult::okay(std::move(textFile));
diff --git a/source/fud_directory.cpp b/source/fud_directory.cpp
index 1697692..318d7e6 100644
--- a/source/fud_directory.cpp
+++ b/source/fud_directory.cpp
@@ -72,48 +72,53 @@ Result<DirectoryEntry, FudStatus> DirectoryEntry::fromStat(const String& name, c
break;
}
- return RetType::okay(DirectoryEntry{
- name,
- statBuffer.st_ino,
- size,
- static_cast<size_t>(statBuffer.st_nlink),
- statBuffer.st_mtime,
- entryType});
+ DirectoryEntry entry{};
+ auto copyStatus = entry.name.copy(name);
+ if (copyStatus != FudStatus::Success) {
+ return RetType::error(copyStatus);
+ }
+ entry.inode = statBuffer.st_ino;
+ entry.size = size;
+ entry.links = static_cast<size_t>(statBuffer.st_nlink);
+ entry.modificationTime = statBuffer.st_mtime;
+ entry.entryType = entryType;
+ return RetType::okay(std::move(entry));
}
-Directory::Directory(const String& name) : m_name{name}
+Result<Directory, FudStatus> Directory::make(const String& name)
{
- if (!m_name.valid()) {
- return;
+ using RetType = Result<Directory, FudStatus>;
+ Directory directory{};
+ if (!name.valid()) {
+ return RetType::error(FudStatus::InvalidInput);
}
- if (!m_name.utf8Valid()) {
- m_status = FudStatus::Utf8Invalid;
- return;
+ if (!name.utf8Valid()) {
+ return RetType::error(FudStatus::Utf8Invalid);
}
- m_directory = opendir(m_name.c_str());
- if (m_directory == nullptr) {
- m_status = FudStatus::Failure;
- m_errorCode = errno;
- return;
+ auto copyResult = directory.m_name.copy(name);
+ if (copyResult != FudStatus::Success) {
+ return RetType::error(copyResult);
}
- m_dirFd = dirfd(m_directory);
- if (m_dirFd == -1) {
- m_status = FudStatus::Failure;
- m_errorCode = errno;
- closedir(m_directory);
- m_directory = nullptr;
- return;
+ directory.m_directory = opendir(name.c_str());
+ if (directory.m_directory == nullptr) {
+ return RetType::error(FudStatus::Failure);
}
- m_errorCode = 0;
- m_status = FudStatus::Success;
+ directory.m_dirFd = dirfd(directory.m_directory);
+ if (directory.m_dirFd == -1) {
+ closedir(directory.m_directory);
+ return RetType::error(FudStatus::Failure);
+ }
+
+ directory.m_errorCode = 0;
+ return RetType::okay(std::move(directory));
}
Directory::Directory(Directory&& rhs) noexcept :
- m_name{std::move(rhs.m_name)}, m_directory{rhs.m_directory}, m_dirFd{rhs.m_dirFd}
+ m_name{std::move(rhs.m_name)}, m_directory{rhs.m_directory}, m_errorCode{rhs.m_errorCode}, m_dirFd{rhs.m_dirFd}
{
rhs.m_directory = nullptr;
rhs.m_dirFd = -1;
@@ -127,35 +132,21 @@ Directory::~Directory()
}
}
-bool Directory::valid() const
-{
- return m_directory != nullptr && m_dirFd != -1;
-}
-
Result<DirectoryEntry, FudStatus> Directory::info()
{
using RetType = Result<DirectoryEntry, FudStatus>;
- if (!valid()) {
- m_status = FudStatus::ObjectInvalid;
- return RetType::error(m_status);
- }
-
Stat sBuffer{};
auto fStatus = fstat(m_dirFd, &sBuffer);
if (fStatus == -1) {
m_errorCode = errno;
- m_status = FudStatus::Failure;
- return RetType::error(m_status);
+ return RetType::error(FudStatus::Failure);
}
auto retValue = DirectoryEntry::fromStat(m_name, sBuffer);
if (retValue.isOkay()) {
m_errorCode = 0;
- m_status = FudStatus::Success;
- } else {
- m_status = retValue.getError();
}
return retValue;
@@ -165,18 +156,12 @@ Result<std::optional<DirectoryEntry>, FudStatus> Directory::getNextEntry()
{
using RetType = Result<std::optional<DirectoryEntry>, FudStatus>;
- if (!valid()) {
- m_status = FudStatus::ObjectInvalid;
- return RetType::error(m_status);
- }
-
errno = 0;
auto* dirEntry = readdir(m_directory);
if (dirEntry == nullptr) {
if (errno != 0) {
m_errorCode = errno;
- m_status = FudStatus::Failure;
- return RetType::error(m_status);
+ return RetType::error(FudStatus::Failure);
}
return RetType::okay(std::nullopt);
}
@@ -184,8 +169,7 @@ Result<std::optional<DirectoryEntry>, FudStatus> Directory::getNextEntry()
const char* entryNameCString = dirEntry->d_name;
if (entryNameCString == nullptr) {
m_errorCode = -1;
- m_status = FudStatus::NullPointer;
- return RetType::error(m_status);
+ return RetType::error(FudStatus::NullPointer);
}
m_errorCode = 0;
@@ -195,8 +179,7 @@ Result<std::optional<DirectoryEntry>, FudStatus> Directory::getNextEntry()
auto fStatus = fstatat(m_dirFd, entryNameCString, &sBuffer, flags);
if (fStatus == -1) {
m_errorCode = errno;
- m_status = FudStatus::Failure;
- return RetType::error(m_status);
+ return RetType::error(FudStatus::Failure);
}
auto entryNameResult = String::makeFromCString(entryNameCString);
@@ -207,23 +190,18 @@ Result<std::optional<DirectoryEntry>, FudStatus> Directory::getNextEntry()
if (retValue.isOkay()) {
m_errorCode = 0;
- m_status = FudStatus::Success;
return RetType::okay(retValue.takeOkay());
}
- m_status = retValue.getError();
return RetType::error(retValue.getError());
}
FudStatus Directory::reset()
{
- if (!valid()) {
- }
if (m_directory != nullptr) {
rewinddir(m_directory);
} else {
- m_status = FudStatus::ObjectInvalid;
- return m_status;
+ return FudStatus::ObjectInvalid;
}
return FudStatus::Success;
}
diff --git a/source/fud_sqlite.cpp b/source/fud_sqlite.cpp
index 449be8b..e13feee 100644
--- a/source/fud_sqlite.cpp
+++ b/source/fud_sqlite.cpp
@@ -22,7 +22,10 @@ namespace fud {
SqliteDbResult SqliteDb::make(const String& name, SqliteOpenMode mode, int extraFlags)
{
SqliteDb sqlDb{};
- sqlDb.m_name = name;
+ auto copyResult = sqlDb.m_name.copy(name);
+ if (copyResult != FudStatus::Success) {
+ return SqliteDbResult::error(copyResult);
+ }
sqlDb.m_mode = mode;
sqlDb.m_extraFlags = extraFlags;
auto status = sqlDb.initialize();
diff --git a/source/fud_string.cpp b/source/fud_string.cpp
index 82a9fe5..f33224a 100644
--- a/source/fud_string.cpp
+++ b/source/fud_string.cpp
@@ -48,22 +48,40 @@ ssize_t cStringLength(const char* str, size_t maxLength)
StringResult String::makeFromCString(const char* cString)
{
+ return makeFromCString(cString, &globalFudAllocator);
+}
+
+StringResult String::makeFromCString(const char* cString, Allocator* allocator)
+{
+ if (allocator == nullptr) {
+ return StringResult::error(FudStatus::NullPointer);
+ }
+
auto lenResult = cStringLength(cString);
if (lenResult < 0 || lenResult >= SSIZE_MAX) {
return StringResult::error(FudStatus::InvalidInput);
}
String output{};
+ output.m_allocator = allocator;
auto* data = output.m_buffer.data();
output.m_length = static_cast<size_t>(lenResult);
+
if (output.m_length >= output.m_capacity) {
output.m_capacity = output.m_length + 1;
- data = static_cast<utf8*>(fudAlloc(output.m_capacity));
+ auto dataResult{output.m_allocator->allocate(output.m_capacity)};
+ if (dataResult.isError()) {
+ return StringResult::error(dataResult);
+ }
+
+ data = static_cast<utf8*>(dataResult.takeOkay());
+
if (data == nullptr) {
return StringResult::error(FudStatus::AllocFailure);
}
output.m_data = data;
}
+
auto copyStatus = copyMem(data, output.m_capacity, cString, output.m_length);
fudAssert(copyStatus == FudStatus::Success);
auto terminateStatus = output.nullTerminate();
@@ -72,36 +90,42 @@ StringResult String::makeFromCString(const char* cString)
return StringResult::okay(std::move(output));
}
-StringResult String::makeFromUtf8(const utf8* utf8String)
+StringResult String::from(const String& rhs)
{
- // NOLINTBEGIN(cppcoreguidelines-pro-type-reinterpret-cast)
- return makeFromCString(reinterpret_cast<const char*>(utf8String));
- // NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast)
-}
+ if (!rhs.valid()) {
+ return StringResult::error(FudStatus::InvalidInput);
+ }
-String::String(const String& rhs) : m_length{rhs.m_length}, m_capacity{rhs.m_capacity}
-{
- if (rhs.valid()) {
- if (isLarge()) {
- m_data = static_cast<utf8*>(fudAlloc(m_capacity));
- fudAssert(m_data != nullptr);
+ String output{};
+ output.m_length = rhs.m_length;
+ output.m_capacity = rhs.m_capacity;
+ output.m_allocator = rhs.m_allocator;
+
+ if (rhs.isLarge()) {
+ auto dataResult = output.m_allocator->allocate(output.m_capacity);
+ if (dataResult.isError()) {
+ return StringResult::error(dataResult.getError());
}
- fudAssert(copyMem(data(), m_capacity, rhs.data(), m_length) == FudStatus::Success);
- fudAssert(nullTerminate() == FudStatus::Success);
+ output.m_data = static_cast<utf8*>(dataResult.getOkay());
+ fudAssert(output.m_data != nullptr);
}
+
+ auto copyResult = copyMem(output.data(), output.m_capacity, rhs.data(), output.m_length);
+ fudAssert(copyResult == FudStatus::Success);
+ auto nullTerminateStatus = output.nullTerminate();
+ fudAssert(nullTerminateStatus == FudStatus::Success);
+ return StringResult::okay(std::move(output));
}
-String::String(String&& rhs) noexcept : m_length{rhs.m_length}, m_capacity{rhs.m_capacity}
+String::String(String&& rhs) noexcept : m_length{rhs.m_length}, m_capacity{rhs.m_capacity}, m_allocator{rhs.m_allocator}
{
- if (isLarge()) {
- cleanup();
- }
if (rhs.isLarge()) {
m_data = rhs.m_data;
rhs.m_data = nullptr;
} else {
m_buffer = rhs.m_buffer;
- fudAssert(nullTerminate() == FudStatus::Success);
+ auto terminateStatus = nullTerminate();
+ fudAssert(terminateStatus == FudStatus::Success);
}
}
@@ -110,25 +134,37 @@ String::~String()
cleanup();
}
-String& String::operator=(const String& rhs)
+FudStatus String::copy(const String& rhs)
{
if (this == &rhs) {
- return *this;
+ return FudStatus::Success;
+ }
+
+ if (!rhs.valid()) {
+ return FudStatus::InvalidInput;
}
cleanup();
m_length = rhs.m_length;
m_capacity = rhs.m_capacity;
- if (rhs.valid()) {
- if (isLarge()) {
- m_data = static_cast<utf8*>(fudAlloc(m_capacity));
- fudAssert(m_data != nullptr);
+ m_allocator = rhs.m_allocator;
+
+ if (isLarge()) {
+ auto dataResult = m_allocator->allocate(m_capacity);
+ if (dataResult.isError()) {
+ return dataResult.getError();
}
- fudAssert(copyMem(data(), m_capacity, rhs.data(), m_length) == FudStatus::Success);
- fudAssert(nullTerminate() == FudStatus::Success);
+ m_data = static_cast<utf8*>(dataResult.getOkay());
+ fudAssert(m_data != nullptr);
}
- return *this;
+
+ auto copyResult = copyMem(data(), m_capacity, rhs.data(), m_length);
+ fudAssert(copyResult == FudStatus::Success);
+ auto nullTerminateStatus = nullTerminate();
+ fudAssert(nullTerminateStatus == FudStatus::Success);
+
+ return FudStatus::Success;
}
String& String::operator=(String&& rhs) noexcept
@@ -137,6 +173,7 @@ String& String::operator=(String&& rhs) noexcept
m_length = rhs.m_length;
m_capacity = rhs.m_capacity;
+ m_allocator = rhs.m_allocator;
if (rhs.isLarge()) {
m_data = rhs.m_data;
rhs.m_data = nullptr;
@@ -149,8 +186,8 @@ String& String::operator=(String&& rhs) noexcept
void String::cleanup()
{
- if (isLarge() && m_data != nullptr) {
- fudFree(m_data);
+ if (isLarge() && m_data != nullptr && m_allocator != nullptr) {
+ m_allocator->deallocate(m_data, m_capacity);
m_data = nullptr;
}
}
@@ -209,7 +246,7 @@ bool String::nullTerminated() const
bool String::valid() const
{
- return nullTerminated();
+ return m_allocator != nullptr && nullTerminated();
}
bool String::utf8Valid() const
@@ -416,7 +453,11 @@ StringResult String::catenate(const char* rhs) const
auto* destPtr = output.m_buffer.data();
if (output.m_length >= output.m_capacity) {
output.m_capacity = output.m_length + 1;
- destPtr = static_cast<utf8*>(fudAlloc(output.m_capacity));
+ auto ptrResult = m_allocator->allocate(output.m_capacity);
+ if (ptrResult.isError()) {
+ return StringResult::error(ptrResult.getError());
+ }
+ destPtr = static_cast<utf8*>(ptrResult.getOkay());
if (destPtr == nullptr) {
return StringResult::error(FudStatus::AllocFailure);
}
diff --git a/source/libfud.cpp b/source/libfud.cpp
index cec544d..538d3a9 100644
--- a/source/libfud.cpp
+++ b/source/libfud.cpp
@@ -55,7 +55,7 @@ Result<String, FudStatus> getEnv(const char* name)
return RetType::error(envVarResult);
}
- return RetType::okay(envVarResult);
+ return RetType::okay(std::move(envVarResult));
}
} // namespace fud