forked from PoliEcho-holding-org/kern
Almost finished stdio.h
This commit is contained in:
@@ -17,12 +17,7 @@
|
||||
#define SEEK_END 1
|
||||
#define SEEK_SET 2
|
||||
|
||||
// Standard file pointers
|
||||
#define STDIN_FILENO 0
|
||||
#define STDOUT_FILENO 1
|
||||
#define STDERR_FILENO 2
|
||||
|
||||
/* The ultimate FILE struct */
|
||||
/* The FILE struct */
|
||||
typedef struct _iobuf { // 24B
|
||||
unsigned char* _ptr; // File buffer base
|
||||
unsigned int _size; // Size of buffer
|
||||
@@ -33,6 +28,7 @@ typedef struct _iobuf { // 24B
|
||||
char __reserved[6];
|
||||
} FILE;
|
||||
|
||||
// Standard file pointers
|
||||
extern FILE* stdin;
|
||||
extern FILE* stdout;
|
||||
extern FILE* stderr;
|
||||
@@ -59,20 +55,23 @@ char* fgets(char* str, int n, FILE* stream);
|
||||
int fputs(const char* str, FILE* stream);
|
||||
int puts(const char* str);
|
||||
|
||||
/* Error handling */
|
||||
/* TODO: Error handling
|
||||
void perror(const char* s);
|
||||
int feof(FILE* stream);
|
||||
int ferror(FILE* stream);
|
||||
void clearerr(FILE* stream);
|
||||
*/
|
||||
|
||||
/* Formatted I/O */
|
||||
int printf(const char* fmt, ...);
|
||||
int vprintf(const char* fmt, va_list va);
|
||||
int fprintf(FILE* stream, const char* fmt, ...);
|
||||
int vfprintf(FILE* stream, const char* fmt, va_list va);
|
||||
// INFO: (v)sprinf() Has been depricated and removed as it is unsafe (potencial buffer overflow). Please use (v)snprintf()
|
||||
// NOTE: (v)sprinf() Has been depricated and removed as it is unsafe (potencial buffer overflow). Please use (v)snprintf()
|
||||
int snprintf(char* str, size_t size, const char* fmt, ...);
|
||||
int vsnprintf(char* str, size_t size, const char* fmt, va_list va);
|
||||
int vpprintf(void (*outfn)(char c, void* arg), void* arg, const char* fmt, ...)
|
||||
int vpprintf(void (*outfn)(char c, void* arg), void* arg, const char* fmt, va_list va)
|
||||
|
||||
int scanf(const char* fmt, ...);
|
||||
int vscanf(const char* fmt, va_list va);
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#include <stdio.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int getchar(void) { return getc(stdin); }
|
||||
int putchar(int c) { return putc(stdout); }
|
||||
|
||||
int getc(FILE* stream) {
|
||||
if (!stream) { return EOF; }
|
||||
|
||||
unsigned char ch;
|
||||
ssize_t res = read(stream->_file, &ch, 1);
|
||||
if (res <= 0) { return EOF; }
|
||||
|
||||
return (int)ch;
|
||||
}
|
||||
|
||||
int putc(int c, FILE* stream) {
|
||||
if (!stream) { return EOF; }
|
||||
|
||||
unsigned char ch = (unsigned char)c;
|
||||
ssize_t res = write(stream->_file, &c, 1);
|
||||
if (res <= 0) { return EOF; }
|
||||
|
||||
return (int)ch;
|
||||
}
|
||||
|
||||
// TODO:
|
||||
int ungetc(int c, FILE* stream) { return EOF; }
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
#include <stdio.h>
|
||||
#include <syscall.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
FILE* fopen(const char* path, const char* mode) {
|
||||
FILE* fp = (FILE*)malloc(sizeof(FILE));
|
||||
if (!fp) { return NULL; }
|
||||
|
||||
int flags = 0;
|
||||
if (strcmp(mode, "r") == 0) { flags = O_RDONLY; }
|
||||
else if (strcmp(mode, "w") == 0) { flags = O_WRONLY | O_CREAT | O_TRUNC; }
|
||||
else if (strcmp(mode, "a") == 0) { flags = O_WRONLY | O_CREAT | O_APPEND; }
|
||||
else if (strcmp(mode, "r+") == 0) { flags = O_RDWR; }
|
||||
else if (strcmp(mode, "w+") == 0) { flags = O_RDWR | O_CREAT | O_TRUNC; }
|
||||
else if (strcmp(mode, "a+") == 0) { flags = O_RDWR | O_CREAT | O_APPEND; }
|
||||
else { // Unsuppored mode
|
||||
free(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int fd = open(path, flags);
|
||||
if (fd == -1) {
|
||||
free(FILE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fp->_file = fd;
|
||||
fp->_ptr = NULL;
|
||||
fp->_size = 0;
|
||||
fp->_offset = 0;
|
||||
fp->_flag = flags;
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
int fclose(FILE* stream) {
|
||||
if (!stream) { return -1; }
|
||||
int ret = close(stream->_file);
|
||||
free(stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t fread(void* ptr, size_t size, size_t count, FILE* stream) {
|
||||
if (!stream || !ptr || size == 0 || count == 0) { return 0; }
|
||||
|
||||
size_t total = size * count;
|
||||
ssize_t read = read(stream->_file, ptr, total);
|
||||
|
||||
if (read < 0) return 0;
|
||||
|
||||
stream->offset += read;
|
||||
return read / size;
|
||||
}
|
||||
|
||||
size_t fwrite(void* ptr, size_t size, size_t count, FILE* stream) {
|
||||
if (!stream || !ptr || size == 0 || count == 0) { return 0; }
|
||||
|
||||
size_t total = size * count;
|
||||
ssize_t written = write(stream->_file, ptr, total);
|
||||
|
||||
if (read < 0) return 0;
|
||||
|
||||
stream->offset += written;
|
||||
return written / size;
|
||||
}
|
||||
|
||||
// TODO
|
||||
int fseek(FILE* stream, long offset, int whence);
|
||||
long ftell(FILE* stream);
|
||||
void rewind(FILE* stream);
|
||||
int fflush(FILE* stream);
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
|
||||
char* fgets(char* str, int n, FILE* stream) {
|
||||
if (!str || !stream || n <= 1) { return NULL; }
|
||||
|
||||
char* dest = str;
|
||||
int ch;
|
||||
|
||||
while (--n > 0 && (ch = getc(stream)) != EOF) {
|
||||
*dest++ = ch;
|
||||
if (ch == '\n') break; // Stop at newline
|
||||
}
|
||||
|
||||
*dest = '\0'; // Null terminate
|
||||
|
||||
return (dest == str) ? NULL : str;
|
||||
}
|
||||
|
||||
int fputs(const char* str, FILE* stream) {
|
||||
if (!str || !stream) { return EOF; }
|
||||
|
||||
while (*str) {
|
||||
if (putc(*str++, stream) == EOF) { return EOF; }
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline char* gets(char* str, int n) { return fgets(str, n, stdin); }
|
||||
inline int puts(const char* str) { return fputs(str, stdout); }
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Internal definitions */
|
||||
typedef struct {
|
||||
int buflen;
|
||||
int offset;
|
||||
char* buf;
|
||||
} printfEnv_t;
|
||||
|
||||
/* Helpers */
|
||||
static void _dynamicPutc(char c, printfEnv_t* env) {
|
||||
if (!env->buf) { return; }
|
||||
|
||||
if (env->offset < env->buflen) {
|
||||
env->buf[env->offset++] = c;
|
||||
} else {
|
||||
env->buflen *= 2;
|
||||
env->buf = realloc(env->buf, env->buflen);
|
||||
|
||||
// If there's not enough memory, we chatch the NULL pointer in the fwrite() call
|
||||
if (!env->buf) { return; }
|
||||
|
||||
env->buf[env->offset++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
static void _staticPutc(char c, printfEnv_t* env) {
|
||||
if (!env->buf) { return; }
|
||||
|
||||
if (env->offset < env->buflen) {
|
||||
env->buf[env->offset] = c;
|
||||
env->offset++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Impementation */
|
||||
int vpprintf(void (*outfn)(char c, void* arg), void* arg, const char* fmt, va_list va) { /* TODO */ }
|
||||
|
||||
int vsnprintf(char* str, size_t size, const char* fmt, va_list va) {
|
||||
printfEnv_t env;
|
||||
env.buflen = size;
|
||||
env.offset = 0;
|
||||
env.buf = str;
|
||||
|
||||
// Format the string
|
||||
int ret = vpprintf(_staticPutc, &env, fmt, va);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vfprintf(FILE* stream, const char* fmt, va_list va) {
|
||||
printfEnv_t env;
|
||||
env.buflen = 128;
|
||||
env.offset = 0;
|
||||
env.buf = malloc(env.buflen);
|
||||
if (!env.buf) { return -1; }
|
||||
|
||||
// Format the string
|
||||
int ret = vpprintf(_dynamicPutc, &env, fmt, va);
|
||||
|
||||
// Write to stream
|
||||
if (fwrite(env.buf, 1, ret, stream) != 1) { return -1; }
|
||||
|
||||
free(env.buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vprintf(const char* fmt, va_list va) { return vfprintf(stdout, fmt, va); }
|
||||
|
||||
// Print using an custom putc function
|
||||
int pprintf(void (*outfn)(char c), const char* fmt, ...) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
int ret = vpprintf(outfn, fmt, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Print to a buffer
|
||||
int snprintf(char* str, size_t size, const char* fmt, ...) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
int ret = vsnprintf(str, size, fmt, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Print to a stream
|
||||
int fprintf(FILE* stream, const char* fmt, ...) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
int ret = vfprintf(stream, fmt, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Print to stdout
|
||||
int printf(const char* fmt, ...) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
int ret = vfprintf(stdout, fmt, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <stdio.h>
|
||||
|
||||
// TODO
|
||||
int scanf(const char* fmt, ...);
|
||||
int vscanf(const char* fmt, va_list va);
|
||||
int fscanf(FILE* stream, const char* fmt, ...);
|
||||
int vfscanf(FILE* stream, const char* fmt, va_list va);
|
||||
int sscanf(const char* str, const char* fmt, ...);
|
||||
int vsscanf(const char* str, const char* fmt, va_list va);
|
||||
|
||||
Reference in New Issue
Block a user