summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/fud_c_file.cpp12
-rw-r--r--source/fud_directory.cpp3
-rw-r--r--source/fud_file.cpp123
-rw-r--r--source/fud_string.cpp75
-rw-r--r--source/fud_utf8.cpp11
5 files changed, 159 insertions, 65 deletions
diff --git a/source/fud_c_file.cpp b/source/fud_c_file.cpp
index 9fc7734..bd90af7 100644
--- a/source/fud_c_file.cpp
+++ b/source/fud_c_file.cpp
@@ -21,9 +21,6 @@ namespace fud {
CBinaryFileResult CBinaryFile::make(const String& filename, CFileMode mode)
{
- if (!filename.valid()) {
- return CBinaryFileResult::error(FudStatus::ArgumentInvalid);
- }
auto modeResult{String::makeFromCString(CBinaryFileModeFromFlags(mode))};
if (modeResult.isError()) {
return CBinaryFileResult::error(modeResult);
@@ -41,9 +38,6 @@ CBinaryFileResult CBinaryFile::make(const String& filename, CFileMode mode)
CBinaryFileResult CBinaryFile::make(const String& filename, CFileMode mode, const char* extraFlags)
{
- if (!filename.valid()) {
- return CBinaryFileResult::error(FudStatus::ArgumentInvalid);
- }
auto modeResult{String::makeFromCStrings(CBinaryFileModeFromFlags(mode), extraFlags)};
if (modeResult.isError()) {
return CBinaryFileResult::error(modeResult);
@@ -89,9 +83,6 @@ CBinaryFile& CBinaryFile::operator=(CBinaryFile&& rhs) noexcept
CTextFileResult CTextFile::make(const String& filename, CFileMode mode)
{
- if (!filename.valid()) {
- return CTextFileResult::error(FudStatus::ArgumentInvalid);
- }
auto modeResult{String::makeFromCString(CBinaryFileModeFromFlags(mode))};
if (modeResult.isError()) {
return CTextFileResult::error(modeResult);
@@ -109,9 +100,6 @@ CTextFileResult CTextFile::make(const String& filename, CFileMode mode)
CTextFileResult CTextFile::make(const String& filename, CFileMode mode, const char* extraFlags)
{
- if (!filename.valid()) {
- return CTextFileResult::error(FudStatus::ArgumentInvalid);
- }
auto modeResult{String::makeFromCStrings(CTextFileModeFromFlags(mode), extraFlags)};
if (modeResult.isError()) {
return CTextFileResult::error(modeResult);
diff --git a/source/fud_directory.cpp b/source/fud_directory.cpp
index 1a1223c..1dc1aba 100644
--- a/source/fud_directory.cpp
+++ b/source/fud_directory.cpp
@@ -89,9 +89,6 @@ Result<Directory, FudStatus> Directory::make(const String& name)
{
using RetType = Result<Directory, FudStatus>;
Directory directory{};
- if (!name.valid()) {
- return RetType::error(FudStatus::ArgumentInvalid);
- }
if (!name.utf8Valid()) {
return RetType::error(FudStatus::Utf8Invalid);
diff --git a/source/fud_file.cpp b/source/fud_file.cpp
index e27a46d..8dab031 100644
--- a/source/fud_file.cpp
+++ b/source/fud_file.cpp
@@ -82,6 +82,7 @@ FileResult RegularFile::open(
return FudStatus::Partial;
case ENOENT:
return FudStatus::NotFound;
+ case EBADF:
case EFBIG:
case EOVERFLOW:
case EINVAL:
@@ -117,17 +118,100 @@ FileResult RegularFile::open(
return file;
}
-/*
- static FileResult RegularFile::create(
- StringView filename,
- FileAccessMode mode,
- OpenFlags flags,
- bool exclusive,
- Option<int> dirFdOption,
- Allocator* allocator = &globalFudAllocator);
+FileResult RegularFile::create(
+ StringView filename,
+ FileAccessMode mode,
+ OpenFlags flags,
+ Permissions permissions,
+ bool exclusive,
+ Option<int> dirFdOption,
+ Allocator* allocator)
{
+ if (allocator == nullptr) {
+ return FudStatus::NullPointer;
+ }
+
+ if (!filename.nullTerminated()) {
+ return FudStatus::ArgumentInvalid;
+ }
+
+ int dirFd = dirFdOption.valueOr(AT_FDCWD);
+
+ RegularFile file{};
+
+ uint32_t openFlags = 0;
+ switch (mode) {
+ case FileAccessMode::Read:
+ openFlags = O_RDONLY;
+ break;
+ case FileAccessMode::Write:
+ openFlags = O_WRONLY;
+ break;
+ case FileAccessMode::ReadWrite:
+ openFlags = O_RDWR;
+ break;
+ default:
+ return FudStatus::ArgumentInvalid;
+ }
+
+ if (flags.hasFlag(OpenFlagEnum::Append) && flags.hasFlag(OpenFlagEnum::Truncate)) {
+ return FudStatus::OperationInvalid;
+ }
+
+ openFlags |= flags.flags() | O_CREAT | (O_EXCL * static_cast<uint8_t>(exclusive));
+
+ open_how openHow{};
+ zeroObject(openHow);
+ openHow.flags = openFlags;
+ openHow.resolve = RESOLVE_NO_SYMLINKS;
+ openHow.mode = permissions.mode();
+
+ auto status = syscall(SYS_openat2, dirFd, filename.data(), &openHow, sizeof(openHow));
+ if (status == -1) {
+ if constexpr (EAGAIN != EWOULDBLOCK && status == EWOULDBLOCK) {
+ return FudStatus::Partial;
+ }
+ switch (errno) {
+ case ETXTBSY:
+ case EAGAIN:
+ return FudStatus::Partial;
+ case EBADF:
+ case EFBIG:
+ case EOVERFLOW:
+ case EINVAL:
+ case EISDIR:
+ case ENAMETOOLONG:
+ return FudStatus::ArgumentInvalid;
+ case EROFS:
+ case EACCES:
+ case EPERM:
+ return FudStatus::PermissionDenied;
+ case EDQUOT:
+ case ENOENT:
+ case ELOOP:
+ case EXDEV:
+ case ENFILE:
+ case E2BIG:
+ default:
+ return FudStatus::Failure;
+ }
+ }
+ fudAssert(status <= std::numeric_limits<decltype(file.m_fd)>::max());
+ file.m_fd = static_cast<decltype(file.m_fd)>(status);
+
+ using Stat = struct stat;
+ Stat sBuffer{};
+ auto fStatus = fstat(file.m_fd, &sBuffer);
+ if (fStatus == -1) {
+ return FudStatus::Failure;
+ }
+
+ if ((sBuffer.st_mode & S_IFMT) != S_IFREG) {
+ return FudStatus::ObjectInvalid;
+ }
+
+ return file;
}
-*/
RegularFile::~RegularFile()
{
@@ -198,4 +282,25 @@ FudStatus RegularFile::close()
return status;
}
+Result<size_t, FudStatus> RegularFile::size() const
+{
+ auto fileSize = lseek(m_fd, 0, SEEK_END);
+ if (fileSize == -1) {
+ switch (errno) {
+ case EBADF:
+ case ESPIPE:
+ return FudStatus::ObjectInvalid;
+ default:
+ return FudStatus::Failure;
+ }
+ }
+
+ auto seekBegin = lseek(m_fd, 0, SEEK_SET);
+ if (seekBegin == -1) {
+ return FudStatus::Failure;
+ }
+
+ return static_cast<size_t>(fileSize);
+}
+
} // namespace fud
diff --git a/source/fud_string.cpp b/source/fud_string.cpp
index caa35e9..58b6bd1 100644
--- a/source/fud_string.cpp
+++ b/source/fud_string.cpp
@@ -34,6 +34,10 @@ StringResult String::makeFromCString(const char* cString, Allocator* allocator)
return StringResult::error(FudStatus::NullPointer);
}
+ if (!String::allocatorValid(allocator)) {
+ return StringResult::error(FudStatus::ArgumentInvalid);
+ }
+
auto lenResult = cStringLength(cString);
if (lenResult < 0 || lenResult >= SSIZE_MAX) {
return StringResult::error(FudStatus::ArgumentInvalid);
@@ -46,11 +50,11 @@ StringResult String::makeFromCString(const char* cString, Allocator* allocator)
if (output.m_length >= output.m_capacity) {
output.m_capacity = output.m_length + 1;
- output.m_data = static_cast<utf8*>(M_TakeOrReturn(output.m_allocator->allocate(output.m_capacity)));
+ output.m_data = static_cast<utf8*>(M_TakeOrReturn(output.allocator()->allocate(output.m_capacity)));
fudAssert(output.m_data != nullptr);
}
- auto copyStatus = copyMem(output.data(), output.m_capacity, cString, output.m_length);
+ auto copyStatus = copyMem(output.dataMut(), output.m_capacity, cString, output.m_length);
fudAssert(copyStatus == FudStatus::Success);
auto terminateStatus = output.nullTerminate();
@@ -71,11 +75,11 @@ StringResult String::from(const String& rhs)
output.m_allocator = rhs.m_allocator;
if (rhs.isLarge()) {
- output.m_data = static_cast<utf8*>(M_TakeOrReturn(output.m_allocator->allocate(output.m_capacity)));
+ output.m_data = static_cast<utf8*>(M_TakeOrReturn(output.allocator()->allocate(output.m_capacity)));
fudAssert(output.m_data != nullptr);
}
- auto copyResult = copyMem(output.data(), output.m_capacity, rhs.data(), output.m_length);
+ auto copyResult = copyMem(output.dataMut(), output.m_capacity, rhs.data(), output.m_length);
fudAssert(copyResult == FudStatus::Success);
auto nullTerminateStatus = output.nullTerminate();
@@ -90,6 +94,10 @@ StringResult String::from(StringView view, Allocator* allocator)
return StringResult::error(FudStatus::NullPointer);
}
+ if (!String::allocatorValid(allocator)) {
+ return StringResult::error(FudStatus::ArgumentInvalid);
+ }
+
String output{};
output.m_allocator = allocator;
output.m_length = view.m_length;
@@ -97,11 +105,11 @@ StringResult String::from(StringView view, Allocator* allocator)
if (output.m_length >= output.m_capacity) {
output.m_capacity = output.m_length + 1;
- output.m_data = static_cast<utf8*>(M_TakeOrReturn(output.m_allocator->allocate(output.m_capacity)));
+ output.m_data = static_cast<utf8*>(M_TakeOrReturn(output.allocator()->allocate(output.m_capacity)));
fudAssert(output.m_data != nullptr);
}
- auto copyStatus = copyMem(output.data(), output.m_capacity, view.m_data, output.m_length);
+ auto copyStatus = copyMem(output.dataMut(), output.m_capacity, view.m_data, output.m_length);
fudAssert(copyStatus == FudStatus::Success);
auto terminateStatus = output.nullTerminate();
@@ -110,7 +118,7 @@ StringResult String::from(StringView view, Allocator* allocator)
return StringResult::okay(std::move(output));
}
-String::String(String&& rhs) noexcept : m_length{rhs.m_length}, m_capacity{rhs.m_capacity}, m_allocator{rhs.m_allocator}
+String::String(String&& rhs) noexcept : m_allocator{rhs.m_allocator}, m_length{rhs.m_length}, m_capacity{rhs.m_capacity}
{
if (rhs.isLarge()) {
m_data = rhs.m_data;
@@ -144,10 +152,10 @@ FudStatus String::copy(const String& rhs)
m_allocator = rhs.m_allocator;
if (isLarge()) {
- m_data = static_cast<utf8*>(M_TakeOrReturn(m_allocator->allocate(m_capacity)));
+ m_data = static_cast<utf8*>(M_TakeOrReturn(allocator()->allocate(m_capacity)));
}
- auto copyResult = copyMem(data(), m_capacity, rhs.data(), m_length);
+ auto copyResult = copyMem(dataMut(), m_capacity, rhs.data(), m_length);
fudAssert(copyResult == FudStatus::Success);
auto nullTerminateStatus = nullTerminate();
fudAssert(nullTerminateStatus == FudStatus::Success);
@@ -178,8 +186,9 @@ String& String::operator=(String&& rhs) noexcept
void String::cleanup()
{
- if (isLarge() && m_data != nullptr && m_allocator != nullptr) {
- auto deallocStatus = m_allocator->deallocate(m_data, m_capacity);
+ const auto* allocPtr = allocator();
+ if (isLarge() && m_data != nullptr && allocPtr != nullptr) {
+ auto deallocStatus = allocator()->deallocate(m_data, m_capacity);
static_cast<void>(deallocStatus);
m_data = nullptr;
}
@@ -202,33 +211,33 @@ FudStatus String::resize(size_t newCapacity)
if (newCapacity <= SSO_BUF_SIZE) {
BufType temp{BufType::constFill(0)};
- auto copyResult = copyMem(data(), temp.size(), temp.data(), length());
+ auto copyResult = copyMem(dataMut(), temp.size(), temp.data(), length());
fudAssert(copyResult == FudStatus::Success);
- auto deallocStatus = m_allocator->deallocate(m_data, m_capacity);
+ auto deallocStatus = allocator()->deallocate(m_data, m_capacity);
m_capacity = SSO_BUF_SIZE;
m_data = nullptr;
copyMem(m_buffer, temp);
- data()[m_length] = '\0';
+ dataMut()[m_length] = '\0';
return deallocStatus != FudStatus::Success ? FudStatus::DeallocFailure : FudStatus::Success;
}
- auto* newData = static_cast<utf8*>(M_TakeOrReturn(m_allocator->allocate(newCapacity)));
+ auto* newData = static_cast<utf8*>(M_TakeOrReturn(allocator()->allocate(newCapacity)));
fudAssert(newData != nullptr);
- auto copyResult = copyMem(newData, newCapacity, data(), length());
+ auto copyResult = copyMem(newData, newCapacity, dataMut(), length());
fudAssert(copyResult == FudStatus::Success);
auto deallocStatus = FudStatus::Success;
if (isLarge()) {
- deallocStatus = m_allocator->deallocate(data(), m_capacity);
+ deallocStatus = allocator()->deallocate(dataMut(), m_capacity);
}
m_capacity = newCapacity;
m_data = newData;
- data()[m_length] = '\0';
+ dataMut()[m_length] = '\0';
fudAssert(valid());
return deallocStatus != FudStatus::Success ? FudStatus::DeallocFailure : FudStatus::Success;
@@ -241,7 +250,7 @@ bool String::nullTerminated() const
bool String::valid() const
{
- return m_allocator != nullptr && nullTerminated();
+ return allocator() != nullptr && nullTerminated();
}
bool String::utf8Valid() const
@@ -257,7 +266,7 @@ bool String::utf8Valid() const
FudStatus String::nullTerminate()
{
if (m_length < m_capacity) {
- data()[m_length] = '\0';
+ dataMut()[m_length] = '\0';
return FudStatus::Success;
}
return FudStatus::StringInvalid;
@@ -282,7 +291,7 @@ FudStatus String::reserve(size_t newCapacity)
return NullOpt;
}
- utf8 backChar = data()[m_length - 1];
+ utf8 backChar = dataMut()[m_length - 1];
if (Ascii::valid(backChar)) {
return backChar;
}
@@ -301,8 +310,8 @@ Option<utf8> String::pop()
}
m_length--;
- auto letter = data()[m_length];
- data()[m_length] = '\0';
+ auto letter = dataMut()[m_length];
+ dataMut()[m_length] = '\0';
return letter;
}
@@ -326,9 +335,9 @@ FudStatus String::pushBack(utf8 letter)
fudAssert(m_capacity == newCapacity);
}
- data()[m_length] = letter;
+ dataMut()[m_length] = letter;
m_length++;
- data()[m_length] = '\0';
+ dataMut()[m_length] = '\0';
return FudStatus::Success;
}
@@ -368,7 +377,7 @@ FudStatus String::pushBack(const FudUtf8& letter)
}
m_length += letterSize;
- data()[m_length] = '\0';
+ dataMut()[m_length] = '\0';
return FudStatus::Success;
}
@@ -416,7 +425,7 @@ FudStatus String::append(StringView source)
fudAssert(m_capacity == newCapacity);
}
- auto* destPtr = data() + length();
+ auto* destPtr = dataMut() + length();
auto status = copyMem(destPtr, remainingLength(), source.data(), source.length());
fudAssert(status == FudStatus::Success);
@@ -463,7 +472,7 @@ DrainResult String::drain(StringView source)
if (source.length() > remainingLength()) {
firstPart.m_length = remainingLength();
}
- auto* destPtr = data() + length();
+ auto* destPtr = dataMut() + length();
auto status = copyMem(destPtr, remainingLength(), firstPart.m_data, firstPart.m_length);
fudAssert(status == FudStatus::Success);
m_length += firstPart.m_length;
@@ -497,7 +506,7 @@ DrainResult String::drain(StringView source)
fudAssert(m_capacity == newCapacity);
}
- auto* destPtr = data() + length();
+ auto* destPtr = dataMut() + length();
auto status = copyMem(destPtr, remainingLength(), source.data(), source.length());
fudAssert(status == FudStatus::Success);
result.bytesWritten += source.length();
@@ -546,7 +555,7 @@ StringResult String::catenate(const char* rhs) const
return StringResult::okay(std::move(output));
}
- output.m_data = static_cast<utf8*>(M_TakeOrReturn(output.m_allocator->allocate(output.m_capacity)));
+ output.m_data = static_cast<utf8*>(M_TakeOrReturn(output.allocator()->allocate(output.m_capacity)));
fudAssert(output.m_data != nullptr);
auto status = copyMem(output.m_data, m_capacity, data(), length());
@@ -581,11 +590,11 @@ StringResult String::catenate(const String& rhs) const
}
if (output.isLarge()) {
- output.m_data = static_cast<utf8*>(M_TakeOrReturn(output.m_allocator->allocate(output.m_capacity)));
+ output.m_data = static_cast<utf8*>(M_TakeOrReturn(output.allocator()->allocate(output.m_capacity)));
fudAssert(output.m_data != nullptr);
}
- auto* destPtr = output.data();
+ auto* destPtr = output.dataMut();
auto status = copyMem(destPtr, m_capacity, data(), length());
fudAssert(status == FudStatus::Success);
@@ -625,7 +634,7 @@ FudStatus String::clear() {
return FudStatus::StringInvalid;
}
- data()[0] = '\0';
+ dataMut()[0] = '\0';
m_length = 0;
return FudStatus::Success;
diff --git a/source/fud_utf8.cpp b/source/fud_utf8.cpp
index bc12c15..ec72b6d 100644
--- a/source/fud_utf8.cpp
+++ b/source/fud_utf8.cpp
@@ -23,18 +23,13 @@ namespace fud {
FudUtf8 FudUtf8::from(const String& fudString, size_t index) noexcept
{
- if (!fudString.valid()) {
- return invalidAscii();
- }
-
- return from(StringView{fudString}, index);
+ return from(fudString.asView(), index);
}
FudUtf8 FudUtf8::from(StringView view, size_t index) noexcept
{
- auto viewLocal{view};
- auto len = viewLocal.length();
- const auto* vData = viewLocal.data();
+ auto len = view.length();
+ const auto* vData = view.data();
if (vData == nullptr) {
return invalidAscii();
}