Compare commits
20 Commits
71b981175e
...
77887eed80
Author | SHA1 | Date | |
---|---|---|---|
77887eed80 | |||
65dd3cd7fb | |||
5a9d31c2be | |||
8ba571a30e | |||
f88dc050a9 | |||
4fc16915d3 | |||
01b6294f76 | |||
a65f4311aa | |||
dd2f31d8d0 | |||
5fb292bc0e | |||
d3bda46325 | |||
ba9d725481 | |||
3a2b8bcfd7 | |||
a49555addc | |||
529b84cd1e | |||
b9fb4c1ce6 | |||
be408c4cdb | |||
38f0d3a4e6 | |||
9274ad0404 | |||
c422d11682 |
@ -28,7 +28,7 @@ set(CMAKE_FIND_ROOT_PATH ${LUNA_ROOT}/toolchain/${LUNA_ARCH}-luna)
|
|||||||
|
|
||||||
message(STATUS "Configuring Luna for ${LUNA_ARCH}")
|
message(STATUS "Configuring Luna for ${LUNA_ARCH}")
|
||||||
|
|
||||||
add_subdirectory(luna)
|
add_subdirectory(libluna)
|
||||||
add_subdirectory(libc)
|
add_subdirectory(libc)
|
||||||
add_subdirectory(kernel)
|
add_subdirectory(kernel)
|
||||||
add_subdirectory(apps)
|
add_subdirectory(apps)
|
||||||
|
@ -26,6 +26,8 @@ set(SOURCES
|
|||||||
src/sys/clock_gettime.cpp
|
src/sys/clock_gettime.cpp
|
||||||
src/sys/allocate_memory.cpp
|
src/sys/allocate_memory.cpp
|
||||||
src/sys/usleep.cpp
|
src/sys/usleep.cpp
|
||||||
|
src/fs/VFS.cpp
|
||||||
|
src/fs/tmpfs/FileSystem.cpp
|
||||||
src/InitRD.cpp
|
src/InitRD.cpp
|
||||||
src/ELF.cpp
|
src/ELF.cpp
|
||||||
)
|
)
|
||||||
|
11
kernel/src/fs/VFS.cpp
Normal file
11
kernel/src/fs/VFS.cpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include "fs/VFS.h"
|
||||||
|
|
||||||
|
namespace VFS
|
||||||
|
{
|
||||||
|
SharedPtr<FileSystem> root_fs;
|
||||||
|
|
||||||
|
Inode& root_inode()
|
||||||
|
{
|
||||||
|
return root_fs->root_inode();
|
||||||
|
}
|
||||||
|
}
|
70
kernel/src/fs/VFS.h
Normal file
70
kernel/src/fs/VFS.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <luna/SharedPtr.h>
|
||||||
|
|
||||||
|
namespace VFS
|
||||||
|
{
|
||||||
|
enum class InodeType
|
||||||
|
{
|
||||||
|
RegularFile,
|
||||||
|
Directory
|
||||||
|
};
|
||||||
|
|
||||||
|
class FileSystem;
|
||||||
|
|
||||||
|
class Inode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Directory-specific methods
|
||||||
|
virtual Result<SharedPtr<Inode>> find(const char* name) const = 0;
|
||||||
|
|
||||||
|
virtual Result<SharedPtr<Inode>> create_file(const char* name) = 0;
|
||||||
|
|
||||||
|
// Generic methods
|
||||||
|
virtual FileSystem& fs() const = 0;
|
||||||
|
|
||||||
|
virtual ~Inode() = default;
|
||||||
|
|
||||||
|
virtual InodeType type() const = 0;
|
||||||
|
|
||||||
|
virtual usize inode_number() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FileInode : Inode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Result<SharedPtr<Inode>> find(const char*) const override
|
||||||
|
{
|
||||||
|
return err(ENOTDIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<SharedPtr<Inode>> create_file(const char*) override
|
||||||
|
{
|
||||||
|
return err(ENOTDIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
InodeType type() const override
|
||||||
|
{
|
||||||
|
return InodeType::RegularFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~FileInode() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FileSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual Inode& root_inode() const = 0;
|
||||||
|
|
||||||
|
virtual Result<SharedPtr<Inode>> create_file_inode() = 0;
|
||||||
|
|
||||||
|
virtual Result<SharedPtr<Inode>> create_dir_inode(SharedPtr<Inode> parent) = 0;
|
||||||
|
|
||||||
|
virtual ~FileSystem() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern SharedPtr<FileSystem> root_fs;
|
||||||
|
|
||||||
|
Result<Inode*> resolve_path(const char* path);
|
||||||
|
|
||||||
|
Inode& root_inode();
|
||||||
|
}
|
71
kernel/src/fs/tmpfs/FileSystem.cpp
Normal file
71
kernel/src/fs/tmpfs/FileSystem.cpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#include "fs/tmpfs/FileSystem.h"
|
||||||
|
#include <luna/Alloc.h>
|
||||||
|
#include <luna/CString.h>
|
||||||
|
#include <luna/Ignore.h>
|
||||||
|
|
||||||
|
namespace TmpFS
|
||||||
|
{
|
||||||
|
Result<SharedPtr<VFS::FileSystem>> FileSystem::create()
|
||||||
|
{
|
||||||
|
SharedPtr<FileSystem> fs = TRY(adopt_shared(new (std::nothrow) FileSystem()));
|
||||||
|
SharedPtr<VFS::Inode> root = TRY(fs->create_dir_inode({}));
|
||||||
|
fs->set_root(root);
|
||||||
|
return (SharedPtr<VFS::FileSystem>)fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<SharedPtr<VFS::Inode>> FileSystem::create_file_inode()
|
||||||
|
{
|
||||||
|
SharedPtr<FileInode> inode = TRY(make_shared<FileInode>());
|
||||||
|
inode->set_fs(*this, {});
|
||||||
|
inode->set_inode_number(m_next_inode_number, {});
|
||||||
|
TRY(m_inodes.try_append(inode));
|
||||||
|
m_next_inode_number++;
|
||||||
|
return (SharedPtr<VFS::Inode>)inode;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<SharedPtr<VFS::Inode>> FileSystem::create_dir_inode(SharedPtr<VFS::Inode> parent)
|
||||||
|
{
|
||||||
|
SharedPtr<DirInode> inode = TRY(make_shared<DirInode>());
|
||||||
|
TRY(inode->add_entry(inode, "."));
|
||||||
|
TRY(inode->add_entry(parent ? parent : (SharedPtr<VFS::Inode>)inode, ".."));
|
||||||
|
|
||||||
|
inode->set_fs(*this, {});
|
||||||
|
inode->set_inode_number(m_next_inode_number, {});
|
||||||
|
TRY(m_inodes.try_append(inode));
|
||||||
|
m_next_inode_number++;
|
||||||
|
return (SharedPtr<VFS::Inode>)inode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSystem::set_root(SharedPtr<VFS::Inode> root)
|
||||||
|
{
|
||||||
|
m_root_inode = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<SharedPtr<VFS::Inode>> DirInode::find(const char* name) const
|
||||||
|
{
|
||||||
|
for (const auto& entry : m_entries)
|
||||||
|
{
|
||||||
|
if (!strcmp(name, entry.name.chars())) return entry.inode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err(ENOENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<void> DirInode::add_entry(SharedPtr<VFS::Inode> inode, const char* name)
|
||||||
|
{
|
||||||
|
Entry entry { inode, name };
|
||||||
|
|
||||||
|
TRY(m_entries.try_append(move(entry)));
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<SharedPtr<VFS::Inode>> DirInode::create_file(const char* name)
|
||||||
|
{
|
||||||
|
auto inode = TRY(m_fs->create_file_inode());
|
||||||
|
|
||||||
|
TRY(add_entry(inode, name));
|
||||||
|
|
||||||
|
return inode;
|
||||||
|
}
|
||||||
|
}
|
118
kernel/src/fs/tmpfs/FileSystem.h
Normal file
118
kernel/src/fs/tmpfs/FileSystem.h
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "fs/VFS.h"
|
||||||
|
#include <luna/Atomic.h>
|
||||||
|
#include <luna/Badge.h>
|
||||||
|
#include <luna/StaticString.h>
|
||||||
|
#include <luna/Vector.h>
|
||||||
|
|
||||||
|
namespace TmpFS
|
||||||
|
{
|
||||||
|
class FileSystem : public VFS::FileSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VFS::Inode& root_inode() const override
|
||||||
|
{
|
||||||
|
return *m_root_inode;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<SharedPtr<VFS::Inode>> create_file_inode() override;
|
||||||
|
Result<SharedPtr<VFS::Inode>> create_dir_inode(SharedPtr<VFS::Inode> parent) override;
|
||||||
|
|
||||||
|
static Result<SharedPtr<VFS::FileSystem>> create();
|
||||||
|
|
||||||
|
virtual ~FileSystem() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
FileSystem() = default;
|
||||||
|
|
||||||
|
void set_root(SharedPtr<VFS::Inode> root);
|
||||||
|
|
||||||
|
SharedPtr<VFS::Inode> m_root_inode;
|
||||||
|
Vector<SharedPtr<VFS::Inode>> m_inodes;
|
||||||
|
|
||||||
|
Atomic<usize> m_next_inode_number { 2 };
|
||||||
|
};
|
||||||
|
|
||||||
|
class FileInode : public VFS::FileInode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FileInode() = default;
|
||||||
|
|
||||||
|
void set_fs(FileSystem& fs, Badge<FileSystem>)
|
||||||
|
{
|
||||||
|
m_fs = &fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_inode_number(usize inum, Badge<FileSystem>)
|
||||||
|
{
|
||||||
|
m_inode_number = inum;
|
||||||
|
}
|
||||||
|
|
||||||
|
VFS::FileSystem& fs() const override
|
||||||
|
{
|
||||||
|
return *m_fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
usize inode_number() const override
|
||||||
|
{
|
||||||
|
return m_inode_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~FileInode() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
VFS::FileSystem* m_fs;
|
||||||
|
usize m_inode_number;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DirInode : public VFS::Inode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DirInode() = default;
|
||||||
|
|
||||||
|
void set_fs(FileSystem& fs, Badge<FileSystem>)
|
||||||
|
{
|
||||||
|
m_fs = &fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_inode_number(usize inum, Badge<FileSystem>)
|
||||||
|
{
|
||||||
|
m_inode_number = inum;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<SharedPtr<VFS::Inode>> find(const char* name) const override;
|
||||||
|
|
||||||
|
VFS::FileSystem& fs() const override
|
||||||
|
{
|
||||||
|
return *m_fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
usize inode_number() const override
|
||||||
|
{
|
||||||
|
return m_inode_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
VFS::InodeType type() const override
|
||||||
|
{
|
||||||
|
return VFS::InodeType::Directory;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<SharedPtr<VFS::Inode>> create_file(const char* name) override;
|
||||||
|
|
||||||
|
Result<void> add_entry(SharedPtr<VFS::Inode> inode, const char* name);
|
||||||
|
|
||||||
|
virtual ~DirInode() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
VFS::FileSystem* m_fs;
|
||||||
|
usize m_inode_number;
|
||||||
|
|
||||||
|
struct Entry
|
||||||
|
{
|
||||||
|
SharedPtr<VFS::Inode> inode;
|
||||||
|
StaticString<128> name;
|
||||||
|
};
|
||||||
|
|
||||||
|
Vector<Entry> m_entries;
|
||||||
|
};
|
||||||
|
}
|
@ -7,6 +7,7 @@
|
|||||||
#include "arch/Timer.h"
|
#include "arch/Timer.h"
|
||||||
#include "boot/Init.h"
|
#include "boot/Init.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "fs/tmpfs/FileSystem.h"
|
||||||
#include "memory/Heap.h"
|
#include "memory/Heap.h"
|
||||||
#include "memory/KernelVM.h"
|
#include "memory/KernelVM.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
@ -55,6 +56,18 @@ Result<void> init()
|
|||||||
Thread::init();
|
Thread::init();
|
||||||
Scheduler::init();
|
Scheduler::init();
|
||||||
|
|
||||||
|
VFS::root_fs = TRY(TmpFS::FileSystem::create());
|
||||||
|
|
||||||
|
VFS::Inode& root_inode = VFS::root_inode();
|
||||||
|
kinfoln("root inode number: %zu", root_inode.inode_number());
|
||||||
|
|
||||||
|
kinfoln("root inode's '.' entry inode number: %zu", TRY(root_inode.find("."))->inode_number());
|
||||||
|
kinfoln("root inode's '..' entry inode number: %zu", TRY(root_inode.find(".."))->inode_number());
|
||||||
|
|
||||||
|
TRY(root_inode.create_file("usr"));
|
||||||
|
|
||||||
|
kinfoln("root inode's 'usr' entry inode number: %zu", TRY(root_inode.find("usr"))->inode_number());
|
||||||
|
|
||||||
TarStream::Entry entry;
|
TarStream::Entry entry;
|
||||||
while (TRY(g_initrd.read_next_entry(entry)))
|
while (TRY(g_initrd.read_next_entry(entry)))
|
||||||
{
|
{
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
#include "thread/Spinlock.h"
|
|
||||||
#include "Log.h"
|
|
||||||
#include "arch/CPU.h"
|
|
||||||
|
|
||||||
void Spinlock::lock()
|
|
||||||
{
|
|
||||||
int expected = 0;
|
|
||||||
while (!m_lock.compare_exchange_strong(expected, 1))
|
|
||||||
{
|
|
||||||
expected = 0;
|
|
||||||
CPU::pause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Spinlock::try_lock()
|
|
||||||
{
|
|
||||||
int expected = 0;
|
|
||||||
return m_lock.compare_exchange_strong(expected, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Spinlock::unlock()
|
|
||||||
{
|
|
||||||
int expected = 1;
|
|
||||||
if (!m_lock.compare_exchange_strong(expected, 0))
|
|
||||||
{
|
|
||||||
kwarnln("Spinlock::unlock() called on an unlocked lock with value %d", expected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ScopeLock::ScopeLock(Spinlock& lock) : m_lock(lock)
|
|
||||||
{
|
|
||||||
m_lock.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
ScopeLock::~ScopeLock()
|
|
||||||
{
|
|
||||||
m_lock.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
const u32 RETRIES = 5000000;
|
|
||||||
|
|
||||||
SafeScopeLock::SafeScopeLock(Spinlock& lock) : m_lock(lock)
|
|
||||||
{
|
|
||||||
u32 tries_left = RETRIES;
|
|
||||||
while (!lock.try_lock() && --tries_left) { CPU::pause(); }
|
|
||||||
|
|
||||||
if (tries_left) m_success = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeScopeLock::~SafeScopeLock()
|
|
||||||
{
|
|
||||||
if (m_success) m_lock.unlock();
|
|
||||||
}
|
|
@ -1,139 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "Log.h"
|
|
||||||
#include "arch/CPU.h"
|
|
||||||
#include <luna/Atomic.h>
|
|
||||||
#include <luna/Option.h>
|
|
||||||
|
|
||||||
class Spinlock
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void lock();
|
|
||||||
void unlock();
|
|
||||||
|
|
||||||
bool try_lock();
|
|
||||||
|
|
||||||
bool is_locked() const
|
|
||||||
{
|
|
||||||
return m_lock.load() != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Atomic<int> m_lock { 0 };
|
|
||||||
};
|
|
||||||
|
|
||||||
class ScopeLock
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ScopeLock(Spinlock& lock);
|
|
||||||
~ScopeLock();
|
|
||||||
|
|
||||||
ScopeLock(const ScopeLock&) = delete;
|
|
||||||
ScopeLock(ScopeLock&&) = delete;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Spinlock& m_lock;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SafeScopeLock
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SafeScopeLock(Spinlock& lock);
|
|
||||||
~SafeScopeLock();
|
|
||||||
|
|
||||||
SafeScopeLock(const SafeScopeLock&) = delete;
|
|
||||||
SafeScopeLock(SafeScopeLock&&) = delete;
|
|
||||||
|
|
||||||
bool did_succeed() const
|
|
||||||
{
|
|
||||||
return m_success;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Spinlock& m_lock;
|
|
||||||
bool m_success { false };
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T> class LockedValue
|
|
||||||
{
|
|
||||||
struct LockedValueGuard
|
|
||||||
{
|
|
||||||
LockedValueGuard(LockedValue& value_ref) : m_value_ref(&value_ref)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
LockedValueGuard(const LockedValueGuard& other) = delete;
|
|
||||||
LockedValueGuard(LockedValueGuard&& other)
|
|
||||||
{
|
|
||||||
m_value_ref = other.m_value_ref;
|
|
||||||
other.m_value_ref = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
~LockedValueGuard()
|
|
||||||
{
|
|
||||||
if (m_value_ref) m_value_ref->m_lock.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
T& ref()
|
|
||||||
{
|
|
||||||
expect(m_value_ref, "LockedValueGuard::ref() called on a moved LockedValueGuard");
|
|
||||||
return m_value_ref->m_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set(const T& other)
|
|
||||||
{
|
|
||||||
ref() = other;
|
|
||||||
}
|
|
||||||
|
|
||||||
T* operator->()
|
|
||||||
{
|
|
||||||
return &ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
T& operator*()
|
|
||||||
{
|
|
||||||
return ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
LockedValue* m_value_ref;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
LockedValue() : m_value()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
LockedValue(T value) : m_value(value)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef LOCKED_VALUE_DEBUG
|
|
||||||
LockedValueGuard lock()
|
|
||||||
{
|
|
||||||
m_lock.lock();
|
|
||||||
return { *this };
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
LockedValueGuard lock()
|
|
||||||
{
|
|
||||||
if (m_lock.try_lock()) { return { *this }; }
|
|
||||||
|
|
||||||
kwarnln("Spinning on a locked LockedValue. This might lead to a deadlock...");
|
|
||||||
|
|
||||||
CPU::print_stack_trace();
|
|
||||||
|
|
||||||
m_lock.lock();
|
|
||||||
return { *this };
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Option<LockedValueGuard> try_lock()
|
|
||||||
{
|
|
||||||
if (m_lock.try_lock()) { return { *this }; }
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
T m_value;
|
|
||||||
Spinlock m_lock;
|
|
||||||
};
|
|
@ -17,7 +17,6 @@ set(FREESTANDING_SOURCES
|
|||||||
src/DebugLog.cpp
|
src/DebugLog.cpp
|
||||||
src/Heap.cpp
|
src/Heap.cpp
|
||||||
src/Spinlock.cpp
|
src/Spinlock.cpp
|
||||||
src/UBSAN.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
@ -22,6 +22,8 @@ extern "C"
|
|||||||
// FIXME: Replace this invented function with strlcpy().
|
// FIXME: Replace this invented function with strlcpy().
|
||||||
void nullcpy(char* dest, const char* src, usize len);
|
void nullcpy(char* dest, const char* src, usize len);
|
||||||
|
|
||||||
|
usize strlcpy(char* dest, const char* src, usize len);
|
||||||
|
|
||||||
[[deprecated]] char* strcpy(char* dst, const char* src);
|
[[deprecated]] char* strcpy(char* dst, const char* src);
|
||||||
[[deprecated]] char* strcat(char* dst, const char* src);
|
[[deprecated]] char* strcat(char* dst, const char* src);
|
||||||
|
|
52
libluna/include/luna/StaticString.h
Normal file
52
libluna/include/luna/StaticString.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <luna/CString.h>
|
||||||
|
#include <luna/Types.h>
|
||||||
|
|
||||||
|
template <usize Size> class StaticString
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StaticString() = default;
|
||||||
|
StaticString(const char* string)
|
||||||
|
{
|
||||||
|
adopt(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
void adopt(const char* string)
|
||||||
|
{
|
||||||
|
usize length = strlcpy(m_buffer, string, sizeof(m_buffer));
|
||||||
|
if (length > Size) { m_length = Size; }
|
||||||
|
else
|
||||||
|
m_length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
StaticString<Size>& operator=(const char* string)
|
||||||
|
{
|
||||||
|
adopt(string);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <usize OSize> StaticString<Size>& operator=(const StaticString<OSize>& string)
|
||||||
|
{
|
||||||
|
if constexpr (OSize == Size)
|
||||||
|
{
|
||||||
|
if (this == &string) return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
adopt(string.chars());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* chars() const
|
||||||
|
{
|
||||||
|
return m_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
usize length() const
|
||||||
|
{
|
||||||
|
return m_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
char m_buffer[Size + 1];
|
||||||
|
usize m_length { 0 };
|
||||||
|
};
|
@ -78,7 +78,7 @@ template <typename T> class Vector
|
|||||||
resize(capacity).release_value();
|
resize(capacity).release_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void> try_append(T item)
|
Result<void> try_append(T&& item)
|
||||||
{
|
{
|
||||||
if (m_capacity == m_size) TRY(resize(m_capacity + 8));
|
if (m_capacity == m_size) TRY(resize(m_capacity + 8));
|
||||||
|
|
||||||
@ -89,6 +89,11 @@ template <typename T> class Vector
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<void> try_append(const T& item)
|
||||||
|
{
|
||||||
|
return try_append(T(item));
|
||||||
|
}
|
||||||
|
|
||||||
Option<T> try_pop()
|
Option<T> try_pop()
|
||||||
{
|
{
|
||||||
if (m_size == 0) return {};
|
if (m_size == 0) return {};
|
@ -125,4 +125,15 @@ extern "C"
|
|||||||
if (*str) return const_cast<char*>(str);
|
if (*str) return const_cast<char*>(str);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
usize strlcpy(char* dest, const char* src, usize len)
|
||||||
|
{
|
||||||
|
usize src_len = strlen(src);
|
||||||
|
usize copy_len = src_len;
|
||||||
|
if (len == 0) return src_len;
|
||||||
|
if (src_len >= (len - 1)) copy_len = len - 1;
|
||||||
|
memcpy(dest, src, copy_len);
|
||||||
|
dest[copy_len] = 0;
|
||||||
|
return src_len;
|
||||||
|
}
|
||||||
}
|
}
|
@ -10,4 +10,4 @@ mkdir -p $LUNA_BASE/usr/include
|
|||||||
mkdir -p $LUNA_BASE/usr/include/luna
|
mkdir -p $LUNA_BASE/usr/include/luna
|
||||||
|
|
||||||
cp --preserve=timestamps -RT libc/include/ $LUNA_BASE/usr/include
|
cp --preserve=timestamps -RT libc/include/ $LUNA_BASE/usr/include
|
||||||
cp --preserve=timestamps -RT luna/include/luna/ $LUNA_BASE/usr/include/luna
|
cp --preserve=timestamps -RT libluna/include/luna/ $LUNA_BASE/usr/include/luna
|
||||||
|
Loading…
Reference in New Issue
Block a user