From 53c4dcf374c66f1e9190f5a62a52d02fe11a69e6 Mon Sep 17 00:00:00 2001 From: Dominick Allen Date: Wed, 16 Oct 2024 22:25:08 -0500 Subject: First crack at allocators. --- source/fud_allocator.cpp | 48 ++++++++++++++++++++++ source/fud_c_file.cpp | 24 ++++++++--- source/fud_directory.cpp | 98 +++++++++++++++++-------------------------- source/fud_sqlite.cpp | 5 ++- source/fud_string.cpp | 105 ++++++++++++++++++++++++++++++++--------------- source/libfud.cpp | 2 +- 6 files changed, 182 insertions(+), 100 deletions(-) create mode 100644 source/fud_allocator.cpp (limited to 'source') 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 FudAllocator::allocate(size_t bytes, size_t alignment) +{ + using RetType = Result; + static_cast(alignment); + auto* pointer = static_cast(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(bytes); + static_cast(alignment); + fudFree(pointer); +} + +bool FudAllocator::isEqual(const Allocator& rhs) const +{ + /* Is this legit? Or is this a bogus check? */ + return &rhs == static_cast(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::fromStat(const String& name, c break; } - return RetType::okay(DirectoryEntry{ - name, - statBuffer.st_ino, - size, - static_cast(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(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::make(const String& name) { - if (!m_name.valid()) { - return; + using RetType = Result; + 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 Directory::info() { using RetType = Result; - 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, FudStatus> Directory::getNextEntry() { using RetType = Result, 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, 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, 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, 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(lenResult); + if (output.m_length >= output.m_capacity) { output.m_capacity = output.m_length + 1; - data = static_cast(fudAlloc(output.m_capacity)); + auto dataResult{output.m_allocator->allocate(output.m_capacity)}; + if (dataResult.isError()) { + return StringResult::error(dataResult); + } + + data = static_cast(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(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(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(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(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(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(fudAlloc(output.m_capacity)); + auto ptrResult = m_allocator->allocate(output.m_capacity); + if (ptrResult.isError()) { + return StringResult::error(ptrResult.getError()); + } + destPtr = static_cast(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 getEnv(const char* name) return RetType::error(envVarResult); } - return RetType::okay(envVarResult); + return RetType::okay(std::move(envVarResult)); } } // namespace fud -- cgit v1.2.3