diff --git a/SConstruct b/SConstruct index 9c503cd..a8ef938 100644 --- a/SConstruct +++ b/SConstruct @@ -8,7 +8,7 @@ env['CXX'] = 'i686-elf-g++' env['LD'] = 'i686-elf-g++' env.Append(CXXFLAGS = ['-ffreestanding', '-fno-exceptions', '-fno-rtti', '-std=c++20']) env.Append(LINKFLAGS = ['-T', 'linker.ld', '-ffreestanding', '-nostdlib']) -env.Append(CPPPATH = ['#include']) +env.Append(CPPPATH = ['#include', '#stdlib/include']) env.Append(CCFLAGS = ['-g', '-O0']) def get_crt_object(name: str) -> str: @@ -31,12 +31,13 @@ os_sources = Split(''' src/os/panic.cpp src/os/tty.cpp - src/stdlib/assert.cpp - src/stdlib/exception.cpp - src/stdlib/new.cpp - src/stdlib/stdio.cpp - src/stdlib/stdlib.cpp - src/stdlib/string.cpp + src/cstdlib/assert.cpp + src/cstdlib/stdio.cpp + src/cstdlib/stdlib.cpp + src/cstdlib/string.cpp + + stdlib/src/exception.cpp + stdlib/src/new.cpp ''') env['LINKCOM'] = env['LINKCOM'].replace('$_LIBFLAGS', f'{crti_o[0]} {crtbegin_o} $_LIBFLAGS {crtend_o} {crtn_o[0]}') diff --git a/include/stdio.h b/include/stdio.h index 6fbde14..00b992f 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -4,7 +4,7 @@ #if !defined(BAD_APPLE_OS_STDIO_H_INCLUDED) #define BAD_APPLE_OS_STDIO_H_INCLUDED -#include +#include "../stdlib/include/cstdarg" #include "./detail/common.h" BA_EXTERN_C_BEGIN diff --git a/src/app/main.cpp b/src/app/main.cpp index 763fc35..67b6849 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -1,6 +1,8 @@ -#include +#include extern "C" void main() { + std::vector someInts; + someInts.resize(100); } diff --git a/src/stdlib/assert.cpp b/src/cstdlib/assert.cpp similarity index 100% rename from src/stdlib/assert.cpp rename to src/cstdlib/assert.cpp diff --git a/src/stdlib/stdio.cpp b/src/cstdlib/stdio.cpp similarity index 100% rename from src/stdlib/stdio.cpp rename to src/cstdlib/stdio.cpp diff --git a/src/stdlib/stdlib.cpp b/src/cstdlib/stdlib.cpp similarity index 100% rename from src/stdlib/stdlib.cpp rename to src/cstdlib/stdlib.cpp diff --git a/src/stdlib/string.cpp b/src/cstdlib/string.cpp similarity index 100% rename from src/stdlib/string.cpp rename to src/cstdlib/string.cpp diff --git a/stdlib/include/algorithm b/stdlib/include/algorithm new file mode 100644 index 0000000..820a0b9 --- /dev/null +++ b/stdlib/include/algorithm @@ -0,0 +1,12 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_ALGORITHM_INCLUDED) +#define BAD_APPLE_OS_ALGORITHM_INCLUDED + +namespace std +{ + +} + +#endif // !defined(BAD_APPLE_OS_ALGORITHM_INCLUDED) diff --git a/stdlib/include/array b/stdlib/include/array new file mode 100644 index 0000000..af5d771 --- /dev/null +++ b/stdlib/include/array @@ -0,0 +1,146 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_ARRAY_INCLUDED) +#define BAD_APPLE_OS_ARRAY_INCLUDED + +#include +#include +#include + +namespace std +{ +template +class array +{ +public: + using value_type = T; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using reference = value_type&; + using const_reference = const value_type&; + using pointer = value_type*; + using const_pointer = const value_type*; + using iterator = pointer; + using const_iterator = const_pointer; + + T _elements; + + constexpr reference operator[](size_type pos) noexcept + { + return _elements[pos]; + } + + constexpr const_reference operator[](size_type pos) const noexcept + { + return _elements[pos]; + } + + [[nodiscard]] constexpr reference at(size_type pos) + { + if (pos >= N) { + __ba_throw out_of_range(); + } + return _elements[pos]; + } + + [[nodiscard]] constexpr const_reference at(size_type pos) const + { + if (pos >= N) { + __ba_throw out_of_range(); + } + return _elements[pos]; + } + + [[nodiscard]] constexpr reference front() noexcept + { + return _elements[0]; + } + + [[nodiscard]] constexpr const_reference front() const noexcept + { + return _elements[0]; + } + + [[nodiscard]] constexpr reference back() noexcept + { + return _elements[N - 1]; + } + + [[nodiscard]] constexpr const_reference back() const noexcept + { + return _elements[N - 1]; + } + + [[nodiscard]] constexpr pointer data() noexcept + { + return _elements; + } + + [[nodiscard]] constexpr const_pointer data() const noexcept + { + return _elements; + } + + [[nodiscard]] constexpr iterator begin() noexcept + { + return _elements; + } + + [[nodiscard]] constexpr const_iterator begin() const noexcept + { + return _elements; + } + + [[nodiscard]] constexpr const_iterator cbegin() const noexcept + { + return _elements; + } + + [[nodiscard]] constexpr iterator end() noexcept + { + return &_elements[N]; + } + + [[nodiscard]] constexpr const_iterator end() const noexcept + { + return &_elements[N]; + } + + [[nodiscard]] constexpr const_iterator cend() const noexcept + { + return &_elements[N]; + } + + [[nodiscard]] constexpr bool empty() const noexcept + { + return N == 0; + } + + [[nodiscard]] constexpr size_type size() const noexcept + { + return N; + } + + [[nodiscard]] constexpr size_type max_size() const noexcept + { + return N; + } + + constexpr void fill(const T& value) + { + for (T& ele : *this) { + ele = value; + } + } + + constexpr void swap(array& other) + { + for (size_type idx = 0; idx < N; ++idx) { + std::swap((*this)[idx], other[idx]); + } + } +}; +} + +#endif // !defined(BAD_APPLE_OS_ARRAY_INCLUDED) diff --git a/include/cassert b/stdlib/include/cassert similarity index 100% rename from include/cassert rename to stdlib/include/cassert diff --git a/include/cstdarg b/stdlib/include/cstdarg similarity index 100% rename from include/cstdarg rename to stdlib/include/cstdarg diff --git a/stdlib/include/cstddef b/stdlib/include/cstddef new file mode 100644 index 0000000..c749377 --- /dev/null +++ b/stdlib/include/cstddef @@ -0,0 +1,15 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_CSTDDEF_INCLUDED) +#define BAD_APPLE_OS_CSTDDEF_INCLUDED + +#include + +namespace std +{ +using ::ptrdiff_t; +using ::size_t; +} + +#endif // !defined(BAD_APPLE_OS_CSTDDEF_INCLUDED) diff --git a/include/cstdio b/stdlib/include/cstdio similarity index 100% rename from include/cstdio rename to stdlib/include/cstdio diff --git a/include/cstdlib b/stdlib/include/cstdlib similarity index 100% rename from include/cstdlib rename to stdlib/include/cstdlib diff --git a/include/cstring b/stdlib/include/cstring similarity index 100% rename from include/cstring rename to stdlib/include/cstring diff --git a/include/exception b/stdlib/include/exception similarity index 100% rename from include/exception rename to stdlib/include/exception diff --git a/include/new b/stdlib/include/new similarity index 63% rename from include/new rename to stdlib/include/new index 7571f8b..80bd0bb 100644 --- a/include/new +++ b/stdlib/include/new @@ -2,6 +2,7 @@ #if !defined(BAD_APPLE_OS_NEW_INCLUDED) #define BAD_APPLE_OS_NEW_INCLUDED +#include #include namespace std @@ -16,4 +17,14 @@ public: }; } +inline void* operator new(std::size_t, void* placement) noexcept +{ + return placement; +} + +inline void* operator new[](std::size_t, void* placement) noexcept +{ + return placement; +} + #endif // !defined(BAD_APPLE_OS_NEW_INCLUDED) diff --git a/stdlib/include/stdexcept b/stdlib/include/stdexcept new file mode 100644 index 0000000..dec66cc --- /dev/null +++ b/stdlib/include/stdexcept @@ -0,0 +1,23 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_STDEXCEPT_INCLUDED) +#define BAD_APPLE_OS_STDEXCEPT_INCLUDED + +#include "exception" + +namespace std +{ +class logic_error : public exception +{ +private: + +}; + +class out_of_range : public logic_error +{ + +}; +} + +#endif // !defined(BAD_APPLE_OS_STDEXCEPT_INCLUDED) diff --git a/stdlib/include/type_traits b/stdlib/include/type_traits new file mode 100644 index 0000000..68dc6df --- /dev/null +++ b/stdlib/include/type_traits @@ -0,0 +1,31 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_TYPE_TRAITS_INCLUDED) +#define BAD_APPLE_OS_TYPE_TRAITS_INCLUDED + +namespace std +{ +template +struct remove_reference +{ + using type = T; +}; + +template +struct remove_reference +{ + using type = T; +}; + +template +struct remove_reference +{ + using type = T; +}; + +template +using remove_reference_t = typename remove_reference::type; +} + +#endif // !defined(BAD_APPLE_OS_TYPE_TRAITS_INCLUDED) diff --git a/stdlib/include/utility b/stdlib/include/utility new file mode 100644 index 0000000..4e241ca --- /dev/null +++ b/stdlib/include/utility @@ -0,0 +1,40 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_UTILITY_INCLUDED) +#define BAD_APPLE_OS_UTILITY_INCLUDED + +#include "type_traits" + +namespace std +{ +template +constexpr remove_reference_t&& move(T&& val) noexcept +{ + return static_cast&&>(val); +} + +template +constexpr void swap(T& first, T& second) +{ + T temp = std::move(first); + first = std::move(second); + second = std::move(temp); +} + +template +[[nodiscard]] constexpr T&& forward(remove_reference_t& value) +{ + return static_cast(value); +} + +template +[[nodiscard]] constexpr T exchange(T& obj, U&& newValue) +{ + T oldValue = std::move(obj); + obj = std::forward(newValue); + return oldValue; +} +} + +#endif // !defined(BAD_APPLE_OS_UTILITY_INCLUDED) diff --git a/stdlib/include/vector b/stdlib/include/vector new file mode 100644 index 0000000..e727baf --- /dev/null +++ b/stdlib/include/vector @@ -0,0 +1,287 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_VECTOR_INCLUDED) +#define BAD_APPLE_OS_VECTOR_INCLUDED + +#include +#include +#include +#include + +namespace std +{ +template // TODO: allocator +class vector +{ +public: + using value_type = T; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using reference = value_type&; + using const_reference = const value_type&; + using pointer = value_type*; + using const_pointer = const value_type*; + using iterator = pointer; + using const_iterator = const_pointer; +private: + T* _elements = nullptr; + size_type _size = 0; + size_type _capacity = 0; +public: + constexpr vector() noexcept = default; + constexpr vector(const vector& other) noexcept + { + resize(other.size()); + for (size_type idx = 0; idx < size(); ++idx) + { + (*this)[idx] = other[idx]; + } + } + constexpr vector(vector&& other) noexcept + : _elements(exchange(other._elements, nullptr)), + _size(exchange(other._size, 0)), + _capacity(exchange(other._capacity, 0)) + { + } + constexpr ~vector() noexcept + { + delete _elements; + } + constexpr vector& operator=(const vector& other) + { + if (this == &other) { + return *this; + } + resize(other.size()); + for (size_type idx = 0; idx < size(); ++idx) + { + (*this)[idx] = other[idx]; + } + return *this; + } + constexpr vector& operator=(vector&& other) + { + if (this == &other) { + return *this; + } + clear(); + _elements = exchange(other._elements, nullptr); + _size = exchange(other._size, 0); + _capacity = exchange(other._capacity, 0); + return *this; + } + + [[nodiscard]] constexpr reference operator[](size_type pos) + { + return _elements[pos]; + } + + [[nodiscard]] constexpr const_reference operator[](size_type pos) const + { + return _elements[pos]; + } + + [[nodiscard]] constexpr reference at(size_type pos) + { + if (pos >= size()) { + __ba_throw out_of_range(); + } + return _elements[pos]; + } + + [[nodiscard]] constexpr const_reference at(size_type pos) const + { + if (pos >= size()) { + __ba_throw out_of_range(); + } + return _elements[pos]; + } + + [[nodiscard]] constexpr reference front() noexcept + { + return _elements[0]; + } + + [[nodiscard]] constexpr const_reference front() const noexcept + { + return _elements[0]; + } + + [[nodiscard]] constexpr reference back() noexcept + { + return _elements[size() - 1]; + } + + [[nodiscard]] constexpr const_reference back() const noexcept + { + return _elements[size() - 1]; + } + + [[nodiscard]] constexpr pointer data() noexcept + { + return _elements; + } + + [[nodiscard]] constexpr const_pointer data() const noexcept + { + return _elements; + } + + [[nodiscard]] constexpr iterator begin() noexcept + { + return _elements; + } + + [[nodiscard]] constexpr const_iterator begin() const noexcept + { + return _elements; + } + + [[nodiscard]] constexpr const_iterator cbegin() const noexcept + { + return _elements; + } + + [[nodiscard]] constexpr iterator end() noexcept + { + return &_elements[size()]; + } + + [[nodiscard]] constexpr const_iterator end() const noexcept + { + return &_elements[size()]; + } + + [[nodiscard]] constexpr const_iterator cend() const noexcept + { + return &_elements[size()]; + } + + [[nodiscard]] constexpr bool empty() const noexcept + { + return size() == 0; + } + + [[nodiscard]] constexpr size_type size() const noexcept + { + return _size; + } + + [[nodiscard]] constexpr size_type max_size() const noexcept + { + return size_type(-1); + } + + constexpr void reserve(size_type newCapacity) + { + if (newCapacity <= capacity()) { + return; + } + updateCapacity(newCapacity); + } + + [[nodiscard]] size_type capacity() const noexcept + { + return _capacity; + } + + constexpr void shrink_to_fit() + { + updateCapacity(size()); + } + + constexpr void clear() + { + resize(0); + } + + constexpr void push_back(const value_type& value) + { + reserve(size() + 1); + ::new (&_elements[size()]) T(value); + ++_size; + } + + constexpr void push_back(value_type&& value) + { + reserve(size() + 1); + ::new (&_elements[size()]) T(std::move(value)); + ++_size; + } + + template + constexpr reference emplace_back(TArgs&&... args) + { + reserve(size() + 1); + ::new (&_elements[size()]) T(std::forward(args)...); + ++_size; + } + + constexpr void resize(size_type newSize) + { + if (newSize == size()) { + return; + } + reserve(newSize); + + if (newSize > size()) + { + for (size_type idx = size(); idx < newSize; ++idx) + { + ::new (&_elements[idx]) T(); + } + } + else + { + for (size_type idx = newSize; idx < size(); ++idx) + { + _elements[idx].~T(); + } + } + _size = newSize; + } + + constexpr void resize(size_type newSize, const value_type& initValue) + { + if (newSize == size()) { + return; + } + reserve(newSize); + + if (newSize > size()) + { + for (size_type idx = size(); idx < newSize; ++idx) + { + ::new (&_elements[idx]) T(initValue); + } + } + else + { + for (size_type idx = newSize; idx < size(); ++idx) + { + _elements[idx].~T(); + } + } + _size = newSize; + } +private: + void updateCapacity(size_type newCapacity) + { + if (capacity() == newCapacity) { + return; + } + T* newElements = static_cast(malloc(newCapacity * sizeof(T))); + for (size_type idx = 0; idx < size(); ++idx) + { + ::new (&newElements[idx]) T(move(_elements[idx])); + _elements[idx].~T(); + } + free(_elements); + _elements = newElements; + _capacity = newCapacity; + } +}; +} + +#endif // !defined(BAD_APPLE_OS_VECTOR_INCLUDED) diff --git a/src/stdlib/exception.cpp b/stdlib/src/exception.cpp similarity index 100% rename from src/stdlib/exception.cpp rename to stdlib/src/exception.cpp diff --git a/src/stdlib/new.cpp b/stdlib/src/new.cpp similarity index 100% rename from src/stdlib/new.cpp rename to stdlib/src/new.cpp