]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
feat: ulibc stdio.h buffered I/O (FILE, fopen/fclose/fread/fwrite/fflush/fgetc/fgets...
authorTulio A M Mendes <[email protected]>
Thu, 12 Feb 2026 03:07:11 +0000 (00:07 -0300)
committerTulio A M Mendes <[email protected]>
Fri, 13 Feb 2026 02:20:50 +0000 (23:20 -0300)
user/ulibc/include/stdio.h
user/ulibc/src/stdio.c

index b1cddf40d1319fb6040ac5943fe6b5d557745ca9..bfeaafd3e12afa53d993bdf22af6c31190f79e54 100644 (file)
@@ -4,6 +4,41 @@
 #include <stddef.h>
 #include <stdarg.h>
 
+#define BUFSIZ      256
+#define EOF         (-1)
+#define FOPEN_MAX   16
+
+#define _STDIO_READ  0x01
+#define _STDIO_WRITE 0x02
+#define _STDIO_EOF   0x04
+#define _STDIO_ERR   0x08
+
+typedef struct _FILE {
+    int     fd;
+    int     flags;
+    char    buf[BUFSIZ];
+    int     buf_pos;
+    int     buf_len;
+} FILE;
+
+extern FILE* stdin;
+extern FILE* stdout;
+extern FILE* stderr;
+
+FILE*   fopen(const char* path, const char* mode);
+int     fclose(FILE* fp);
+size_t  fread(void* ptr, size_t size, size_t nmemb, FILE* fp);
+size_t  fwrite(const void* ptr, size_t size, size_t nmemb, FILE* fp);
+int     fflush(FILE* fp);
+int     fgetc(FILE* fp);
+char*   fgets(char* s, int size, FILE* fp);
+int     fputc(int c, FILE* fp);
+int     fputs(const char* s, FILE* fp);
+int     feof(FILE* fp);
+int     ferror(FILE* fp);
+int     fprintf(FILE* fp, const char* fmt, ...) __attribute__((format(printf, 2, 3)));
+int     vfprintf(FILE* fp, const char* fmt, va_list ap);
+
 int     putchar(int c);
 int     puts(const char* s);
 int     printf(const char* fmt, ...) __attribute__((format(printf, 1, 2)));
index a01bc017a608a43e80ad5e6a29463b68c97cc936..2dbf69f0e090d4ff658c4634edf62e5d2aaadd8c 100644 (file)
@@ -3,6 +3,159 @@
 #include "string.h"
 #include <stdarg.h>
 
+static FILE _stdin_file  = { .fd = 0, .flags = _STDIO_READ };
+static FILE _stdout_file = { .fd = 1, .flags = _STDIO_WRITE };
+static FILE _stderr_file = { .fd = 2, .flags = _STDIO_WRITE };
+
+FILE* stdin  = &_stdin_file;
+FILE* stdout = &_stdout_file;
+FILE* stderr = &_stderr_file;
+
+static FILE _file_pool[FOPEN_MAX];
+static int _file_pool_used[FOPEN_MAX];
+
+FILE* fopen(const char* path, const char* mode) {
+    int flags = 0;
+    int stdio_flags = 0;
+    if (mode[0] == 'r') {
+        flags = 0; /* O_RDONLY */
+        stdio_flags = _STDIO_READ;
+    } else if (mode[0] == 'w') {
+        flags = 1 | 0x40 | 0x200; /* O_WRONLY | O_CREAT | O_TRUNC */
+        stdio_flags = _STDIO_WRITE;
+    } else if (mode[0] == 'a') {
+        flags = 1 | 0x40 | 0x400; /* O_WRONLY | O_CREAT | O_APPEND */
+        stdio_flags = _STDIO_WRITE;
+    } else {
+        return (FILE*)0;
+    }
+    int fd = open(path, flags);
+    if (fd < 0) return (FILE*)0;
+    for (int i = 0; i < FOPEN_MAX; i++) {
+        if (!_file_pool_used[i]) {
+            _file_pool_used[i] = 1;
+            _file_pool[i].fd = fd;
+            _file_pool[i].flags = stdio_flags;
+            _file_pool[i].buf_pos = 0;
+            _file_pool[i].buf_len = 0;
+            return &_file_pool[i];
+        }
+    }
+    close(fd);
+    return (FILE*)0;
+}
+
+int fflush(FILE* fp) {
+    if (!fp) return EOF;
+    if ((fp->flags & _STDIO_WRITE) && fp->buf_pos > 0) {
+        write(fp->fd, fp->buf, (size_t)fp->buf_pos);
+        fp->buf_pos = 0;
+    }
+    return 0;
+}
+
+int fclose(FILE* fp) {
+    if (!fp) return EOF;
+    fflush(fp);
+    int rc = close(fp->fd);
+    for (int i = 0; i < FOPEN_MAX; i++) {
+        if (&_file_pool[i] == fp) { _file_pool_used[i] = 0; break; }
+    }
+    return rc;
+}
+
+size_t fread(void* ptr, size_t size, size_t nmemb, FILE* fp) {
+    if (!fp || !ptr || size == 0 || nmemb == 0) return 0;
+    size_t total = size * nmemb;
+    size_t done = 0;
+    char* dst = (char*)ptr;
+    while (done < total) {
+        if (fp->buf_pos >= fp->buf_len) {
+            int r = read(fp->fd, fp->buf, BUFSIZ);
+            if (r <= 0) { fp->flags |= _STDIO_EOF; break; }
+            fp->buf_pos = 0;
+            fp->buf_len = r;
+        }
+        int avail = fp->buf_len - fp->buf_pos;
+        int want = (int)(total - done);
+        int chunk = avail < want ? avail : want;
+        memcpy(dst + done, fp->buf + fp->buf_pos, (size_t)chunk);
+        fp->buf_pos += chunk;
+        done += (size_t)chunk;
+    }
+    return done / size;
+}
+
+size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* fp) {
+    if (!fp || !ptr || size == 0 || nmemb == 0) return 0;
+    size_t total = size * nmemb;
+    const char* src = (const char*)ptr;
+    size_t done = 0;
+    while (done < total) {
+        int space = BUFSIZ - fp->buf_pos;
+        int want = (int)(total - done);
+        int chunk = space < want ? space : want;
+        memcpy(fp->buf + fp->buf_pos, src + done, (size_t)chunk);
+        fp->buf_pos += chunk;
+        done += (size_t)chunk;
+        if (fp->buf_pos >= BUFSIZ) fflush(fp);
+    }
+    return done / size;
+}
+
+int fgetc(FILE* fp) {
+    unsigned char c;
+    if (fread(&c, 1, 1, fp) != 1) return EOF;
+    return (int)c;
+}
+
+char* fgets(char* s, int size, FILE* fp) {
+    if (!s || size <= 0 || !fp) return (char*)0;
+    int i = 0;
+    while (i < size - 1) {
+        int c = fgetc(fp);
+        if (c == EOF) { if (i == 0) return (char*)0; break; }
+        s[i++] = (char)c;
+        if (c == '\n') break;
+    }
+    s[i] = '\0';
+    return s;
+}
+
+int fputc(int c, FILE* fp) {
+    unsigned char ch = (unsigned char)c;
+    if (fwrite(&ch, 1, 1, fp) != 1) return EOF;
+    return (int)ch;
+}
+
+int fputs(const char* s, FILE* fp) {
+    size_t len = strlen(s);
+    if (fwrite(s, 1, len, fp) != len) return EOF;
+    return 0;
+}
+
+int feof(FILE* fp) { return fp ? (fp->flags & _STDIO_EOF) : 0; }
+int ferror(FILE* fp) { return fp ? (fp->flags & _STDIO_ERR) : 0; }
+
+int vfprintf(FILE* fp, const char* fmt, va_list ap) {
+    char buf[1024];
+    int n = vsnprintf(buf, sizeof(buf), fmt, ap);
+    if (n > 0) {
+        int w = n;
+        if (w > (int)(sizeof(buf) - 1)) w = (int)(sizeof(buf) - 1);
+        fwrite(buf, 1, (size_t)w, fp);
+    }
+    return n;
+}
+
+int fprintf(FILE* fp, const char* fmt, ...) {
+    va_list ap;
+    va_start(ap, fmt);
+    int r = vfprintf(fp, fmt, ap);
+    va_end(ap);
+    return r;
+}
+
 int putchar(int c) {
     char ch = (char)c;
     write(STDOUT_FILENO, &ch, 1);