29 changed files with 44 additions and 986 deletions
@ -1,14 +0,0 @@ |
|||
#include "../klib/sprintf.h" |
|||
#include "assert.h" |
|||
#include "panic.h" |
|||
|
|||
|
|||
void __assert(const char* __restrict__ expression, |
|||
const char* __restrict__ file, |
|||
const int line) { |
|||
char buffer[1024]; |
|||
|
|||
sprintf(buffer, "%s:%d: assertion '%s' failed", file, line, expression); |
|||
|
|||
panic(buffer); |
|||
} |
@ -1,20 +0,0 @@ |
|||
#pragma once |
|||
|
|||
|
|||
#ifndef NDEBUG |
|||
void __assert(const char* __restrict__ expression, |
|||
const char* __restrict__ file, |
|||
const int line); |
|||
|
|||
#define assert(EX) (void)((EX) || (__assert (#EX, __FILE__, __LINE__),0)) |
|||
|
|||
#define assert_aligned(ADDR, ALIGNMENT) assert(((uint64_t)ADDR & (ALIGNMENT-1)) == 0) |
|||
#else |
|||
#define assert(EX) |
|||
#endif |
|||
|
|||
#define static_assert(EX) _Static_assert(EX, #EX) |
|||
|
|||
#define static_assert_equals(EX1,EX2) _Static_assert(EX1==EX2, #EX1 " != " #EX2) |
|||
|
|||
|
@ -1,100 +0,0 @@ |
|||
#include "dump.h" |
|||
#include "../klib/sprintf.h" |
|||
|
|||
void dump(const void* addr, size_t size, size_t line_size, uint8_t mode) { |
|||
|
|||
char row_fmt[16], last_row_fmt[16]; |
|||
|
|||
size_t pitch; // sizeof word
|
|||
|
|||
int i = 0; |
|||
row_fmt [i] = '%'; |
|||
last_row_fmt[i] = '%'; |
|||
i++; |
|||
|
|||
|
|||
// create fmts for printf
|
|||
|
|||
// word width
|
|||
if((mode & DUMP_8) != 0) { |
|||
// byte mode
|
|||
|
|||
row_fmt [i] = '2'; |
|||
last_row_fmt[i] = '2'; |
|||
i++; |
|||
|
|||
pitch = 1; |
|||
} |
|||
else if((mode & DUMP_64) == 0) { |
|||
// normal 32bit mode
|
|||
|
|||
row_fmt [i] = '8'; |
|||
last_row_fmt[i] = '8'; |
|||
i++; |
|||
|
|||
pitch = 4; |
|||
} |
|||
else { |
|||
// long mode
|
|||
row_fmt [i] = 'l'; |
|||
last_row_fmt[i] = 'l'; |
|||
i++; |
|||
row_fmt [i] = '1'; |
|||
last_row_fmt[i] = '1'; |
|||
i++; |
|||
row_fmt [i] = '6'; |
|||
last_row_fmt[i] = '6'; |
|||
i++; |
|||
|
|||
pitch = 8; |
|||
} |
|||
|
|||
// base
|
|||
char base_id; |
|||
|
|||
|
|||
if((mode & DUMP_HEX) == 0) // hex
|
|||
base_id = 'x'; |
|||
else // dec
|
|||
base_id = 'u'; |
|||
|
|||
row_fmt [i] = base_id; |
|||
last_row_fmt[i] = base_id; |
|||
i++; |
|||
|
|||
row_fmt [i] = ' '; |
|||
last_row_fmt[i] = '\n'; |
|||
i++; |
|||
|
|||
row_fmt [i] = '\0'; |
|||
last_row_fmt[i] = '\0'; |
|||
i++; |
|||
|
|||
|
|||
|
|||
size /= pitch; |
|||
size_t lines = (size + line_size - 1) / line_size; |
|||
|
|||
// iterator ptr
|
|||
const uint8_t* ptr = addr; |
|||
|
|||
// create mask : create the complementary with 0xff...ff << n
|
|||
// then complement it
|
|||
const uint64_t mask = ~(~0llu << 8*pitch); |
|||
|
|||
for(size_t i = 0; i < lines; i++) { |
|||
// the last line might not be full
|
|||
// therefore we have to check each one
|
|||
|
|||
for(size_t j = 0; j < line_size-1; j++) { |
|||
if(size-- <= 1) |
|||
break; |
|||
else { |
|||
kprintf(row_fmt, *(uint64_t *)ptr & mask); |
|||
ptr+=pitch; |
|||
} |
|||
} |
|||
kprintf(last_row_fmt, *(uint64_t *)ptr & mask); |
|||
ptr+=pitch; |
|||
} |
|||
} |
@ -1,38 +0,0 @@ |
|||
#pragma once |
|||
|
|||
#include <stddef.h> |
|||
#include <stdint.h> |
|||
|
|||
|
|||
|
|||
#define DUMP_HEX 0 |
|||
#define DUMP_DEC 16 |
|||
|
|||
#define DUMP_8 32 |
|||
#define DUMP_32 0 |
|||
#define DUMP_64 1 |
|||
|
|||
#define DUMP_HEX8 (DUMP_HEX | DUMP_8) |
|||
#define DUMP_HEX32 (DUMP_HEX | DUMP_32) |
|||
#define DUMP_HEX64 (DUMP_HEX | DUMP_64) |
|||
#define DUMP_DEC8 (DUMP_DEC | DUMP_8) |
|||
#define DUMP_DEC32 (DUMP_DEC | DUMP_32) |
|||
#define DUMP_DEC64 (DUMP_DEC | DUMP_64) |
|||
|
|||
|
|||
/**
|
|||
* dump a memory chunk in kprintf |
|||
* addr: address of the beginning of the chunk |
|||
* size: number of bytes to dump |
|||
* line_size: number of words per line |
|||
* |
|||
* mode: either |
|||
* DUMP_HEX8 : hexadecimal integers of size 8 bits |
|||
* DUMP_HEX32 : hexadecimal integers of size 32 bits |
|||
* DUMP_HEX64 : hexadecimal integers of size 64 bits |
|||
* DUMP_DEC8 : decimal integers of size 8 bits |
|||
* DUMP_DEC32 : decimal integers of size 32 bits |
|||
* DUMP_DEC64 : decimal integers of size 64 bits |
|||
* |
|||
**/ |
|||
void dump(const void* addr, size_t size, size_t line_size, uint8_t mode); |
@ -1,99 +0,0 @@ |
|||
#include <stdarg.h> |
|||
|
|||
#include "../klib/sprintf.h" |
|||
#include "logging.h" |
|||
#include "../video/terminal.h" |
|||
|
|||
#include "../klib/string.h" |
|||
|
|||
#define TEXT_COLOR 0xfff0a0 |
|||
|
|||
#define BUFFER_SIZE 4096 |
|||
|
|||
static char logs_buffer[BUFFER_SIZE]; |
|||
static unsigned current_level; |
|||
// current position in the buffer
|
|||
static int i = 0; |
|||
|
|||
// appends a string to the buffer
|
|||
// if there is enough space remaining.
|
|||
// else, leave it as is
|
|||
static inline void append_string(const char* str) { |
|||
|
|||
unsigned len = strlen(str); |
|||
if(i+len >= BUFFER_SIZE) |
|||
klog_flush(); |
|||
memcpy(logs_buffer+i, str, len); |
|||
i += len; |
|||
} |
|||
|
|||
static const char* get_level_names_and_set_terminal_color(unsigned level) { |
|||
switch(level) { |
|||
case LOG_LEVEL_DEBUG: |
|||
set_terminal_fgcolor(LOG_DEBUG_COLOR); |
|||
return "[DEBUG] "; |
|||
case LOG_LEVEL_INFO: |
|||
set_terminal_fgcolor(LOG_INFO_COLOR); |
|||
return "[INFO] "; |
|||
|
|||
default:// level > warning -> warning.
|
|||
case LOG_LEVEL_WARNING: |
|||
set_terminal_fgcolor(LOG_WARNIN_COLOR); |
|||
return "[WARNING] "; |
|||
} |
|||
} |
|||
|
|||
void klog(unsigned level, const char* string) { |
|||
if(level < current_level) |
|||
return; // avoid overflows
|
|||
|
|||
const char* level_name = get_level_names_and_set_terminal_color(level); |
|||
|
|||
|
|||
// print on the screen
|
|||
// with fancy colors
|
|||
kputs(level_name); |
|||
set_terminal_fgcolor(TEXT_COLOR); |
|||
|
|||
kputs(string); |
|||
kputs("\n"); |
|||
|
|||
// append to the buffer
|
|||
append_string(level_name); |
|||
append_string(string); |
|||
append_string("\n"); |
|||
} |
|||
|
|||
|
|||
|
|||
void klogf(unsigned level, const char* fmt, ...) { |
|||
if(level < current_level) |
|||
return; |
|||
|
|||
char string[1024]; |
|||
|
|||
// render string buffer
|
|||
va_list ap; |
|||
va_start(ap, fmt); |
|||
vsprintf(string, fmt, ap); |
|||
va_end(ap); |
|||
|
|||
klog(level, string); |
|||
|
|||
} |
|||
|
|||
void set_logging_level(unsigned level) { |
|||
current_level = level; |
|||
} |
|||
|
|||
|
|||
const char* klog_get(void) { |
|||
logs_buffer[i] = 0; |
|||
return logs_buffer; |
|||
} |
|||
|
|||
void klog_flush(void) { |
|||
i = 0; |
|||
} |
|||
|
|||
|
@ -1,35 +0,0 @@ |
|||
#pragma once |
|||
|
|||
|
|||
|
|||
#define NUMARGS(...) (sizeof((int[]){__VA_ARGS__})/sizeof(int)) |
|||
|
|||
|
|||
#define LOG_LEVEL_DEBUG 1 |
|||
#define LOG_LEVEL_INFO 2 |
|||
#define LOG_LEVEL_WARNING 3 |
|||
|
|||
#define LOG_DEBUG_COLOR 0x909090 |
|||
#define LOG_INFO_COLOR 0xc0c0c0 |
|||
#define LOG_WARNIN_COLOR 0xffff00 |
|||
|
|||
|
|||
#ifndef NDEBUG |
|||
#define klog_debug(...) klogf(LOG_LEVEL_DEBUG, __VA_ARGS__) |
|||
#else |
|||
#define klog_debug(...) |
|||
#endif |
|||
|
|||
#define klog_info(...) klogf(LOG_LEVEL_INFO, __VA_ARGS__) |
|||
#define klog_warn(...) klogf(LOG_LEVEL_WARN, __VA_ARGS__) |
|||
|
|||
void klog(unsigned level, const char* string); |
|||
|
|||
// behaves like kprintf
|
|||
void klogf(unsigned level, const char* fmt, ...); |
|||
|
|||
void set_logging_level(unsigned level); |
|||
|
|||
const char* klog_get(void); |
|||
|
|||
void klog_flush(void); |
@ -1,55 +0,0 @@ |
|||
#include "panic.h" |
|||
#include "../klib/sprintf.h" |
|||
#include "../video/terminal.h" |
|||
|
|||
|
|||
int zero = 0; |
|||
|
|||
#define MAX_STACK_TRACE 15 |
|||
|
|||
extern uint64_t _rbp(void); |
|||
|
|||
// always inline: make sure
|
|||
static inline __attribute__((always_inline)) void stack_trace(void) { |
|||
void** ptr = (void**)_rbp(); |
|||
kputs("backtrace:\n"); |
|||
|
|||
for(unsigned i = 0; i < MAX_STACK_TRACE; i++) { |
|||
|
|||
if(*ptr == 0) // reached the top
|
|||
break; |
|||
kprintf("\t%llx \n", *(ptr+1)); |
|||
|
|||
ptr = *ptr; |
|||
} |
|||
} |
|||
|
|||
__attribute__((noreturn)) void panic(const char* panic_string) { |
|||
// checks if video is operationnal
|
|||
if(get_terminal_handler() != NULL) { |
|||
terminal_set_colors(0xfff0a0, 0x400000); |
|||
|
|||
if(panic_string == NULL) |
|||
panic_string = "(null)"; |
|||
|
|||
kputs( |
|||
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" |
|||
"!!!!!!!!!!!!! KERNL PANIC !!!!!!!!!!!!!\n" |
|||
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); |
|||
|
|||
kputs(panic_string); |
|||
kputs("\n\n"); |
|||
|
|||
stack_trace(); |
|||
|
|||
kputs( |
|||
"\n\n" |
|||
"you may manually shutdown the machine.\n" |
|||
); |
|||
} |
|||
|
|||
asm volatile("cli"); |
|||
asm volatile("hlt"); |
|||
|
|||
__builtin_unreachable(); |
|||
} |
@ -1,10 +0,0 @@ |
|||
#pragma once |
|||
|
|||
|
|||
/**
|
|||
* panic_string can be NULL |
|||
* |
|||
* doesn't return: freezes |
|||
* dumps the registers and print debug infos |
|||
*/ |
|||
__attribute__((noreturn)) void panic(const char* panic_string); |
@ -1,4 +0,0 @@ |
|||
test: |
|||
del -f a.exe |
|||
gcc test.c sprintf.c string.c |
|||
a.exe |
@ -1,6 +0,0 @@ |
|||
#pragma once |
|||
|
|||
#define MIN(X,Y) (X > Y ? Y : X) |
|||
#define MAX(X,Y) (X < Y ? Y : X) |
|||
|
|||
#define CEIL_DIV(X, Y) ((X + Y - 1) / Y) |
@ -1,227 +0,0 @@ |
|||
#include "sprintf.h" |
|||
#include "math.h" |
|||
#include "string.h" |
|||
#include "../video/terminal.h" |
|||
|
|||
#define SIGN(X) X > 0 ? 1 : -1 |
|||
#define ARG(TYPE) (TYPE)va_arg(ap, TYPE) |
|||
|
|||
static char* utohex(char* str, uint64_t x, int min_digits) { |
|||
size_t digits = 1; |
|||
|
|||
uint64_t _x = x; |
|||
|
|||
// _x < 0xf
|
|||
while(_x & ~0xf) { |
|||
_x >>= 4; |
|||
digits++; |
|||
} |
|||
|
|||
if((int)digits < min_digits) |
|||
digits = min_digits; |
|||
|
|||
char* end = str+digits; |
|||
|
|||
char* ptr = end; |
|||
|
|||
for(int i = digits;i>0;i--) { |
|||
int d = x & 0x0f; |
|||
if(d < 0xa) |
|||
d += '0'; |
|||
else |
|||
d += 'a'-10; |
|||
*(--ptr) = d; |
|||
|
|||
x >>= 4; |
|||
} |
|||
|
|||
|
|||
*end = '\0'; |
|||
return end; |
|||
} |
|||
|
|||
// unsigned to string
|
|||
// return a ptr to the end of the string
|
|||
static char* utos(char* str, uint64_t x, int min_digits) { |
|||
size_t digits = 1; |
|||
|
|||
uint64_t _x = x; |
|||
while(_x > 9) { |
|||
_x /= 10; |
|||
digits++; |
|||
} |
|||
|
|||
if((int)digits < min_digits) |
|||
digits = min_digits; |
|||
|
|||
char* end = str+digits; |
|||
|
|||
char* ptr = end; |
|||
for(int i = digits;i>0;i--) { |
|||
*(--ptr) = '0' + x%10; |
|||
|
|||
x /= 10; |
|||
} |
|||
*end = '\0'; |
|||
|
|||
|
|||
return end; |
|||
} |
|||
|
|||
// signed to string
|
|||
static char* itos(char* str, int64_t x, int min_digits) { |
|||
if(x < 0) { |
|||
*(str++) = '-'; |
|||
x *= -1; |
|||
} |
|||
|
|||
return utos(str, x, min_digits); |
|||
} |
|||
|
|||
|
|||
int vsprintf(char *str, const char *format, va_list ap) { |
|||
char cf; |
|||
int args_put = 0; |
|||
int persent = 0; |
|||
int digits = -1; |
|||
|
|||
// bool value: '%l..'
|
|||
int _long = 0; |
|||
|
|||
while(1) { |
|||
cf = *(format++); |
|||
if(cf == '\0') |
|||
break; |
|||
|
|||
if(persent) { |
|||
if(cf == '.') |
|||
continue; |
|||
else if(cf == 'l') { |
|||
_long = 1; |
|||
continue; |
|||
} |
|||
|
|||
int i = cf - '0'; |
|||
if(i >= 0 && i <= 9) { |
|||
if(digits < 0) |
|||
digits = 0; |
|||
digits = 10 * digits + i; |
|||
} |
|||
else { |
|||
switch(cf) { |
|||
default: |
|||
// invalid
|
|||
break; |
|||
case 'u': |
|||
if(!_long) |
|||
str = utos(str, ARG(uint32_t), digits); |
|||
else |
|||
str = utos(str, ARG(uint64_t), digits); |
|||
break; |
|||
case 'd': |
|||
case 'i': |
|||
if(!_long) |
|||
str = itos(str, ARG(int32_t), digits); |
|||
else |
|||
str = itos(str, ARG(int64_t), digits); |
|||
break; |
|||
case 'h': |
|||
case 'x': |
|||
if(!_long) |
|||
str = utohex(str, ARG(uint32_t), digits); |
|||
else |
|||
str = utohex(str, ARG(uint64_t), digits); |
|||
break; |
|||
case 's': |
|||
{ |
|||
const char* arg = ARG(const char*); |
|||
if(digits >= 0) { |
|||
strncpy(str, arg, digits); |
|||
if((int) strlen(arg) < digits) |
|||
str += strlen(arg); |
|||
else |
|||
str += digits; |
|||
} |
|||
else { |
|||
strcpy(str, arg); |
|||
str += strlen(arg); |
|||
} |
|||
} |
|||
break; |
|||
case 'c': |
|||
*(str++) = (char)ARG(int); |
|||
break; |
|||
} |
|||
digits = -1; |
|||
persent = 0; |
|||
_long = 0; |
|||
args_put++; |
|||
} |
|||
} |
|||
|
|||
else if(cf == '%') { |
|||
if(persent) { |
|||
// allow %% in fmt to print '%'
|
|||
persent = 0; |
|||
*(str++) = '%'; |
|||
} |
|||
persent = 1; |
|||
} |
|||
else { |
|||
*(str++) = cf; |
|||
} |
|||
} |
|||
|
|||
*str = '\0'; |
|||
return args_put; |
|||
} |
|||
|
|||
|
|||
int sprintf(char* str, const char* format, ...) { |
|||
va_list ap; |
|||
int res; |
|||
|
|||
va_start(ap, format); |
|||
res = vsprintf(str,format,ap); |
|||
va_end(ap); |
|||
|
|||
return res; |
|||
} |
|||
//
|
|||
//int vsnprintf(char *str, size_t size, const char *format, va_list ap) {
|
|||
//
|
|||
//
|
|||
//}
|
|||
|
|||
void kputs(const char* s) { |
|||
terminal_handler_t print_fun = get_terminal_handler(); |
|||
|
|||
if(print_fun) |
|||
print_fun(s, strlen(s)); |
|||
} |
|||
|
|||
int kprintf(const char* format, ...) { |
|||
va_list ap; |
|||
int ret; |
|||
|
|||
va_start(ap, format); |
|||
|
|||
ret = vkprintf(format, ap); |
|||
|
|||
|
|||
va_end(ap); |
|||
|
|||
return ret; |
|||
} |
|||
|
|||
int vkprintf(const char* format, va_list ap) { |
|||
terminal_handler_t print_fun = get_terminal_handler(); |
|||
|
|||
char buf[1024]; |
|||
|
|||
int ret = vsprintf(buf, format, ap); |
|||
|
|||
print_fun(buf, strlen(buf)); |
|||
|
|||
return ret; |
|||
} |
@ -1,20 +0,0 @@ |
|||
#ifndef SPRINTF_H |
|||
#define SPRINTF_H |
|||
|
|||
|
|||
#include <stdint.h> |
|||
#include <stddef.h> |
|||
#include <stdarg.h> |
|||
|
|||
|
|||
int sprintf(char *str, const char *format, ...); |
|||
int snprintf(char *str, size_t size, const char *format, ...); |
|||
int vsprintf(char *str, const char *format, va_list ap); |
|||
int vsnprintf(char *str, size_t size, const char *format, va_list ap); |
|||
|
|||
int vkprintf(const char* format, va_list ap); |
|||
int kprintf(const char* format, ...); |
|||
|
|||
void kputs(const char* s); |
|||
|
|||
#endif |
@ -1,273 +0,0 @@ |
|||
#include "string.h" |
|||
|
|||
|
|||
size_t strlen(const char* str) { |
|||
const char* ptr = str; |
|||
|
|||
int len = 0; |
|||
|
|||
while(*(ptr++) != '\0') |
|||
len++; |
|||
|
|||
return len; |
|||
} |
|||
|
|||
|
|||
size_t strnlen(const char* str, size_t n) { |
|||
int len = 0; |
|||
|
|||
while(*(str++) != '\0' && n--) |
|||
len++; |
|||
|
|||
return len; |
|||
} |
|||
|
|||
char* strcpy(char* dst, const char* src) { |
|||
char c; |
|||
char* pdst = dst; |
|||
|
|||
do { |
|||
c = *(src++); |
|||
|
|||
*(pdst++) = c; |
|||
} |
|||
while(c != '\0'); |
|||
|
|||
return dst; |
|||
} |
|||
|
|||
char* strncpy(char* dst, const char* src, size_t n) { |
|||
char c; |
|||
char* pdst = dst; |
|||
|
|||
do { |
|||
c = *(src++); |
|||
|
|||
*(pdst++) = c; |
|||
|
|||
n--; |
|||
} |
|||
while(c != '\0' && n > 0); |
|||
|
|||
if(c != '\0') |
|||
*pdst = '\0'; |
|||
dst = '\0'; |
|||
return dst; |
|||
} |
|||
|
|||
|
|||
int strcmp(const char* str1, const char* str2) { |
|||
int d; |
|||
|
|||
while(1) { |
|||
char c1 = *(str1++); |
|||
char c2 = *(str2++); |
|||
|
|||
d = c1-c2; |
|||
|
|||
if(!c1 || !c2 || d) |
|||
break; |
|||
} |
|||
|
|||
return d; |
|||
} |
|||
|
|||
int strncmp(const char* str1, const char* str2, size_t n) { |
|||
int d; |
|||
|
|||
while(n-- > 0) { |
|||
char c1 = *(str1++); |
|||
char c2 = *(str2++); |
|||
|
|||
d = c1-c2; |
|||
|
|||
if(!c1 || !c2 || d) |
|||
break; |
|||
} |
|||
|
|||
return d; |
|||
} |
|||
|
|||
|
|||
const char* strchr (const char *_s, int c) { |
|||
const char* s=_s; |
|||
char curr; |
|||
|
|||
while(1) { |
|||
curr = *s; |
|||
|
|||
if(curr == c) |
|||
return s; |
|||
else if(curr == '\0') |
|||
break; |
|||
|
|||
s++; |
|||
} |
|||
|
|||
return NULL; |
|||
} |
|||
|
|||
|
|||
const char* strrchr(const char *s, int c) { |
|||
char curr; |
|||
|
|||
const char* found = NULL; |
|||
|
|||
while(1) { |
|||
curr = *s; |
|||
|
|||
if(curr == c) |
|||
found = s; |
|||
else if(curr == '\0') |
|||
break; |
|||
|
|||
s++; |
|||
} |
|||
|
|||
return found; |
|||
} |
|||
|
|||
|
|||
const char *strstr(const char *haystack, const char *needle) { |
|||
|
|||
int i = 0; |
|||
char c, ci; |
|||
|
|||
while(1) { |
|||
|
|||
ci = needle[i]; |
|||
|
|||
if(ci == '\0') |
|||
return haystack - i - 1; |
|||
|
|||
|
|||
c = *(haystack++); |
|||
|
|||
if(c == ci) |
|||
i++; |
|||
else if(c == '\0') |
|||
return NULL; |
|||
else |
|||
i = 0; |
|||
} |
|||
} |
|||
|
|||
|
|||
char* strcat(char *dest, const char *src) { |
|||
while(*(dest++)) ; |
|||
|
|||
return strcpy(dest, src); |
|||
} |
|||
|
|||
char *strncat(char *dest, const char *src, size_t n) { |
|||
char* ret = dest; |
|||
|
|||
while(*(dest++)) ; |
|||
strncpy(--dest, src, n); |
|||
|
|||
return ret; |
|||
} |
|||
|
|||
|
|||
void * memccpy (void* dst, const void *src, int c, size_t n) { |
|||
|
|||
|
|||
for(; n > 0; n--) { |
|||
char d = *(char*)(src++) = *(char*)(dst++); |
|||
|
|||
if(d == c) |
|||
return dst; |
|||
} |
|||
|
|||
return NULL; |
|||
} |
|||
|
|||
const void* memchr (const void *_buf, int _ch, size_t n) { |
|||
uint8_t ch = *(uint8_t*)(&_ch); |
|||
const uint8_t* buf=_buf; |
|||
|
|||
for(;n > 0; n--) { |
|||
if(*buf == ch) |
|||
return buf; |
|||
buf++; |
|||
} |
|||
return NULL; |
|||
} |
|||
|
|||
int memcmp (const void* _buf1, const void* _buf2, size_t n) { |
|||
const uint8_t* buf1=_buf1; |
|||
const uint8_t* buf2=_buf2; |
|||
|
|||
for(; n > 0; n--) { |
|||
int d = *(buf1++) - *(buf2++); |
|||
|
|||
if(d != 0) |
|||
return d; |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
void * memcpy (void* restrict _dest, |
|||
const void* restrict _src, size_t n) { |
|||
const uint8_t* src=_src; |
|||
uint8_t* dest=_dest; |
|||
|
|||
for(;n > 0; --n) |
|||
*(dest++) = *(src++); |
|||
|
|||
return dest; |
|||
} |
|||
|
|||
void * memset (void * _buf, int _ch, size_t n) { |
|||
uint8_t ch = *(uint8_t*)(&_ch); |
|||
uint8_t* buf = _buf; |
|||
|
|||
// first unaligned bytes
|
|||
for(;n > 0 && (uint64_t)buf % 8 != 0; --n) |
|||
*(buf++) = ch; |
|||
|
|||
|
|||
if(!n) return buf; |
|||
|
|||
if(n >= 8) { |
|||
uint64_t ch64 = ch | (ch << 8); |
|||
ch64 = ch64 | (ch64 << 16); |
|||
ch64 = ch64 | (ch64 << 32); |
|||
|
|||
for(;n > 0; n -= 8) { |
|||
*(uint64_t*)buf = ch64; |
|||
buf += 8; |
|||
} |
|||
} |
|||
|
|||
// last unaligned bytes
|
|||
for(;n > 0 && (uint64_t)buf % 8 != 0; --n) |
|||
*(buf++) = ch; |
|||
|
|||
return buf; |
|||
} |
|||
|
|||
|
|||
void * memmove (void* _dest, const void* _src, size_t n) { |
|||
uint8_t* dest=_dest; |
|||
const uint8_t* src=_src; |
|||
|
|||
// check for overlapping
|
|||
if(src < dest && src + n > dest) { |
|||
dest += n; |
|||
src += n; |
|||
|
|||
|
|||
// backward copy
|
|||
for(;n > 0; --n) |
|||
*(--dest) = *(--src); |
|||
|
|||
return _dest; |
|||
} |
|||
// not overlapping: just call memcpy
|
|||
else { |
|||
return memcpy(dest, src, n); |
|||
} |
|||
} |
@ -1,41 +0,0 @@ |
|||
#ifndef KSTRING_H |
|||
#define KSTRING_H |
|||
|
|||
#include <stdint.h> |
|||
#include <stddef.h> |
|||
|
|||
|
|||
#ifndef __ATTR_PURE__ |
|||
#define __ATTR_PURE__ __attribute__((__pure__)) |
|||
#endif |
|||
|
|||
|
|||
void * memccpy (void * __restrict__, const void * __restrict__, int, size_t); |
|||
const void * memchr (const void *, int, size_t) __ATTR_PURE__; |
|||
int memcmp (const void *, const void *, size_t) __ATTR_PURE__; |
|||
void * memcpy (void * __restrict__, const void * __restrict__, size_t); |
|||
void * memset (void *, int, size_t); |
|||
//void * memmem (const void *, size_t, const void *, size_t) __ATTR_PURE__;
|
|||
void * memmove (void *, const void *, size_t); |
|||
//void * memrchr (const void *, int, size_t) __ATTR_PURE__;
|
|||
|
|||
|
|||
|
|||
size_t strlen (const char* str) __ATTR_PURE__; |
|||
size_t strnlen(const char* str, size_t n) __ATTR_PURE__; |
|||
int strcmp (const char* str1, const char* str2) __ATTR_PURE__; |
|||
int strncmp(const char* str1, const char* str2, size_t n) __ATTR_PURE__; |
|||
const char* strchr (const char *s, int c) __ATTR_PURE__; |
|||
const char* strrchr(const char *s, int c) __ATTR_PURE__; |
|||
const char* strstr(const char *haystack, const char *needle) __ATTR_PURE__; |
|||
|
|||
|
|||
char* strcpy (char* __restrict__ dst, const char* __restrict__ src); |
|||
char* strncpy(char* __restrict__ dst, const char* __restrict__ src, size_t n); |
|||
char* strcat(char * __restrict__ dest, const char * __restrict__ src); |
|||
char* strncat(char * __restrict__ dest, const char * __restrict__ src, size_t n); |
|||
|
|||
|
|||
|
|||
|
|||
#endif//KSTRING_H
|
Loading…
Reference in new issue