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_END 1
|
||||||
#define SEEK_SET 2
|
#define SEEK_SET 2
|
||||||
|
|
||||||
// Standard file pointers
|
/* The FILE struct */
|
||||||
#define STDIN_FILENO 0
|
|
||||||
#define STDOUT_FILENO 1
|
|
||||||
#define STDERR_FILENO 2
|
|
||||||
|
|
||||||
/* The ultimate FILE struct */
|
|
||||||
typedef struct _iobuf { // 24B
|
typedef struct _iobuf { // 24B
|
||||||
unsigned char* _ptr; // File buffer base
|
unsigned char* _ptr; // File buffer base
|
||||||
unsigned int _size; // Size of buffer
|
unsigned int _size; // Size of buffer
|
||||||
@@ -33,6 +28,7 @@ typedef struct _iobuf { // 24B
|
|||||||
char __reserved[6];
|
char __reserved[6];
|
||||||
} FILE;
|
} FILE;
|
||||||
|
|
||||||
|
// Standard file pointers
|
||||||
extern FILE* stdin;
|
extern FILE* stdin;
|
||||||
extern FILE* stdout;
|
extern FILE* stdout;
|
||||||
extern FILE* stderr;
|
extern FILE* stderr;
|
||||||
@@ -59,20 +55,23 @@ char* fgets(char* str, int n, FILE* stream);
|
|||||||
int fputs(const char* str, FILE* stream);
|
int fputs(const char* str, FILE* stream);
|
||||||
int puts(const char* str);
|
int puts(const char* str);
|
||||||
|
|
||||||
/* Error handling */
|
/* TODO: Error handling
|
||||||
void perror(const char* s);
|
void perror(const char* s);
|
||||||
int feof(FILE* stream);
|
int feof(FILE* stream);
|
||||||
int ferror(FILE* stream);
|
int ferror(FILE* stream);
|
||||||
void clearerr(FILE* stream);
|
void clearerr(FILE* stream);
|
||||||
|
*/
|
||||||
|
|
||||||
/* Formatted I/O */
|
/* Formatted I/O */
|
||||||
int printf(const char* fmt, ...);
|
int printf(const char* fmt, ...);
|
||||||
int vprintf(const char* fmt, va_list va);
|
int vprintf(const char* fmt, va_list va);
|
||||||
int fprintf(FILE* stream, const char* fmt, ...);
|
int fprintf(FILE* stream, const char* fmt, ...);
|
||||||
int vfprintf(FILE* stream, const char* fmt, va_list va);
|
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 snprintf(char* str, size_t size, const char* fmt, ...);
|
||||||
int vsnprintf(char* str, size_t size, const char* fmt, va_list va);
|
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 scanf(const char* fmt, ...);
|
||||||
int vscanf(const char* fmt, va_list va);
|
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