i dont even know anymore

This commit is contained in:
Gvidas Juknevičius 2025-06-16 16:57:25 +03:00
parent 4e3de1cfb2
commit 67e704edab
Signed by: MCorange
GPG Key ID: 5BE6B533CB76FE86
25 changed files with 534 additions and 49 deletions

View File

@ -3,14 +3,20 @@ LIB=libcx
BUILD_DIR?=build BUILD_DIR?=build
COM_FLAGS = -fPIC -Isrc/include COM_FLAGS = -fPIC -Isrc/include
CC_FLAGS = -std=c23 -ggdb CC_FLAGS = -std=c23
CXX_FLAGS = -std=c++23 -nostdinc++ -ggdb -fexceptions CXX_FLAGS = -std=c++23 -nostdinc++
LD_FLAGS = -nostdlib++ -lsupc++ -ggdb -fexceptions LD_FLAGS = -nostdlib++ -lsupc++
CC=clang CC=clang
CXX=clang CXX=clang
LD=clang LD=clang
AR=ar AR=ar
ifeq ($(DEBUG),true)
CXX_FLAGS += -DDEBUG -ggdb
CC_FLAGS += -DDEBUG -ggdb
LD_FLAGS += -ggdb
endif
cxx_sources=$(wildcard src/*.cpp) cxx_sources=$(wildcard src/*.cpp)
c_sources=$(wildcard src/*.c) 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)) 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 shared: $(BUILD_DIR)/$(LIB).so
static: $(BUILD_DIR)/$(LIB).a 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) $(BUILD_DIR)/$(LIB).a: $(objects)
$(AR) rcs $@ $^ $(AR) rcs $@ $^

10
libcx.pc Normal file
View File

@ -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

View File

@ -0,0 +1,63 @@
#ifndef _H_CX_COLLECTIONS_BUFFER
#define _H_CX_COLLECTIONS_BUFFER
#include <cx/libc.hpp>
#include <cx/stddef.hpp>
#include <cx/stl.hpp>
template <typename T>
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<uint8_t const*>;
{ t.buf_get_raw_mut_ptr() } -> stl::same_as<uint8_t*>;
{ t.buf_get_size() } -> stl::same_as<size_t>;
{ t.buf_push_byte(byte) } -> stl::same_as<void>;
{ t.buf_append_bytes(byte_ptr, byte_count) } -> stl::same_as<void>;
};
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

View File

@ -120,6 +120,28 @@ public:
// nv.capacity = this->capacity; // nv.capacity = this->capacity;
return nv; 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 #endif // _H_LIBCX_COLLECTIONS_VEC

View File

@ -2,10 +2,7 @@
#define _H_LIBCX_FORMAT_BASE_TYPES #define _H_LIBCX_FORMAT_BASE_TYPES
#include <cx/string.hpp> #include <cx/string.hpp>
#include <cx/libc.hpp>
extern "C" {
int snprintf(char* __restrict s, size_t maxlen, const char* __restrict format, ...);
}
template <typename T> template <typename T>
struct Formatter; struct Formatter;
@ -14,7 +11,7 @@ template <>
struct Formatter<int> { struct Formatter<int> {
static String fmt_to_str(const int& val) { static String fmt_to_str(const int& val) {
char buf[32]; char buf[32];
snprintf(buf, sizeof(buf), "%d", val); libc::snprintf(buf, sizeof(buf), "%d", val);
return String(buf); return String(buf);
} }
}; };
@ -37,7 +34,7 @@ template <>
struct Formatter<float> { struct Formatter<float> {
static String fmt_to_str(const float& val) { static String fmt_to_str(const float& val) {
char buf[32]; char buf[32];
snprintf(buf, sizeof(buf), "%f", val); libc::snprintf(buf, sizeof(buf), "%f", val);
return String(buf); return String(buf);
} }
}; };
@ -46,7 +43,7 @@ template <>
struct Formatter<double> { struct Formatter<double> {
static String fmt_to_str(const double& val) { static String fmt_to_str(const double& val) {
char buf[32]; char buf[32];
snprintf(buf, sizeof(buf), "%f", val); libc::snprintf(buf, sizeof(buf), "%f", val);
return String(buf); return String(buf);
} }
}; };

View File

@ -1,25 +1,21 @@
#ifndef _H_LIBCX_IO_PRINT #ifndef _H_LIBCX_IO_PRINT
#define _H_LIBCX_IO_PRINT #define _H_LIBCX_IO_PRINT
#include <cx/io/stdout.hpp>
#include <cx/string.hpp>
#include <cx/stl.hpp>
#include <cx/format/fmt.hpp> #include <cx/format/fmt.hpp>
extern "C" {
int putchar(int c);
}
template <typename... Types> template <typename... Types>
void print(const char* fmt, Types... args) { void print(const char* fmt, Types... args) {
String s = format(fmt, args...); String s = format(fmt, args...);
char* cs = s.as_cstr(); Stdout<String>::write(stl::move(s));
for (int i = 0; i < s.len(); i++) {
putchar(cs[i]);
}
} }
template <typename... Types> template <typename... Types>
void println(const char* fmt, Types... args) { void println(const char* fmt, Types... args) {
print(fmt, args...); print(fmt, args...);
putchar('\n'); Stdout<String>::write(String("\n"));
} }
#endif // !_H_LIBCX_IO_PRINT #endif // !_H_LIBCX_IO_PRINT

View File

@ -0,0 +1,7 @@
#ifndef _H_LIBCX_IO_PRINT
#define _H_LIBCX_IO_PRINT
#include <cx/format/fmt.hpp>
#include <cx/libc.hpp>
#endif // !_H_LIBCX_IO_PRINT

View File

@ -0,0 +1,11 @@
#ifndef _H_CX_IO_SHELL
#define _H_CX_IO_SHELL
#include <cx/std.hpp>
namespace shell {
void clear();
void move_cursor(size_t row, size_t col);
} // namespace shell
#endif // !_H_CX_IO_SHELL

View File

@ -0,0 +1,25 @@
#ifndef _H_LIBCX_IO_STDERR
#define _H_LIBCX_IO_STDERR
#include "cx/result.hpp"
#include <cx/collections/buffer.hpp>
#include <cx/std.hpp>
#include <cx/libc.hpp>
template <Buffer T>
class Stderr {
static Result<size_t> write(T& buf) {
int res = libc::write(stderr, buf.buf_get_raw_ptr(), buf.buf_get_size());
if (res < 0) {
return Result<size_t>::err("Failed to write to stderr");
}
return Result<size_t>::ok(res);
}
static Result<void> flush(T& buf) {
libc::fflush((FILE*)stderr);
return Result<void>::ok();
}
};
#endif

View File

@ -0,0 +1,50 @@
#ifndef _H_LIBCX_IO_STDIN
#define _H_LIBCX_IO_STDIN
#include "cx/result.hpp"
#include <cx/collections/buffer.hpp>
#include <cx/std.hpp>
#include <cx/libc.hpp>
template <Buffer T>
class Stdin {
// This will clear the buffer
Result<void, const char*> read_fill_buf(T&& buf) {
read(stdin, buf.buf_get_raw_mut_ptr(), buf.buf_get_size()());
return Result<void, const char*>::ok();
}
Result<void, const char*> 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<void, const char*>::ok();
}
}
for (int i = 0; i < strlen(int_buf); i++) {
buf.buf_push_byte(int_buf[i]);
}
}
Result<void, const char*> 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<void, const char*>::ok();
}
}
for (int i = 0; i < strlen(int_buf); i++) {
buf.buf_push_byte(int_buf[i]);
}
}
};
#endif // !_H_LIBCX_IO_STDIN

View File

@ -0,0 +1,25 @@
#ifndef _H_LIBCX_IO_STDOUT
#define _H_LIBCX_IO_STDOUT
#include "cx/result.hpp"
#include <cx/collections/buffer.hpp>
#include <cx/libc.hpp>
template <Buffer T>
class Stdout {
public:
static Result<size_t> write(T&& buf) {
int res = libc::write(stdout, buf.buf_get_raw_ptr(), buf.buf_get_size());
if (res < 0) {
return Result<size_t>::err("Failed to write to stdout");
}
return Result<size_t>::ok(res);
}
static Result<void> flush(T&& buf) {
libc::fflush((FILE*)stdout);
return Result<void>::ok();
}
};
#endif

29
src/include/cx/libc.hpp Normal file
View File

@ -0,0 +1,29 @@
#ifndef _H_CX_LIBC
#define _H_CX_LIBC
#include <cx/stddef.hpp>
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

View File

@ -2,10 +2,7 @@
#ifndef _H_LIBCX_OPTION #ifndef _H_LIBCX_OPTION
#define _H_LIBCX_OPTION #define _H_LIBCX_OPTION
#include <cx/stl.hpp> #include <cx/stl.hpp>
#include <cx/libc.hpp>
extern "C" {
int puts(const char* s);
}
template <typename T> template <typename T>
class Option { class Option {
@ -41,9 +38,9 @@ public:
T& expect(const char* str) { T& expect(const char* str) {
if (!has_value) { if (!has_value) {
puts("PANIC: Unwrapped a None Option: "); libc::puts("PANIC: Unwrapped a None Option: ");
puts(str); libc::puts(str);
puts("\n"); libc::puts("\n");
__builtin_trap(); __builtin_trap();
} }
return this->storage; return this->storage;
@ -51,7 +48,7 @@ public:
T& unwrap() { T& unwrap() {
if (!has_value) { if (!has_value) {
puts("PANIC: Unwrapped a None Option\n"); libc::puts("PANIC: Unwrapped a None Option\n");
__builtin_trap(); __builtin_trap();
} }
return this->storage; return this->storage;

View File

@ -2,12 +2,9 @@
#define _H_LIBCX_RESULT #define _H_LIBCX_RESULT
#include <cx/stl.hpp> #include <cx/stl.hpp>
#include <cx/libc.hpp>
extern "C" { template <typename E = const char*>
int puts(const char* s);
};
template <typename E>
struct ResultErrBase { struct ResultErrBase {
bool is_okay = true; bool is_okay = true;
E err_data; E err_data;
@ -44,7 +41,7 @@ struct ResultErrBase {
} }
}; };
template <typename T, typename E> template <typename T, typename E = const char*>
class Result : private ResultErrBase<E> { class Result : private ResultErrBase<E> {
T ok_data; T ok_data;
@ -86,9 +83,9 @@ public:
T& expect(const char* str) { T& expect(const char* str) {
if (!this->is_ok()) { if (!this->is_ok()) {
puts("PANIC: Unwrapped result with error: "); libc::puts("PANIC: Unwrapped result with error: ");
puts(str); libc::puts(str);
puts("\n"); libc::puts("\n");
__builtin_trap(); __builtin_trap();
} }
return &this->ok_data; return &this->ok_data;
@ -96,7 +93,7 @@ public:
T& unwrap() { T& unwrap() {
if (!this->is_ok()) { if (!this->is_ok()) {
puts("PANIC: Unwrapped result with error\n"); libc::puts("PANIC: Unwrapped result with error\n");
__builtin_trap(); __builtin_trap();
} }
return &this->ok_data; return &this->ok_data;

View File

@ -1,6 +1,10 @@
#ifndef _H_LIBCX_STDDEF #ifndef _H_LIBCX_STDDEF
#include <cx/stl.hpp>
#include <stdint.h>
using size_t = decltype(sizeof(int)); using size_t = decltype(sizeof(int));
using ssize_t = stl::make_signed_t<size_t>;
using ptrdiff_t = decltype(static_cast<int*>(nullptr) - static_cast<int*>(nullptr)); using ptrdiff_t = decltype(static_cast<int*>(nullptr) - static_cast<int*>(nullptr));
using nullptr_t = decltype(nullptr); using nullptr_t = decltype(nullptr);

View File

@ -16,6 +16,10 @@ namespace stl {
#include <cx/stl/void_t.hpp> #include <cx/stl/void_t.hpp>
#include <cx/stl/is_referenceable.hpp> #include <cx/stl/is_referenceable.hpp>
#include <cx/stl/is_integral.hpp> #include <cx/stl/is_integral.hpp>
#include <cx/stl/conditional.hpp>
#include <cx/stl/is_unsigned.hpp>
#include <cx/stl/make_unsigned.hpp>
#include <cx/stl/make_signed.hpp>
} // namespace stl } // namespace stl
#endif // _H_LIBCX_STL #endif // _H_LIBCX_STL

View File

@ -0,0 +1,45 @@
#ifndef _H_CX_STL_CONDITIONAL
#define _H_CX_STL_CONDITIONAL
template <bool>
struct _IfImpl;
template <>
struct _IfImpl<true> {
template <class _IfRes, class _ElseRes>
using _Select = _IfRes;
};
template <>
struct _IfImpl<false> {
template <class _IfRes, class _ElseRes>
using _Select = _ElseRes;
};
template <bool _Cond, class _IfRes, class _ElseRes>
using _If = typename _IfImpl<_Cond>::template _Select<_IfRes, _ElseRes>;
template <bool _Bp, class _If, class _Then>
struct conditional {
using type = _If;
};
// _Pragma("clang diagnostic push")
// #if __has_warning("-Winvalid-specialization")
// _Pragma("clang diagnostic ignored -Winvalid-specialization")
// #endif
template <class _If, class _Then>
struct conditional<false, _If, _Then> {
using type = _Then;
};
// _Pragma("clang diagnostic pop")
template <bool _Bp, class _IfRes, class _ElseRes>
using conditional_t = typename conditional<_Bp, _IfRes, _ElseRes>::type;
// Helper so we can use "conditional_t" in all language versions.
template <bool _Bp, class _If, class _Then>
using __conditional_t = typename conditional<_Bp, _If, _Then>::type;
#endif // !_H_CX_STL_CONDITIONAL

View File

@ -0,0 +1,29 @@
#ifndef _H_CX_STL_IS_UNSIGNED
#define _H_CX_STL_IS_UNSIGNED
#if __has_builtin(__is_unsigned)
#include <cx/stl/integral_constant.hpp>
#include <cx/stl/is_integral.hpp>
template <class _Tp>
struct is_unsigned : _BoolConstant<__is_unsigned(_Tp)> {};
template <class _Tp>
inline constexpr bool is_unsigned_v = __is_unsigned(_Tp);
#else // __has_builtin(__is_unsigned)
template <class _Tp, bool = is_integral<_Tp>::value>
inline constexpr bool __is_unsigned_v = false;
template <class _Tp>
inline constexpr bool __is_unsigned_v<_Tp, true> = _Tp(0) < _Tp(-1);
template <class _Tp>
struct is_unsigned : integral_constant<bool, __is_unsigned_v<_Tp>> {};
template <class _Tp>
inline constexpr bool is_unsigned_v = __is_unsigned_v<_Tp>;
#endif // __has_builtin(__is_unsigned)
#endif // !_H_CX_STL_IS_UNSIGNED

View File

@ -0,0 +1,52 @@
#ifndef _H_LIBCX_STL_MAKE_SIGNED
#define _H_LIBCX_STL_MAKE_SIGNED
#if __has_builtin(__make_signed)
template <class _Tp>
using __make_signed_t = __make_signed(_Tp);
#else
using __signed_types = __type_list<signed char, signed short, signed int, signed long, signed long long
#if _CX_HAS_INT128
,
__int128_t
#endif
>;
template <class _Tp, bool = is_integral<_Tp>::value || is_enum<_Tp>::value>
struct __make_signed{};
template <class _Tp>
struct __make_signed<_Tp, true> {
typedef typename __find_first<__signed_types, sizeof(_Tp)>::type type;
};
// clang-format off
template <> struct __make_signed<bool, true> {};
template <> struct __make_signed< signed short, true> {typedef short type;};
template <> struct __make_signed<unsigned short, true> {typedef short type;};
template <> struct __make_signed< signed int, true> {typedef int type;};
template <> struct __make_signed<unsigned int, true> {typedef int type;};
template <> struct __make_signed< signed long, true> {typedef long type;};
template <> struct __make_signed<unsigned long, true> {typedef long type;};
template <> struct __make_signed< signed long long, true> {typedef long long type;};
template <> struct __make_signed<unsigned long long, true> {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 <class _Tp>
using __make_signed_t = __copy_cv_t<_Tp, typename __make_signed<__remove_cv_t<_Tp>>::type>;
#endif // __has_builtin(__make_signed)
template <class _Tp>
struct make_signed {
using type = __make_signed_t<_Tp>;
};
template <class _Tp>
using make_signed_t = __make_signed_t<_Tp>;
#endif // _H_LIBCX_STL_MAKE_SIGNED

View File

@ -0,0 +1,63 @@
#ifndef _H_LIBCX_STL_MAKE_UNSIGNED
#define _H_LIBCX_STL_MAKE_UNSIGNED
#include <cx/stl/is_unsigned.hpp>
#include <cx/stl/conditional.hpp>
#if __has_builtin(__make_unsigned)
template <class _Tp>
using __make_unsigned_t = __make_unsigned(_Tp);
#else
using __unsigned_types = __type_list<unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long
#if _CX_HAS_INT128
,
__uint128_t
#endif
>;
template <class _Tp, bool = is_integral<_Tp>::value || is_enum<_Tp>::value>
struct __make_unsigned{};
template <class _Tp>
struct __make_unsigned<_Tp, true> {
typedef typename __find_first<__unsigned_types, sizeof(_Tp)>::type type;
};
// clang-format off
template <> struct __make_unsigned<bool, true> {};
template <> struct __make_unsigned< signed short, true> {typedef unsigned short type;};
template <> struct __make_unsigned<unsigned short, true> {typedef unsigned short type;};
template <> struct __make_unsigned< signed int, true> {typedef unsigned int type;};
template <> struct __make_unsigned<unsigned int, true> {typedef unsigned int type;};
template <> struct __make_unsigned< signed long, true> {typedef unsigned long type;};
template <> struct __make_unsigned<unsigned long, true> {typedef unsigned long type;};
template <> struct __make_unsigned< signed long long, true> {typedef unsigned long long type;};
template <> struct __make_unsigned<unsigned long long, true> {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 <class _Tp>
using __make_unsigned_t = __copy_cv_t<_Tp, typename __make_unsigned<__remove_cv_t<_Tp>>::type>;
#endif // __has_builtin(__make_unsigned)
template <class _Tp>
struct make_unsigned {
using type = __make_unsigned_t<_Tp>;
};
template <class _Tp>
using make_unsigned_t = __make_unsigned_t<_Tp>;
template <class _Tp>
__make_unsigned_t<_Tp> __to_unsigned_like(_Tp __x) {
return static_cast<__make_unsigned_t<_Tp>>(__x);
}
template <class _Tp, class _Up>
using __copy_unsigned_t = __conditional_t<is_unsigned<_Tp>::value, __make_unsigned_t<_Up>, _Up>;
#endif // _H_LIBCX_STL_MAKE_UNSIGNED

View File

@ -23,6 +23,16 @@ public:
String fmt_to_str(); String fmt_to_str();
// IMPL: Clone // IMPL: Clone
String 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 #endif // _H_LIBCX_STRING

View File

@ -1,9 +1,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <cx/std.hpp>
// #include <cx/std.hpp>
namespace std { namespace std {
void __glibcxx_assert_fail(char const* file, int line, char const* func, char const* info) { 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() { void terminate() {

12
src/io/shell.cpp Normal file
View File

@ -0,0 +1,12 @@
#include <cx/io/shell.hpp>
#include <cx/std.hpp>
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

View File

@ -1,7 +1,7 @@
#include <cx/io/print.hpp> #include <cx/io/print.hpp>
#include <string.h> #include <string.h>
#include <cx/logger.hpp> #include <cx/logger.hpp>
#include <cx/libc.hpp>
using namespace log; using namespace log;
#define C_RS "\x1b[0m" #define C_RS "\x1b[0m"
@ -19,10 +19,8 @@ using namespace log;
#define C_UL "\x1b[4m" #define C_UL "\x1b[4m"
#define C_BLINK "\x1b[5m" #define C_BLINK "\x1b[5m"
extern "C" char* getenv(const char* name);
Logger::Logger() { Logger::Logger() {
char* val = getenv("CPLUS_LOG"); char* val = libc::getenv("CPLUS_LOG");
if (val != NULL) { if (val != NULL) {
if (strcmp(val, "OFF") == 0) { if (strcmp(val, "OFF") == 0) {
this->set_log_level(LOG_OFF); 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 // clang-format off
if (val != NULL) { if (val != NULL) {
if ( if (

View File

@ -50,3 +50,28 @@ String String::clone() {
s._chars = this->_chars.clone(); s._chars = this->_chars.clone();
return s; 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]);
}
}