diff --git a/Makefile b/Makefile index 161a1bb..85c7ae8 100644 --- a/Makefile +++ b/Makefile @@ -3,14 +3,20 @@ LIB=libcx BUILD_DIR?=build COM_FLAGS = -fPIC -Isrc/include -CC_FLAGS = -std=c23 -ggdb -CXX_FLAGS = -std=c++23 -nostdinc++ -ggdb -fexceptions -LD_FLAGS = -nostdlib++ -lsupc++ -ggdb -fexceptions +CC_FLAGS = -std=c23 +CXX_FLAGS = -std=c++23 -nostdinc++ +LD_FLAGS = -nostdlib++ -lsupc++ CC=clang CXX=clang LD=clang AR=ar +ifeq ($(DEBUG),true) + CXX_FLAGS += -DDEBUG -ggdb + CC_FLAGS += -DDEBUG -ggdb + LD_FLAGS += -ggdb +endif + cxx_sources=$(wildcard src/*.cpp) c_sources=$(wildcard src/*.c) objects=$(patsubst src/%.cpp,$(BUILD_DIR)/obj/%.cpp.o,$(cxx_sources)) $(patsubst src/%.c,$(BUILD_DIR)/obj/%.c.o,$(c_sources)) @@ -21,6 +27,13 @@ all: shared static compile_commands.json shared: $(BUILD_DIR)/$(LIB).so static: $(BUILD_DIR)/$(LIB).a +install: shared static + cp -r src/include/cx /usr/local/include/ + cp $(BUILD_DIR)/libcx.a /usr/lib/ + cp $(BUILD_DIR)/libcx.so /usr/lib/ + ldconfig # updates linker cache + cp libcx.pc /usr/lib/pkgconfig/ + $(BUILD_DIR)/$(LIB).a: $(objects) $(AR) rcs $@ $^ diff --git a/libcx.pc b/libcx.pc new file mode 100644 index 0000000..fa2dc5d --- /dev/null +++ b/libcx.pc @@ -0,0 +1,10 @@ +prefix=/usr/local +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: cx +Description: libcxx alternative +Version: 1.0.0 +Libs: -L${libdir} -lcx +Cflags: -I${includedir}/cx diff --git a/src/include/cx/collections/buffer.hpp b/src/include/cx/collections/buffer.hpp new file mode 100644 index 0000000..6a8ca8c --- /dev/null +++ b/src/include/cx/collections/buffer.hpp @@ -0,0 +1,63 @@ +#ifndef _H_CX_COLLECTIONS_BUFFER +#define _H_CX_COLLECTIONS_BUFFER + +#include +#include +#include + +template +concept Buffer = requires(T t, uint8_t byte, uint8_t const* byte_ptr, size_t byte_count) { + { t.buf_get_raw_ptr() } -> stl::same_as; + { t.buf_get_raw_mut_ptr() } -> stl::same_as; + { t.buf_get_size() } -> stl::same_as; + { t.buf_push_byte(byte) } -> stl::same_as; + { t.buf_append_bytes(byte_ptr, byte_count) } -> stl::same_as; +}; + +class BufferContainer { +private: + uint8_t* inner; + size_t len; + size_t size; + +public: + BufferContainer() { + this->inner = (uint8_t*)libc::malloc(1024); + this->size = 1024; + } + + ~BufferContainer() { + libc::free(this->inner); + } + + void resize(size_t bytes) { + this->inner = (uint8_t*)libc::realloc(this->inner, bytes); + } + + // IMPL: Buffer + uint8_t const* buf_get_raw_ptr() { + return (uint8_t const*)this->inner; + } + + // IMPL: Buffer + size_t buf_get_size() { + return this->size; + } + + // IMPL: Buffer + void buf_push_byte(uint8_t byte) { + if (this->size <= this->len) { + this->resize(this->size * 2); + } + this->inner[this->len++] = byte; + } + + // IMPL: Buffer + void buf_append_bytes(uint8_t const* byte_ptr, size_t byte_count) { + for (size_t i = 0; i < byte_count; i++) { + this->buf_push_byte(byte_ptr[i]); + } + } +}; + +#endif // !_H_CX_COLLECTIONS_BUFFER \ No newline at end of file diff --git a/src/include/cx/collections/vec.hpp b/src/include/cx/collections/vec.hpp index fcd9d01..fbf3b33 100644 --- a/src/include/cx/collections/vec.hpp +++ b/src/include/cx/collections/vec.hpp @@ -120,6 +120,28 @@ public: // nv.capacity = this->capacity; return nv; } + + // IMPL: Buffer + uint8_t const* buf_get_raw_ptr() { + return (uint8_t const*)this->items; + } + + // IMPL: Buffer + size_t buf_get_size() { + return this->count; + } + + // IMPL: Buffer + void buf_push_byte(uint8_t byte) { + this->push(byte); + } + + // IMPL: Buffer + void buf_append_bytes(uint8_t const* byte_ptr, size_t byte_count) { + for (size_t i = 0; i < byte_count; i++) { + this->buf_push_byte(byte_ptr[i]); + } + } }; #endif // _H_LIBCX_COLLECTIONS_VEC \ No newline at end of file diff --git a/src/include/cx/format/base_types.hpp b/src/include/cx/format/base_types.hpp index d15da6a..2bc964c 100644 --- a/src/include/cx/format/base_types.hpp +++ b/src/include/cx/format/base_types.hpp @@ -2,10 +2,7 @@ #define _H_LIBCX_FORMAT_BASE_TYPES #include - -extern "C" { -int snprintf(char* __restrict s, size_t maxlen, const char* __restrict format, ...); -} +#include template struct Formatter; @@ -14,7 +11,7 @@ template <> struct Formatter { static String fmt_to_str(const int& val) { char buf[32]; - snprintf(buf, sizeof(buf), "%d", val); + libc::snprintf(buf, sizeof(buf), "%d", val); return String(buf); } }; @@ -37,7 +34,7 @@ template <> struct Formatter { static String fmt_to_str(const float& val) { char buf[32]; - snprintf(buf, sizeof(buf), "%f", val); + libc::snprintf(buf, sizeof(buf), "%f", val); return String(buf); } }; @@ -46,9 +43,9 @@ template <> struct Formatter { static String fmt_to_str(const double& val) { char buf[32]; - snprintf(buf, sizeof(buf), "%f", val); + libc::snprintf(buf, sizeof(buf), "%f", val); return String(buf); } }; -#endif // !_H_LIBCX_FORMAT_BASE_TYPES +#endif // !_H_LIBCX_FORMAT_BASE_TYPES \ No newline at end of file diff --git a/src/include/cx/io/print.hpp b/src/include/cx/io/print.hpp index c541364..2a9cc27 100644 --- a/src/include/cx/io/print.hpp +++ b/src/include/cx/io/print.hpp @@ -1,25 +1,21 @@ #ifndef _H_LIBCX_IO_PRINT #define _H_LIBCX_IO_PRINT +#include +#include +#include #include -extern "C" { -int putchar(int c); -} - template void print(const char* fmt, Types... args) { String s = format(fmt, args...); - char* cs = s.as_cstr(); - for (int i = 0; i < s.len(); i++) { - putchar(cs[i]); - } + Stdout::write(stl::move(s)); } template void println(const char* fmt, Types... args) { print(fmt, args...); - putchar('\n'); + Stdout::write(String("\n")); } -#endif // !_H_LIBCX_IO_PRINT +#endif // !_H_LIBCX_IO_PRINT \ No newline at end of file diff --git a/src/include/cx/io/read.hpp b/src/include/cx/io/read.hpp new file mode 100644 index 0000000..76c1c74 --- /dev/null +++ b/src/include/cx/io/read.hpp @@ -0,0 +1,7 @@ +#ifndef _H_LIBCX_IO_PRINT +#define _H_LIBCX_IO_PRINT + +#include +#include + +#endif // !_H_LIBCX_IO_PRINT \ No newline at end of file diff --git a/src/include/cx/io/shell.hpp b/src/include/cx/io/shell.hpp new file mode 100644 index 0000000..e7a74d8 --- /dev/null +++ b/src/include/cx/io/shell.hpp @@ -0,0 +1,11 @@ +#ifndef _H_CX_IO_SHELL +#define _H_CX_IO_SHELL + +#include + +namespace shell { + void clear(); + void move_cursor(size_t row, size_t col); +} // namespace shell + +#endif // !_H_CX_IO_SHELL \ No newline at end of file diff --git a/src/include/cx/io/stderr.hpp b/src/include/cx/io/stderr.hpp new file mode 100644 index 0000000..d083423 --- /dev/null +++ b/src/include/cx/io/stderr.hpp @@ -0,0 +1,25 @@ +#ifndef _H_LIBCX_IO_STDERR +#define _H_LIBCX_IO_STDERR + +#include "cx/result.hpp" +#include +#include +#include + +template +class Stderr { + static Result write(T& buf) { + int res = libc::write(stderr, buf.buf_get_raw_ptr(), buf.buf_get_size()); + if (res < 0) { + return Result::err("Failed to write to stderr"); + } + return Result::ok(res); + } + + static Result flush(T& buf) { + libc::fflush((FILE*)stderr); + return Result::ok(); + } +}; + +#endif \ No newline at end of file diff --git a/src/include/cx/io/stdin.hpp b/src/include/cx/io/stdin.hpp new file mode 100644 index 0000000..6a38ba3 --- /dev/null +++ b/src/include/cx/io/stdin.hpp @@ -0,0 +1,50 @@ +#ifndef _H_LIBCX_IO_STDIN +#define _H_LIBCX_IO_STDIN + +#include "cx/result.hpp" +#include +#include +#include + +template +class Stdin { + // This will clear the buffer + Result read_fill_buf(T&& buf) { + read(stdin, buf.buf_get_raw_mut_ptr(), buf.buf_get_size()()); + return Result::ok(); + } + + Result read_till_eof(T&& buf) { + const int buf_size = 1024; + char* int_buf = (char*)libc::malloc(buf_size + 1); + while (libc::fgets(int_buf, buf_size, stdin) != NULL) { + if (libc::feof(stdin) != 0) { + for (int i = 0; i < strlen(int_buf); i++) { + buf.buf_push_byte(int_buf[i]); + } + return Result::ok(); + } + } + for (int i = 0; i < strlen(int_buf); i++) { + buf.buf_push_byte(int_buf[i]); + } + } + + Result read_line(T&& buf) { + const int buf_size = 1024; + char* int_buf = (char*)libc::malloc(buf_size + 1); + while (libc::fgets(int_buf, buf_size, stdin) != NULL) { + if (int_buf[strlen(int_buf) - 1] == '\n') { + for (int i = 0; i < strlen(int_buf); i++) { + buf.buf_push_byte(int_buf[i]); + } + return Result::ok(); + } + } + for (int i = 0; i < strlen(int_buf); i++) { + buf.buf_push_byte(int_buf[i]); + } + } +}; + +#endif // !_H_LIBCX_IO_STDIN \ No newline at end of file diff --git a/src/include/cx/io/stdout.hpp b/src/include/cx/io/stdout.hpp new file mode 100644 index 0000000..853842c --- /dev/null +++ b/src/include/cx/io/stdout.hpp @@ -0,0 +1,25 @@ +#ifndef _H_LIBCX_IO_STDOUT +#define _H_LIBCX_IO_STDOUT + +#include "cx/result.hpp" +#include +#include + +template +class Stdout { +public: + static Result write(T&& buf) { + int res = libc::write(stdout, buf.buf_get_raw_ptr(), buf.buf_get_size()); + if (res < 0) { + return Result::err("Failed to write to stdout"); + } + return Result::ok(res); + } + + static Result flush(T&& buf) { + libc::fflush((FILE*)stdout); + return Result::ok(); + } +}; + +#endif \ No newline at end of file diff --git a/src/include/cx/libc.hpp b/src/include/cx/libc.hpp new file mode 100644 index 0000000..9e46235 --- /dev/null +++ b/src/include/cx/libc.hpp @@ -0,0 +1,29 @@ +#ifndef _H_CX_LIBC +#define _H_CX_LIBC +#include + +typedef void FILE; + +#define stdin 0 +#define stdout 1 +#define stderr 2 + +namespace libc { + extern "C" { + void* malloc(size_t size); + void* realloc(void* ptr, size_t size); + void free(void* ptr); + int snprintf(char* __restrict s, size_t maxlen, const char* __restrict format, ...); + int putchar(int c); + int puts(const char* s); + char* getenv(const char* name); + ssize_t write(int fd, const void* buf, size_t n); + ssize_t read(int fd, void* buf, size_t nbytes); + // returns buf on success, and NULL on error or when end of file occurs while no characters have been read. + char* fgets(char* buf, int size, FILE* stream); + int feof(FILE* stream); + int fflush(FILE* stream); + } +} // namespace libc + +#endif // _H_CX_LIBC \ No newline at end of file diff --git a/src/include/cx/option.hpp b/src/include/cx/option.hpp index 4a12f6e..fd6fb9f 100644 --- a/src/include/cx/option.hpp +++ b/src/include/cx/option.hpp @@ -2,10 +2,7 @@ #ifndef _H_LIBCX_OPTION #define _H_LIBCX_OPTION #include - -extern "C" { -int puts(const char* s); -} +#include template class Option { @@ -41,9 +38,9 @@ public: T& expect(const char* str) { if (!has_value) { - puts("PANIC: Unwrapped a None Option: "); - puts(str); - puts("\n"); + libc::puts("PANIC: Unwrapped a None Option: "); + libc::puts(str); + libc::puts("\n"); __builtin_trap(); } return this->storage; @@ -51,7 +48,7 @@ public: T& unwrap() { if (!has_value) { - puts("PANIC: Unwrapped a None Option\n"); + libc::puts("PANIC: Unwrapped a None Option\n"); __builtin_trap(); } return this->storage; diff --git a/src/include/cx/result.hpp b/src/include/cx/result.hpp index 77c07ac..38e40fd 100644 --- a/src/include/cx/result.hpp +++ b/src/include/cx/result.hpp @@ -2,12 +2,9 @@ #define _H_LIBCX_RESULT #include +#include -extern "C" { -int puts(const char* s); -}; - -template +template struct ResultErrBase { bool is_okay = true; E err_data; @@ -44,7 +41,7 @@ struct ResultErrBase { } }; -template +template class Result : private ResultErrBase { T ok_data; @@ -86,9 +83,9 @@ public: T& expect(const char* str) { if (!this->is_ok()) { - puts("PANIC: Unwrapped result with error: "); - puts(str); - puts("\n"); + libc::puts("PANIC: Unwrapped result with error: "); + libc::puts(str); + libc::puts("\n"); __builtin_trap(); } return &this->ok_data; @@ -96,7 +93,7 @@ public: T& unwrap() { if (!this->is_ok()) { - puts("PANIC: Unwrapped result with error\n"); + libc::puts("PANIC: Unwrapped result with error\n"); __builtin_trap(); } return &this->ok_data; diff --git a/src/include/cx/stddef.hpp b/src/include/cx/stddef.hpp index 57ac423..554fbd7 100644 --- a/src/include/cx/stddef.hpp +++ b/src/include/cx/stddef.hpp @@ -1,7 +1,11 @@ #ifndef _H_LIBCX_STDDEF +#include +#include + using size_t = decltype(sizeof(int)); +using ssize_t = stl::make_signed_t; using ptrdiff_t = decltype(static_cast(nullptr) - static_cast(nullptr)); using nullptr_t = decltype(nullptr); -#endif // !_H_LIBCX_STDDEF +#endif // !_H_LIBCX_STDDEF \ No newline at end of file diff --git a/src/include/cx/stl.hpp b/src/include/cx/stl.hpp index 321496e..232cdf1 100644 --- a/src/include/cx/stl.hpp +++ b/src/include/cx/stl.hpp @@ -16,6 +16,10 @@ namespace stl { #include #include #include +#include +#include +#include +#include } // namespace stl #endif // _H_LIBCX_STL \ No newline at end of file diff --git a/src/include/cx/stl/conditional.hpp b/src/include/cx/stl/conditional.hpp new file mode 100644 index 0000000..d8598e0 --- /dev/null +++ b/src/include/cx/stl/conditional.hpp @@ -0,0 +1,45 @@ +#ifndef _H_CX_STL_CONDITIONAL +#define _H_CX_STL_CONDITIONAL + +template +struct _IfImpl; + +template <> +struct _IfImpl { + template + using _Select = _IfRes; +}; + +template <> +struct _IfImpl { + template + using _Select = _ElseRes; +}; + +template +using _If = typename _IfImpl<_Cond>::template _Select<_IfRes, _ElseRes>; + +template +struct conditional { + using type = _If; +}; + +// _Pragma("clang diagnostic push") +// #if __has_warning("-Winvalid-specialization") +// _Pragma("clang diagnostic ignored -Winvalid-specialization") +// #endif +template +struct conditional { + using type = _Then; +}; + +// _Pragma("clang diagnostic pop") + +template +using conditional_t = typename conditional<_Bp, _IfRes, _ElseRes>::type; + +// Helper so we can use "conditional_t" in all language versions. +template +using __conditional_t = typename conditional<_Bp, _If, _Then>::type; + +#endif // !_H_CX_STL_CONDITIONAL \ No newline at end of file diff --git a/src/include/cx/stl/is_unsigned.hpp b/src/include/cx/stl/is_unsigned.hpp new file mode 100644 index 0000000..354563a --- /dev/null +++ b/src/include/cx/stl/is_unsigned.hpp @@ -0,0 +1,29 @@ +#ifndef _H_CX_STL_IS_UNSIGNED +#define _H_CX_STL_IS_UNSIGNED +#if __has_builtin(__is_unsigned) + +#include +#include + +template +struct is_unsigned : _BoolConstant<__is_unsigned(_Tp)> {}; + +template +inline constexpr bool is_unsigned_v = __is_unsigned(_Tp); + +#else // __has_builtin(__is_unsigned) + +template ::value> +inline constexpr bool __is_unsigned_v = false; + +template +inline constexpr bool __is_unsigned_v<_Tp, true> = _Tp(0) < _Tp(-1); + +template +struct is_unsigned : integral_constant> {}; + +template +inline constexpr bool is_unsigned_v = __is_unsigned_v<_Tp>; + +#endif // __has_builtin(__is_unsigned) +#endif // !_H_CX_STL_IS_UNSIGNED \ No newline at end of file diff --git a/src/include/cx/stl/make_signed.hpp b/src/include/cx/stl/make_signed.hpp new file mode 100644 index 0000000..41e691d --- /dev/null +++ b/src/include/cx/stl/make_signed.hpp @@ -0,0 +1,52 @@ +#ifndef _H_LIBCX_STL_MAKE_SIGNED +#define _H_LIBCX_STL_MAKE_SIGNED +#if __has_builtin(__make_signed) + +template +using __make_signed_t = __make_signed(_Tp); + +#else +using __signed_types = __type_list; + +template ::value || is_enum<_Tp>::value> +struct __make_signed{}; + +template +struct __make_signed<_Tp, true> { + typedef typename __find_first<__signed_types, sizeof(_Tp)>::type type; +}; + +// clang-format off +template <> struct __make_signed {}; +template <> struct __make_signed< signed short, true> {typedef short type;}; +template <> struct __make_signed {typedef short type;}; +template <> struct __make_signed< signed int, true> {typedef int type;}; +template <> struct __make_signed {typedef int type;}; +template <> struct __make_signed< signed long, true> {typedef long type;}; +template <> struct __make_signed {typedef long type;}; +template <> struct __make_signed< signed long long, true> {typedef long long type;}; +template <> struct __make_signed {typedef long long type;}; +# if _CX_HAS_INT128 +template <> struct __make_signed<__int128_t, true> {typedef __int128_t type;}; +template <> struct __make_signed<__uint128_t, true> {typedef __int128_t type;}; +# endif +// clang-format on + +template +using __make_signed_t = __copy_cv_t<_Tp, typename __make_signed<__remove_cv_t<_Tp>>::type>; + +#endif // __has_builtin(__make_signed) + +template +struct make_signed { + using type = __make_signed_t<_Tp>; +}; + +template +using make_signed_t = __make_signed_t<_Tp>; +#endif // _H_LIBCX_STL_MAKE_SIGNED \ No newline at end of file diff --git a/src/include/cx/stl/make_unsigned.hpp b/src/include/cx/stl/make_unsigned.hpp new file mode 100644 index 0000000..f205ac3 --- /dev/null +++ b/src/include/cx/stl/make_unsigned.hpp @@ -0,0 +1,63 @@ +#ifndef _H_LIBCX_STL_MAKE_UNSIGNED +#define _H_LIBCX_STL_MAKE_UNSIGNED + +#include +#include +#if __has_builtin(__make_unsigned) + +template +using __make_unsigned_t = __make_unsigned(_Tp); + +#else +using __unsigned_types = __type_list; + +template ::value || is_enum<_Tp>::value> +struct __make_unsigned{}; + +template +struct __make_unsigned<_Tp, true> { + typedef typename __find_first<__unsigned_types, sizeof(_Tp)>::type type; +}; + +// clang-format off +template <> struct __make_unsigned {}; +template <> struct __make_unsigned< signed short, true> {typedef unsigned short type;}; +template <> struct __make_unsigned {typedef unsigned short type;}; +template <> struct __make_unsigned< signed int, true> {typedef unsigned int type;}; +template <> struct __make_unsigned {typedef unsigned int type;}; +template <> struct __make_unsigned< signed long, true> {typedef unsigned long type;}; +template <> struct __make_unsigned {typedef unsigned long type;}; +template <> struct __make_unsigned< signed long long, true> {typedef unsigned long long type;}; +template <> struct __make_unsigned {typedef unsigned long long type;}; +# if _CX_HAS_INT128 +template <> struct __make_unsigned<__int128_t, true> {typedef __uint128_t type;}; +template <> struct __make_unsigned<__uint128_t, true> {typedef __uint128_t type;}; +# endif +// clang-format on + +template +using __make_unsigned_t = __copy_cv_t<_Tp, typename __make_unsigned<__remove_cv_t<_Tp>>::type>; + +#endif // __has_builtin(__make_unsigned) + +template +struct make_unsigned { + using type = __make_unsigned_t<_Tp>; +}; + +template +using make_unsigned_t = __make_unsigned_t<_Tp>; + +template +__make_unsigned_t<_Tp> __to_unsigned_like(_Tp __x) { + return static_cast<__make_unsigned_t<_Tp>>(__x); +} + +template +using __copy_unsigned_t = __conditional_t::value, __make_unsigned_t<_Up>, _Up>; +#endif // _H_LIBCX_STL_MAKE_UNSIGNED \ No newline at end of file diff --git a/src/include/cx/string.hpp b/src/include/cx/string.hpp index 25acfc9..c7bb6f5 100644 --- a/src/include/cx/string.hpp +++ b/src/include/cx/string.hpp @@ -23,6 +23,16 @@ public: String fmt_to_str(); // IMPL: Clone String clone(); + // IMPL: Buffer + uint8_t const* buf_get_raw_ptr(); + // IMPL: Buffer + uint8_t* buf_get_raw_mut_ptr(); + // IMPL: Buffer + size_t buf_get_size(); + // IMPL: Buffer + void buf_push_byte(uint8_t byte); + // IMPL: Buffer + void buf_append_bytes(uint8_t const* byte_ptr, size_t byte_count); }; #endif // _H_LIBCX_STRING \ No newline at end of file diff --git a/src/internals.cpp b/src/internals.cpp index 641fdea..3b1ce4f 100644 --- a/src/internals.cpp +++ b/src/internals.cpp @@ -1,9 +1,10 @@ #include -#include + +// #include namespace std { void __glibcxx_assert_fail(char const* file, int line, char const* func, char const* info) { - println("{}:{}:{}: {}", file, line, func, info); + // println("{}:{}:{}: {}", file, line, func, info); } void terminate() { @@ -12,4 +13,4 @@ namespace std { } // namespace std -extern "C" void __cxa_begin_catch() {} +extern "C" void __cxa_begin_catch() {} \ No newline at end of file diff --git a/src/io/shell.cpp b/src/io/shell.cpp new file mode 100644 index 0000000..40b85c9 --- /dev/null +++ b/src/io/shell.cpp @@ -0,0 +1,12 @@ +#include +#include + +namespace shell { + void clear() { + println("\e[1;1H\e[2J"); // unix only AFAIK + } + + void move_cursor(size_t row, size_t col) { + println("\e[{};{}H", row, col); + } +} // namespace shell \ No newline at end of file diff --git a/src/logger.cpp b/src/logger.cpp index fcc09f1..3d96922 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -1,7 +1,7 @@ #include #include #include - +#include using namespace log; #define C_RS "\x1b[0m" @@ -19,10 +19,8 @@ using namespace log; #define C_UL "\x1b[4m" #define C_BLINK "\x1b[5m" -extern "C" char* getenv(const char* name); - Logger::Logger() { - char* val = getenv("CPLUS_LOG"); + char* val = libc::getenv("CPLUS_LOG"); if (val != NULL) { if (strcmp(val, "OFF") == 0) { this->set_log_level(LOG_OFF); @@ -37,7 +35,7 @@ Logger::Logger() { } } - val = getenv("CPLUS_LOG_COLOR"); + val = libc::getenv("CPLUS_LOG_COLOR"); // clang-format off if (val != NULL) { if ( @@ -103,4 +101,4 @@ void Logger::load_custom_prefixes(const char* pfx[LOG_LEVEL_COUNT]) { bool Logger::should_display(LogLevel level) { return this->filter_level >= level; -} +} \ No newline at end of file diff --git a/src/string.cpp b/src/string.cpp index 56da6bc..5ad15c4 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -49,4 +49,29 @@ String String::clone() { String s = String(); s._chars = this->_chars.clone(); return s; +} + +// IMPL: Buffer +uint8_t const* String::buf_get_raw_ptr() { + return (uint8_t const*)this->_chars.to_ptr(); +} + +// IMPL: Buffer +uint8_t* String::buf_get_raw_mut_ptr() { + return (uint8_t*)this->_chars.to_ptr(); +} + +// IMPL: Buffer +size_t String::buf_get_size() { + return this->len(); +} + +void String::buf_push_byte(uint8_t byte) { + this->push((char)byte); +} + +void String::buf_append_bytes(uint8_t const* byte_ptr, size_t byte_count) { + for (size_t i = 0; i < byte_count; i++) { + this->buf_push_byte(byte_ptr[i]); + } } \ No newline at end of file