diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/fud_c_file.cpp | 12 | ||||
-rw-r--r-- | source/fud_directory.cpp | 3 | ||||
-rw-r--r-- | source/fud_file.cpp | 123 | ||||
-rw-r--r-- | source/fud_string.cpp | 75 | ||||
-rw-r--r-- | source/fud_utf8.cpp | 11 |
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(); } |